diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 31c5b11fce..0000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "env": { - "browser": true, - "commonjs": true, - "es2021": true, - "node": true - }, - "extends": "eslint:recommended", - "parserOptions": { - "ecmaVersion": "latest" - }, - "rules": { - "no-var": 2, - "no-case-declarations": 0, - "no-unused-vars": [ - "error", - { - "argsIgnorePattern": "^_", - "caughtErrorsIgnorePattern": "^_", - "vars": "local" - } - ] - } -} diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index f0250567f0..cf22b92771 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -17,6 +17,7 @@ jobs: run: | npm install -g spago npm install -g purescript@0.15.8 + rm -rf package.json # remove package.json so that we are no more in an ESM module. A hack to make 'spago docs' work spago docs - name: Deploy uses: JamesIves/github-pages-deploy-action@v4.3.3 diff --git a/.gitignore b/.gitignore index a8bba0b04d..bfcddf80f7 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ node_modules plutip-server/dist-newstyle/ plutip-server/dist/ plutip-server/.stack-work/ +nixos.qcow2 diff --git a/.mlc_config.json b/.mlc_config.json index b7e3f107c7..531256fdfb 100644 --- a/.mlc_config.json +++ b/.mlc_config.json @@ -3,6 +3,9 @@ { "pattern": "^https://gerowallet.io" }, + { + "pattern": "^https://stackoverflow.com" + }, { "pattern": "^https://singularitynet.io" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index d451909cc6..df72f62af0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,74 +7,319 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -- [[Unreleased]](#unreleased) +- [[v9.2.0]](#v920) - [Added](#added) - [Changed](#changed) - - [Fixed](#fixed) - [Removed](#removed) -- [[v7.0.0]](#v700) + - [Fixed](#fixed) +- [[v9.1.0]](#v910) - [Added](#added-1) - [Changed](#changed-1) - - [Fixed](#fixed-1) - [Removed](#removed-1) -- [[v6.0.0]](#v600) + - [Fixed](#fixed-1) +- [[v9.0.0]](#v900) + - [Deprecated](#deprecated) - [Added](#added-2) + - [Removed](#removed-2) - [Changed](#changed-2) - [Fixed](#fixed-2) - - [Removed](#removed-2) -- [[v5.0.0]](#v500) +- [[v8.0.0]](#v800) - [Added](#added-3) - [Changed](#changed-3) - - [Removed](#removed-3) - [Fixed](#fixed-3) - - [Runtime Dependencies](#runtime-dependencies) -- [[v4.0.2] - 2023-01-17](#v402---2023-01-17) - - [Fixed](#fixed-4) -- [[v4.0.1] - 2022-12-20](#v401---2022-12-20) + - [Removed](#removed-3) +- [[v7.0.0]](#v700) - [Added](#added-4) -- [[v4.0.0] - 2022-12-15](#v400---2022-12-15) - - [Added](#added-5) - [Changed](#changed-4) + - [Fixed](#fixed-4) - [Removed](#removed-4) - - [Fixed](#fixed-5) - - [Runtime Dependencies](#runtime-dependencies-1) -- [[3.0.0] - 2022-11-21](#300---2022-11-21) - - [Added](#added-6) +- [[v6.0.0]](#v600) + - [Added](#added-5) - [Changed](#changed-5) + - [Fixed](#fixed-5) - [Removed](#removed-5) - - [Fixed](#fixed-6) - - [Runtime Dependencies](#runtime-dependencies-2) -- [[2.0.0] - 2022-09-12](#200---2022-09-12) - - [Added](#added-7) +- [[v5.0.0]](#v500) + - [Added](#added-6) - [Changed](#changed-6) - [Removed](#removed-6) + - [Fixed](#fixed-6) + - [Runtime Dependencies](#runtime-dependencies) +- [[v4.0.2] - 2023-01-17](#v402---2023-01-17) - [Fixed](#fixed-7) -- [[2.0.0-alpha] - 2022-07-05](#200-alpha---2022-07-05) +- [[v4.0.1] - 2022-12-20](#v401---2022-12-20) + - [Added](#added-7) +- [[v4.0.0] - 2022-12-15](#v400---2022-12-15) - [Added](#added-8) - - [Removed](#removed-7) - [Changed](#changed-7) + - [Removed](#removed-7) - [Fixed](#fixed-8) -- [[1.1.0] - 2022-06-30](#110---2022-06-30) + - [Runtime Dependencies](#runtime-dependencies-1) +- [[3.0.0] - 2022-11-21](#300---2022-11-21) + - [Added](#added-9) + - [Changed](#changed-8) + - [Removed](#removed-8) - [Fixed](#fixed-9) -- [[1.0.1] - 2022-06-17](#101---2022-06-17) + - [Runtime Dependencies](#runtime-dependencies-2) +- [[2.0.0] - 2022-09-12](#200---2022-09-12) + - [Added](#added-10) + - [Changed](#changed-9) + - [Removed](#removed-9) - [Fixed](#fixed-10) +- [[2.0.0-alpha] - 2022-07-05](#200-alpha---2022-07-05) + - [Added](#added-11) + - [Removed](#removed-10) + - [Changed](#changed-10) + - [Fixed](#fixed-11) +- [[1.1.0] - 2022-06-30](#110---2022-06-30) + - [Fixed](#fixed-12) +- [[1.0.1] - 2022-06-17](#101---2022-06-17) + - [Fixed](#fixed-13) - [[1.0.0] - 2022-06-10](#100---2022-06-10) -## [Unreleased] +## [v9.2.0] ### Added +- CIP-95 methods for querying the connected wallet account's public DRep key and +its registered and unregistered public stake keys: `ownDrepPubKey`, +`ownDrepPubKeyHash`, `ownRegisteredPubStakeKeys`, `ownUnregisteredPubStakeKeys`. +These new functions can be imported from `Contract.Wallet`. +**WARNING**: KeyWallet does not distinguish between registered and unregistered +stake keys due to the limitations of the underlying query layer. This means that +all controlled stake keys are returned as part of `ownUnregisteredPubStakeKeys`, +and the response of `ownRegisteredPubStakeKeys` is always an empty array. +([#1638](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1638)) + +- New examples demonstrating various interactions with the Cardano governance +system: `Gov.DelegateVoteAbstain`, `Gov.ManageDrep`, `Gov.ManageDrepScript`, +`Gov.SubmitVote`, `Gov.SubmitVoteScript`. +([#1638](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1638)) + +### Changed + +- `signData` for KeyWallet: Previously, the supplied address was discarded, +and the wallet's address was used as part of the COSE `Sig_structure`. Now, +the provided address is inspected, and the keys associated with that address +are used. Additionally, KeyWallet now supports signing with the DRep key as +specified in CIP-95. Keep in mind that if the wallet does not have the required +keys, an error will be thrown. +([#1638](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1638)) + +### Removed + +- Constructors for individual wallets (like Nami or Eternl) from `WalletSpec`. +Use `ConnectToGenericCip30` with the right wallet identifier instead. To obtain +the identifier of a known wallet, refer to `KnownWallet` and `walletName` from +`Contract.Config`. +([#1638](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1638)) + +### Fixed + +- `getRewardAddresses` for KeyWallet now returns actual reward addresses +without the payment part. +([#1638](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1638)) + +## [v9.1.0] + +This version provides basic Conway support and replaces Plutip with `cardano-testnet`. + +- `cardano-node`: 9.1.0 +- `ogmios`: 6.5.0 +- `kupo`: 2.9.0 +- `@mlabs-haskell/cardano-serialization-lib-gc`: `12.0.0-alpha.31` (wraps the same version of [CSL](https://github.com/Emurgo/cardano-serialization-lib/)) +- `@mlabs-haskell/uplc-apply-args`: `1.0.29-alpha` (wraps the same version of the [`uplc` crate](https://github.com/aiken-lang/aiken/tree/main/crates/uplc)) + +### Added + +- `Contract.Transaction.getTxAuxiliaryData` for querying transaction data ([#1624](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1624)). + +### Changed + +- `Contract.Test.Plutip` is replaced with `Contract.Test.Testnet` that uses `cardano-testnet` instead of Plutip. As a result, we reduced the dependency footprint (`cardano-testnet` is distributed with `cardano-node`, so there are no internal Haskell components anymore in CTL) ([#1624](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1624)) + +### Removed + +- `Contract.Transaction.getTxMetadata` - use `getTxAuxiliaryData` ([#1624](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1624)) + +### Fixed + +- Non-deterministic `ClientHttpError` raised during tests on rare occasions ([#1624](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1624)). + +## [v9.0.0] + +### Deprecated + +> [!WARNING] +> **IMPORTANT** Constraints interface (`Contract.TxConstraints` & `Contract.ScriptLookups`) has been deprecated and will be removed in a future version. Please use [`purescript-cardano-transaction-builder`](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder) (via `Contract.Transaction.buildTx`) for new contracts. The motivation for deprecation is that it was unnecessarily complex, not flexible enough, and existed only because of the desire to provide code-level compatibility with PAB. See [this Catalyst proposal](https://cardano.ideascale.com/c/idea/101478) for more info. + +### Added + +- `Contract.Transaction.buildTx :: Array TransactionBuilderStep -> Contract Transaction` that provides a `Contract`-based interface for the [new transaction builder](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder). +- `Contract.Transaction.submitTxFromBuildPlan :: UtxoMap -> BalanceTxConstraintsBuilder -> Array TransactionBuilderStep -> Contract Transaction` - a convenience function that executes the whole transaction creation pipeline starting from a build plan for [the new transaction builder](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder). +- `Contract.ClientError.pprintClientError` to provide readable error reports. +- `Contract.Staking.getStakeCredentialDelegationsAndRewards` utility function + +### Removed + +- **IMPORTANT** `UnbalancedTx` type has been removed. This change was motivated by the fact that `UnbalancedTx` existed simply to tie together transaction building and balancing by keeping extra context. Now that transaction builder is placed in [its own package](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder), there is no more need in `UnbalancedTx`, that is not used with the new builder. +- **IMPORTANT** `balanceTxWithConstraints`, `balanceTxWithConstraintsE` - use `balanceTx` +- **IMPORTANT** `balanceTxsWithConstraints` - use `balanceTxs` +- **IMPORTANT** `withBalancedTxWithConstraints`, `withBalancedTxWithConstraints` - use `withBalancedTxs` +- **IMPORTANT** `Contract.Scripts.applyArgs` - use `Cardano.Plutus.ApplyArgs.applyArgs` from [purescript-uplc-apply-args](https://github.com/mlabs-haskell/purescript-uplc-apply-args). +- `Contract.Transaction.submitTxFromConstraintsReturningFee` - too niche use case to be allowed in the public API. +- `Contract.Transaction` lens values. Use lenses from `Cardano.Types.Transaction` + +### Changed + +- Bumped Ogmios to version 6.0.3 ([#1626](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1626)) +- `Contract.Transaction.mkUnbalancedTx` now returns a tuple: a transaction and the UTxOs it used. +- `Contract.Transaction.balanceTx` accepts two extra argument: a list of used UTxOs (set to `Data.Map.empty` if none of them are coming from the outside of the wallet) and balancer constraints (set to `mempty` if not needed) +- Default synchronization parameters: all [wallet <-> query layer synchronization primitives](./doc/query-layers.md) are now off by default. The reason is that the runtime overhead made the users unhappy and it was not worth it for most of the users. If your dApp sends transactions in quick succession, consider enabling the synchronization again by using `softSynchronizationParams` (old behavior) or `strictSynchronizationParams`. +- `BalanceTxConstraintsBuilder` has been renamed to `BalancerConstraints`. It is still available under the old name as a type synonym. + +### Fixed + +## [v8.0.0] + +In this version, we've refactored CTL and split it into multiple reusable sub-packages, most notably: + +- this package +- `purescript-cardano-types` - (`Cardano.Types.*`) - domain types for Cardano ledger +- `purescript-cardano-serialization-lib` - (`Cardano.Serialization.Lib.*`) - PureScript wrapper for CSL +- `purescript-plutus-types` - (`Cardano.Plutus.*`) - Plutus-style domain types used only for `ToData`/`FromData` instances. + +See the [cardano-purescript repo](https://github.com/klntsky/cardano-purescript) for a complete list of new packages. + +These packages maintain their own public API, so the interfaces you should use are not necessarily namespaced under `Contract.*` anymore. E.g. `Cardano.Types.*` from `purescript-cardano-types` is public. + +Starting from this version, CTL does not use Plutus-domain types anymore. This change comes with some downsides (e.g. the need to provide NetworkId in `Address`es), but the benefit of not caring about conversions for basic functionality will hopefully be more noticeable. The only case when a conversion is needed is when the developer wants to use [`purescript-plutus-types`](https://github.com/mlabs-haskell/purescript-plutus-types), which is a package that offers `PlutusData` encodings compatible with Plutus. Its main purpose is to be used when there is a need to apply arguments to parametrized scripts. + +### Added + +- New purescript dependencies: + - [`purescript-bytearrays`](https://github.com/mlabs-haskell/purescript-bytearrays) + - [`purescript-cardano-hd-wallet`](https://github.com/mlabs-haskell/purescript-cardano-hd-wallet) + - [`purescript-cardano-message-signing`](https://github.com/mlabs-haskell/purescript-cardano-message-signing) + - [`purescript-cardano-plutus-data-schema`](https://github.com/mlabs-haskell/purescript-cardano-plutus-data-schema) + - [`purescript-cardano-serialization-lib`](https://github.com/mlabs-haskell/purescript-cardano-serialization-lib) + - [`purescript-cardano-types`](https://github.com/mlabs-haskell/purescript-cardano-types) +- `Contract.Address.mkAddress` - a helper that automatically uses the correct `NetworkId` to construct an `Address`. +- Sharing wallets between Plutip tests - see [the docs for this feature](./doc/plutip-testing.md#sharing-wallet-state-between-tests) ([#1585](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1585)) + - `runPlutipTestPlan` is a new function that executes a `ContractTestPlan`. + - `sameWallets` is a new function that creates a `ContractTestPlan` from a `UtxoDistribution` and a `TestPlanM` of the same wallets running different `Contract`s. +- new `onClusterStartup` hook that allows to get cluster startup parameters (private keys, `cardano-node` socket and config paths). See [`Test.Ctl.Plutip.Contract.ClusterParameters`](https://github.com/Plutonomicon/cardano-transaction-lib/blob/a5f9947/test/Plutip/Contract/ClusterParameters.purs). ([#1610](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1610)) + + ### Changed - Replaced custom CIP-30 wrapper code with [`purescript-cip30-typesafe`](https://github.com/mlabs-haskell/purescript-cip30-typesafe/) - ([#1583](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1583)) +- Renamings for better conformity with CSL: + - `TokenName` renamed to `AssetName` + - `NonAdaAsset` renamed to `MultiAsset` + - `CurrencySymbol` renamed to `ScriptHash` +- `Coin` now wraps BigNum instead of BigInt (in line with CSL) +- `NoOutputDatum` variant has been removed from `OutputDatum`: instead, it was made optional via `Maybe` in `TransactionOutput` +- `TransactionMetadatum` constructor naming change, in PS and in JSON encoding: `MetadataMap` -> `Map`, `MetadataList` -> `List` +- `Contract.PlutusData.Redeemer` has been renamed to `RedeemerDatum` (to resolve naming conflict with `cardano-ledger`-style redeemer) +- `Contract.PlutusData.Datum` has been deprecated, use `Cardano.Types.PlutusData` +- `plutusScriptV1FromEnvelope`, `plutusScriptV2FromEnvelope` have been replaced with `plutusScriptFromEnvelope` (the script is tagged with its language anyway) ### Fixed +- Plutip cluster's Kupo instances don't share the same working folder anymore - ([#1570](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1570)) +- WebAssembly memory leaks (`csl-gc-wrapper` used to depend on unstable `wasm-bidngen` API [that got changed](https://github.com/mlabs-haskell/csl-gc-wrapper/commit/2dea38228b77f7c904aafef12eece7e5af195977)) ([#1595](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1595)) ### Removed +- **[IMPORTANT]** Removed use of conditional code rewriting based on `BROWSER_RUNTIME` env variable during bundling ([#1595](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1598)). This change simplifies the bundling process, but it requires a number of updates for all CTL-dependent projects: + + * WebPack users should make this change to the webpack config: + ```diff + plugins: [ + - new webpack.DefinePlugin({ + - BROWSER_RUNTIME: isBrowser + - }), + ``` + * Esbuild users should make this change: + ```diff + const config = { + ... + - define: { + - BROWSER_RUNTIME: isBrowser ? "true" : '""' + - }, + ``` + * All users should update the runtime dependencies: + ```diff + - "@emurgo/cardano-message-signing-browser": "1.0.1", + - "@emurgo/cardano-message-signing-nodejs": "1.0.1", + + "@mlabs-haskell/cardano-message-signing": "1.0.1", + - "apply-args-browser": "0.0.1", + - "apply-args-nodejs": "0.0.1", + + "@mlabs-haskell/uplc-apply-args": "1.0.0", + + "isomorphic-ws": "^5.0.0", + - "ws": "8.4.0", + + "ws": "^8.16.0", + + "web-encoding": "^1.1.5", + ``` +- NPM runtime dependencies: + +```diff + "bip39": "^3.1.0", +- "blakejs": "1.2.1", + "bufferutil": "4.0.5", +- "jssha": "3.2.0", + "puppeteer-core": "^15.3.2", + "reconnecting-webs +``` + +- `Contract.Address` utilities to work with `Address` - use `mkAddress` and machinery from `Cardano.Types.Address` +- `Contract.RewardAddress` - use `Cardano.Types.RewardAddress` +- `Contract.Transaction`: + - Removed newtypes for `Transaction`: + - `BalancedSignedTransaction` + - `FinalizedTransaction` +- `Contract.Scripts`: + - `MintingPolicy` type. It was not used anywhere except of `mintingPolicy` lookup. Use `plutusMintingPolicy` and `nativeMintingPolicy` lookups instead. +- `Contract.ScriptLookups`: + - synonyms for lookup functions that use `Maybe` have been removed: `mintingPolicyM`, `ownPaymentPubKeyHashM`, `ownStakePubKeyHashM`, `unspentOutputsM`, `validatorM` +- `Contract.Credential` renamings: + - `PubKeyCredential` -> `PubKeyHashCredential` + - `ScriptCredential` -> `ScriptHashCredential` - `ModifyTx` error: made conversion functions total and removed the need to handle it +- `Contract.CborBytes` utils: + - `cborBytesToByteArray` + - `cborBytesFromByteArray` + - `cborBytesFromAscii` + - `cborBytesToIntArray` + - `cborBytesFromIntArray` + - `cborBytesFromIntArrayUnsafe` + - `cborBytesToHex` + - `cborByteLength` + - `hexToCborBytes` + - `hexToCborBytesUnsafe` + - `rawBytesAsCborBytes` +- `ToData`/`FromData` Instances for `purescript-noble-secp256k1` types (PS does not allow orphans) +- `ToMetadata`/`FromMetadata` instance for `BigInt`: it was partial and unsafe +- `Cardano.Types.BigNum.toInt'` method +- `Contract.Address`: + - `scriptHashAddress` - use `Contract.Address.mkAddress` + - `payPubKeyHashBaseAddress` - use `Contract.Address.mkAddress` + - `payPubKeyHashEnterpriseAddress` - use `Contract.Address.mkAddress` +- `Contract.Value`: + - `flattenNonAdaAssets` - use `Cardano.Types.Value.flatten`. +- `Contract.PlutusData`: + - `Datum`: removed, use `Cardano.Types.PlutusData` + - `unitDatum` +- `Contract.TextEnvelope`: + - `plutusScriptV1FromEnvelope` - use `plutusScriptFromEnvelope` +- `Contract.Hashing` +- `Contract.Transaction`: + - `TransactionOutputWithRefScript` - use `Cardano.Types.TransactionOutput`. It comes with refscript included. + - `getTxFinalFee` +- `Contract.Numeric.NatRatio` - the module was not used in the library. +- `Contract.AssocMap` - use `Cardano.Plutus.Types.Map` from [`purescript-plutus-types`](https://github.com/mlabs-haskell/purescript-plutus-types) +- CIP-25 metadata machinery (we need to keep the API surface thin for CTL) ## [v7.0.0] @@ -340,7 +585,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil ### Added -- Support passing the inital UTxO distribution as an Array and also get the KeyWallets as an Array when writing Plutip tests. ([#1018](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1018)). An usage example can be found [here](doc/plutip-testing.md). +- Support passing the initial UTxO distribution as an Array and also get the KeyWallets as an Array when writing Plutip tests. ([#1018](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1018)). An usage example can be found [here](doc/plutip-testing.md). - New `Contract.Test.Utils` assertions and checks: `assertOutputHasRefScript`, `checkOutputHasRefScript`, `checkTxHasMetadata` ([#1044](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1044)) - `Parallel` instance to `Contract` monad. Parallel capabilities are in the associated `ParContract` datatype ([#1037](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1037)) - Balancer constraints interface (check [Building and submitting transactions](https://github.com/Plutonomicon/cardano-transaction-lib/blob/95bdd213eff16a5e00df82fb27bbe2479e8b4196/doc/getting-started.md#building-and-submitting-transactions) and `examples/BalanceTxConstraints.purs` for reference) ([#1053](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1053)) @@ -392,7 +637,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil - Adapted Gero wallet extension to `preview` network in E2E test suite ([#1086](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1086)) - `Contact.TextEnvelope` how provides more type safe interface with simplified error handling ([#988](https://github.com/Plutonomicon/cardano-transaction-lib/issues/988)) - Forbid minting zero tokens. ([#1156](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1156)) -- Modified functions `getWalletAddress`, `ownPubKeyHash`, `ownStakePubKeyHash`, `getWalletAddressWithNetworkTag` and `ownPaymentPubKeyHash` to return `Contract r (Array Adress)`. ([#1045](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1045)) +- Modified functions `getWalletAddress`, `ownPubKeyHash`, `ownStakePubKeyHash`, `getWalletAddressWithNetworkTag` and `ownPaymentPubKeyHash` to return `Contract r (Array Address)`. ([#1045](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1045)) - `pubKeyHashAddress` and `scriptHashAddress` now both accept an optional `Credential` that corresponds to the staking component of the address ([#1060](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1060)) - `utxosAt` and `getUtxo` now use Kupo internally, `utxosAt` returns `UtxoMap` without `Maybe` context. The users will need to set `kupoConfig` in `ConfigParams`. ([#1185](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1185)) - `Interval` type is redesigned to restrain some finite intervals to be expressed in the system ([#1041](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1041)) diff --git a/Makefile b/Makefile index 5519cd4075..0bc1a80a0d 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,15 @@ SHELL := bash .ONESHELL: -.PHONY: esbuild-bundle esbuild-serve webpack-bundle webpack-serve check-format format query-testnet-tip clean check-explicit-exports spago-build create-bundle-entrypoint create-html-entrypoint delete-bundle-entrypoint +.PHONY: esbuild-bundle esbuild-serve webpack-bundle webpack-serve check-format \ + format query-preview-testnet-tip query-preprod-testnet-tip \ + clean check-explicit-exports build create-bundle-entrypoint \ + create-html-entrypoint delete-bundle-entrypoint .SHELLFLAGS := -eu -o pipefail -c ps-sources := $(shell fd --no-ignore-parent -epurs) nix-sources := $(shell fd --no-ignore-parent -enix --exclude='spago*') js-sources := $(shell fd --no-ignore-parent -ejs -ecjs) +purs-args := "--stash --censor-lib --censor-codes=UserDefinedWarning,ImplicitImport,ImplicitQualifiedImport,ImplicitQualifiedImportReExport" ### Bundler setup @@ -13,15 +17,16 @@ js-sources := $(shell fd --no-ignore-parent -ejs -ecjs) ps-entrypoint := Ctl.Examples.ByUrl # The entry point function in the main PureScript module ps-entrypoint-function := main -# Whether to bundle for the browser +# Whether to bundle for the browser ("1") or the node ("") +# NOTE: bundling for the node is not necessary, see https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/doc/using-from-js.md browser-runtime := 1 # Use "1" for true and "" for false preview-node-ipc = $(shell docker volume inspect store_node-preview-ipc | jq -r '.[0].Mountpoint') preprod-node-ipc = $(shell docker volume inspect store_node-preprod-ipc | jq -r '.[0].Mountpoint') serve-port := 4008 -spago-build: - @spago build +build: + @spago build --purs-args ${purs-args} create-bundle-entrypoint: @mkdir -p dist/ @@ -39,20 +44,20 @@ create-html-entrypoint: EOF -esbuild-bundle: spago-build create-bundle-entrypoint +esbuild-bundle: build create-bundle-entrypoint @mkdir -p dist/ BROWSER_RUNTIME=${browser-runtime} node esbuild/bundle.js ./dist/entrypoint.js dist/index.js @make delete-bundle-entrypoint -esbuild-serve: spago-build create-bundle-entrypoint create-html-entrypoint +esbuild-serve: build create-bundle-entrypoint create-html-entrypoint BROWSER_RUNTIME=1 node esbuild/serve.js ./dist/entrypoint.js dist/index.js dist/ ${serve-port} -webpack-bundle: spago-build create-bundle-entrypoint +webpack-bundle: build create-bundle-entrypoint BROWSER_RUNTIME=${browser-runtime} webpack --mode=production \ -o dist/ --env entry=./dist/entrypoint.js @make delete-bundle-entrypoint -webpack-serve: spago-build create-bundle-entrypoint create-html-entrypoint +webpack-serve: build create-bundle-entrypoint create-html-entrypoint BROWSER_RUNTIME=1 webpack-dev-server --progress \ --port ${serve-port} \ -o dist/ --env entry=./dist/entrypoint.js @@ -61,6 +66,7 @@ webpack-serve: spago-build create-bundle-entrypoint create-html-entrypoint check-explicit-exports: @if grep -rn '(\.\.)' ${ps-sources}; then echo "Use explicit imports/exports ^" + echo "Run ./scripts/import-fixer.sh to autofix some of these" exit 1 else echo "All imports/exports are explicit" @@ -76,7 +82,7 @@ check-format: check-explicit-exports check-examples-imports check-whitespace @purs-tidy check ${ps-sources} @nixpkgs-fmt --check ${nix-sources} @prettier --log-level warn -c ${js-sources} - @eslint --quiet ${js-sources} --parser-options 'sourceType: module' + @eslint --quiet ${js-sources} format: @purs-tidy format-in-place ${ps-sources} @@ -95,17 +101,19 @@ query-preprod-testnet-tip: CARDANO_NODE_SOCKET_PATH=${preprod-node-ipc}/node.socket cardano-cli query tip \ --testnet-magic 1 -run-ci-actions: +run-ci-actions: run-template-checks nix build -L .#checks.x86_64-linux.formatting-check - nix build -L .#checks.x86_64-linux.template-deps-json - nix build -L .#checks.x86_64-linux.template-dhall-diff - nix build -L .#checks.x86_64-linux.template-version nix build -L .#checks.x86_64-linux.ctl-unit-test nix build -L .#checks.x86_64-linux.ctl-e2e-test - nix build -L .#checks.x86_64-linux.ctl-plutip-test + nix build -L .#checks.x86_64-linux.ctl-local-testnet-test nix build -L .#checks.x86_64-linux.ctl-staking-test nix build -L .#checks.x86_64-linux.examples-imports-check +run-template-checks: + nix build -L .#checks.x86_64-linux.template-deps-json + nix build -L .#checks.x86_64-linux.template-dhall-diff + nix build -L .#checks.x86_64-linux.template-version + clean: @ rm -r .psc-ide-port || true @ rm -rf .psci_modules || true diff --git a/README.md b/README.md index c2d164a066..9ccdbe83b7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# cardano-transaction-lib +# cardano-transaction-lib [![cardano-purescript](https://img.shields.io/badge/cardano--purescript?logo=cardano&logoColor=white&label=cardano-purescript&labelColor=blue&color=blue)](https://github.com/klntsky/cardano-purescript) + [![Hercules-ci][herc badge]][herc link] [![Cachix Cache][cachix badge]][cachix link] @@ -11,7 +12,7 @@ [docs badge]: https://img.shields.io/badge/docs-PureScript%20code%20documentation-%2377F [docs link]: https://plutonomicon.github.io/cardano-transaction-lib/ -**cardano-transaction-lib** (CTL) is a Purescript library for building smart contract transactions on Cardano. It aims to port the functionality and interface of Plutus off-chain code to the browser environment and NodeJS. +**cardano-transaction-lib** (CTL) is a Purescript framework for building smart contract transactions on Cardano. It belongs to the the same category of tools as Lucid, Mesh.js, Atlas, Plutus Application Backend (PAB). **Table of Contents** @@ -19,9 +20,6 @@ - [Documentation](#documentation) - - [Light wallet support](#light-wallet-support) -- [Roadmap](#roadmap) -- [Architecture](#architecture) - [Additional resources/tools:](#additional-resourcestools) - [Available support channels info](#available-support-channels-info) - [Funding acknowledgements](#funding-acknowledgements) @@ -31,7 +29,7 @@ ## Documentation -Please explore our documentation to discover how to use CTL, how to set up its runtime, and how it compares to Plutus/PAB: +Please explore our documentation to discover how to use CTL, how to set up its runtime, and how it compares to other tools: - [Super quick start](./doc/getting-started.md#setting-up-a-new-project) - [Adding CTL as a dependency](./doc/ctl-as-dependency.md) @@ -41,18 +39,19 @@ Please explore our documentation to discover how to use CTL, how to set up its r - [Managing contract environment](./doc/contract-environment.md) - [Using CTL from JS](./doc/using-from-js.md) - [Importing Plutus Scripts](./doc/importing-scripts.md) -- [Migrating from Plutus to CTL](./doc/plutus-comparison.md) +- [Migrating from Plutus Application Backend to CTL](./doc/plutus-comparison.md) - [Overview of testing approaches](./doc/testing.md) - - [Testing contracts with Plutip](./doc/plutip-testing.md) - - [End-to-end testing with headless browsers](./doc/e2e-testing.md) - - [Utilities for testing](./doc/test-utils.md) -- [CIP-25 NFT standard support](./doc/cip-25-nfts.md) + - [Testing on local Cardano testnets](./doc/cardano-testnet-testing.md) + - [End-to-end dApp testing with headless browsers](./doc/e2e-testing.md) + - [Assertion utilities for testing](./doc/test-utils.md) + - [Using a directory with private keys to run tests](./doc/keydir.md) - [Transaction balancing](./doc/balancing.md) - [Transaction chaining](./doc/tx-chaining.md) - [Ada staking support](./doc/staking.md) - [Key management](./doc/key-management.md) - [SECP256k1 support (CIP-49)](./doc/secp256k1-support.md) - [Custom query layers](./doc/custom-query-layers.md) +- [Going to production with CTL](./doc/production.md) - [FAQs](./doc/faq.md) - [Feature overview video](./doc/video-intro.md) - [Comparison with other frameworks (Lucid)](./doc/comparisons.md) @@ -60,46 +59,6 @@ Please explore our documentation to discover how to use CTL, how to set up its r You can also access [PureScript documentation for CTL and its dependencies](https://plutonomicon.github.io/cardano-transaction-lib/) for the most recent `develop` version, or [generate it yourself](./doc/development.md#generating-ps-documentation). -### Light wallet support - -Support is planned for the following light wallets: - -- [x] [Nami](https://namiwallet.io/) -- [x] [Gero](https://gerowallet.io/) -- [x] [Flint](https://flint-wallet.com/) -- [x] [Lode](https://lodewallet.io/) -- [x] [Eternl (formerly CCvault)](https://eternl.io/) -- [x] [NuFi](https://nu.fi/) -- [x] [Lace](https://www.lace.io/) -- [ ] [Typhon](https://typhonwallet.io/) -- [ ] [Yoroi](https://yoroi-wallet.com/) - -## Roadmap - -- [x] **Stage 1** Build a simple transaction in the browser that works with at least one light wallet (Nami) -- [x] **Stage 2** Once we can construct a simple user-to-user transaction, we will try to use the library to submit the tx with nami -- [x] **Stage 3** Once we have a simple working transaction, we will seek to build a Plutus smart contract transaction with datum from scratch -- [x] **Stage 4** Once we can construct Plutus smart contract transactions, we will seek to build a library/DSL/interface such that transactions can be built using constraints and lookups - as close as possible to a cut-and-paste solution from Plutus' `Contract` monad code in Haskell (but with no guarantee that code changes are not necessary) - - [x] **Stage 4.1** Investigate supporting compatibility with the Vasil hardfork and improvements to our initial `Contract` API -- [x] **Stage 5** Once we have a basic `Contract`-style API, we will further refine its public interface, expand wallet support (see [below](#light-wallet-support)), expose a test interface (**DONE** - see [here](doc/plutip-testing.md)), provide a more ergonomic JS/TS API, support stake validators (**DONE**), and support CIP workflows on the public testnet (**In progress**) -- [x] **Stage 6** Once CTL's `Contract` interface has been stabilized, we will add support for even more wallets and attempt to deprecate CTL's currently required Haskell server (**DONE**) - -## Architecture - -CTL is directly inspired by the Plutus Application Backend (PAB). Unlike PAB, however, CTL is a library and not a standalone process. Over the course of CTL's development, several questions have been raised as to how best create PAB-as-a-library: - -1. How do we get the transaction in the right format? - - This is handled by `cardano-serialization-lib`, a Rust library available as WASM -2. How do we query the chain? - - This has been solved using Ogmios & Kupo - - Thanks to [Catalyst](https://cardano.ideascale.com/c/idea/420791), we now support an alternative [BlockFrost](https://blockfrost.io/) backend as well -3. How do we get wallet data? - - This is done via browser-based light wallet integration in the browser based on CIP-30 -4. How closely should we follow Plutus' `Contract` API? - - CTL's `Contract` model is **significantly** less restrictive than Plutus' and allows for arbitrary effects within the `Contract` monad - - Certain features cannot be directly translated into Purescript from Haskell due to differences between the two languages - - Some of the Plutus conventions do not make sense for us, due to differences between on-chain and off-chain - ## Additional resources/tools: - [`cardano-serialization-lib`](https://github.com/Emurgo/cardano-serialization-lib/) @@ -118,17 +77,19 @@ You can find help, more information and ongoing discusion about the project here ## Funding acknowledgements -CTL is being developed by MLabs. The following companies/funds have contributed significant resources to development: +CTL is being developed by MLabs. The following companies/funds have contributed significant resources (development time or funding): - [IOHK](https://iohk.io/en/about/) - [Catalyst Fund8](https://cardano.ideascale.com/c/idea/396607) - [Catalyst Fund9](https://cardano.ideascale.com/c/idea/420791) - [Catalyst Fund10](https://cardano.ideascale.com/c/idea/101478) +- [Intersect MBO](https://docs.intersectmbo.org/intersect-community-grants/grant-projects) - [MLabs](https://mlabs.city/) - [Indigo Protocol](https://indigoprotocol.io/) - [Equine](https://www.equine.gg/) - [Liqwid Labs](https://liqwid.finance/) - [PlayerMint](https://www.playermint.com/) +- [Fourier Labs](https://fourierlabs.io/) - Ardana ## Use in production diff --git a/doc/babbage-features.md b/doc/babbage-features.md index 02a32211a5..1cfac81e77 100644 --- a/doc/babbage-features.md +++ b/doc/babbage-features.md @@ -6,48 +6,29 @@ This document is a reference/explainer for the new CTL APIs introduced for Babba -- [Reference Inputs](#reference-inputs) -- [Reference Scripts](#reference-scripts) +- [Reference Inputs & Reference Scripts](#reference-inputs--reference-scripts) - [Inline Data](#inline-data) - [Collateral Output](#collateral-output) -## Reference Inputs +## Reference Inputs & Reference Scripts [Reference inputs](https://cips.cardano.org/cip/CIP-0031#reference-inputs) allow looking at an output without spending it in Plutus scripts. -There are two ways to use an input as a reference in the constraints API: - -1. via `mustReferenceOutput`, which allows Plutus scripts to access the information (e.g. datum, locked value) contained in the output. - -[Usage example](../examples/PlutusV2/ReferenceInputs.purs) - -2. by providing constraints which accept a value of the type `InputWithScriptRef` with the `RefInput` constructor. These allow scripts (validating or minting) to be reused by reference between multiple transactions without including them in those transactions, explained further in [Reference Scripts](#reference-scripts). - -[Usage example](../examples/PlutusV2/ReferenceInputsAndScripts.purs) - -## Reference Scripts - [Reference Scripts](https://cips.cardano.org/cip/CIP-0033) allows the use of scripts without attaching them to the transaction (and using a reference instead). -Reference scripts can be utilized in CTL by first creating a reference point for the script to be used later via `mustPayToScriptWithScriptRef` (or its variants). +Reference scripts can be utilized in CTL by first creating a UTxO containing the script to be used later. -This constraint utilises a new `ScriptRef` type that includes either a native script or a Plutus script. - -Then, `mustSpendScriptOutputUsingScriptRef` (or its variants) can be used to use a reference script. It accepts a value of type `InputWithScriptRef` that specifies whether the UTxO with the reference script should be spent or referenced. - -[Usage example](../examples/PlutusV2/ReferenceScripts.purs) +[Usage example](../examples/PlutusV2/ReferenceInputsAndScripts.purs) ## Inline Data [CIP-32](https://cips.cardano.org/cip/CIP-0032) introduces the inline data feature that allows storing datum values directly in transaction outputs, instead of just the hashes. -In CTL, alternating between datum storage options can be achieved by specifying a `DatumPresence` value with constraints that accept it, like `mustPayToPubKeyWithDatum`. - -[Usage example](../examples/PlutusV2/InlineDatum.purs) - ## Collateral Output [CIP-40](https://cips.cardano.org/cip/CIP-0040) introduces explicit collateral output. On validation failure, previously the entire collateral was consumed. Now, if excess collateral is supplied, even with native assets, the surplus can be returned on validation failure. Collateral output is automatically added to transactions in CTL. To trigger a collateral return, the `mustNotBeValid` constraint should be explicitly specified, otherwise a script error would be detected earlier and the transaction will not be sent. + +[Usage example](../examples/Lose7Ada.purs) diff --git a/doc/balancing.md b/doc/balancing.md index 961e357a4a..f3681101ee 100644 --- a/doc/balancing.md +++ b/doc/balancing.md @@ -1,7 +1,7 @@ -- [Configuring balancing process](#configuring-balancing-process) +- [Configuring the balancing process](#configuring-the-balancing-process) - [Balancer constraints](#balancer-constraints) - [Concurrent spending](#concurrent-spending) - [Balancing a Tx for other wallet](#balancing-a-tx-for-other-wallet) @@ -10,7 +10,7 @@ -# Configuring balancing process +# Configuring the balancing process Transaction balancing in Cardano is the process of finding a set of inputs and outputs that that sum up to zero, covering all the required fees for the transaction to be valid. @@ -37,7 +37,7 @@ Setting `mustUseUtxosAtAddress`, `mustSendChangeToAddress` and `mustUseCollatera ## Synchronization -Before balancing, CTL tries to synchronize the wallet state with the query layer, i.e. waits until all UTxOs that the wallet returns are visible in the query layer. Thus the situation when the query layer refuses to validate a Tx (either during ex-units evaluation or on Tx submission) is only possible due to a rollback or a synchronization timeout. Please see [our docs for query layer synchronization](./query-layers.md). +It's possible to make CTL try to synchronize the wallet state with the query layer, i.e. wait until all UTxOs that the wallet returns are visible in the query layer. Thus the situation when the query layer refuses to validate a Tx (either during ex-units evaluation or on Tx submission) is only possible due to a rollback or a synchronization timeout. Please see [our docs for query layer synchronization](./query-layers.md). ## Balancing process limitations diff --git a/doc/blockfrost.md b/doc/blockfrost.md index 8239f4fa1b..72efd58bf9 100644 --- a/doc/blockfrost.md +++ b/doc/blockfrost.md @@ -47,7 +47,7 @@ Go to https://blockfrost.io to generate a new API key and specify it as `BLOCKFR ### Generating private keys -Follow https://developers.cardano.org/docs/stake-pool-course/handbook/keys-addresses/ to generate a private payment key (and, optionally, a stake key). You can use [this script](https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/scripts/generate-keys.sh) for convenience instead of following instructions in this section manually. +Follow [this guide](https://developers.cardano.org/docs/operate-a-stake-pool/generating-wallet-keys) to generate a private payment key (and, optionally, a stake key). You can use [this script](https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/scripts/generate-keys.sh) for convenience instead of following instructions in this section manually. The generated keys should look like this: @@ -210,4 +210,5 @@ This function is never used for constraints resolution, the only way to make it ## See also +- [key-directory test suite](./keydir.md) that is used under the hood by `executeContractTestsWithBlockfrost`. This test machinery can be used with any runtime backend, not just Blockfrost. - [Testing utilities for CTL](./test-utils.md). diff --git a/doc/cardano-testnet-testing.md b/doc/cardano-testnet-testing.md new file mode 100644 index 0000000000..7065a5ce2d --- /dev/null +++ b/doc/cardano-testnet-testing.md @@ -0,0 +1,410 @@ +# CTL integration with Cardano Testnet + +**Table of Contents** + + + +- [Overview](#overview) +- [Architecture](#architecture) +- [Testing contracts](#testing-contracts) + - [Testing with Mote](#testing-with-mote) + - [Using Mote testing interface](#using-mote-testing-interface) + - [Internal implementation overview](#internal-implementation-overview) + - [Testing in Aff context](#testing-in-aff-context) + - [Sharing wallet state between tests](#sharing-wallet-state-between-tests) + - [Writing checks in tests](#writing-checks-in-tests) + - [Note on SIGINT](#note-on-sigint) + - [Testing with Nix](#testing-with-nix) +- [Cluster configuration options](#cluster-configuration-options) + - [Current limitations](#current-limitations) +- [Using addresses with staking key components](#using-addresses-with-staking-key-components) +- [Limitations](#limitations) +- [See also](#see-also) + + + +## Overview + +[`cardano-testnet`](https://github.com/IntersectMBO/cardano-node/tree/master/cardano-testnet) is a tool for spinning up temporary local testnets. CTL integrates with it to provide an environment for `Contract` testing, that is very close to production. + +## Architecture + +CTL depends on a number of binaries in the `$PATH` to execute tests on the +Cardano Testnet: + +- [`cardano-node`](https://github.com/IntersectMBO/cardano-node) to connect to the Cardano Testnet +- [`ogmios`](https://ogmios.dev/) +- [`kupo`](https://cardanosolutions.github.io/kupo/) + +All of these are provided by CTL's `overlays.runtime` (and are provided in +CTL's own `devShell`). You **must** use the `runtime` overlay or otherwise make +the services available in your package set (e.g. by defining them within your +own `overlays` when instantiating `nixpkgs`) as `purescriptProject.runTest` +expects all of them; an example of using CTL's overlays is in the +[`ctl-scaffold` template](../templates/ctl-scaffold/flake.nix#L35). + +The services are NOT run by `docker-compose` (via `arion`) as is the case with +`launchCtlRuntime`: instead, they are started and stopped on each CTL +`ContractTest` execution by CTL itself. + +If you have based your project on the [`ctl-scaffold` +template](../templates/ctl-scaffold) then you have two options to run tests on +the Cardano Testnet: +1. `nix develop` followed by `npm run test` (recommended for development) +2. `nix run .#checks.x86_64-linux.ctl-scaffold-local-testnet-test` + * where you'd usually replace `x86_64-linux` with the system you run tests on + * and `ctl-scaffold-local-testnet-test` with the name of the test derivation for your project; + +## Testing contracts + +CTL provides integrated testing environment for Mote (a test framework in PureScript). Alternatively, testing in the `Aff` context is also available, which makes it possible to integrate with any testing framework (or none at all). + +### Testing with Mote + +[Mote](https://github.com/garyb/purescript-mote) is a DSL for defining and +grouping tests (plus other quality of life features, e.g. skipping marked +tests). + +First (and more widely used) approach is to first build a tree of tests (in +CTL's case a tree of `ContractTest` types -- basically a function from some +distribution of funds to a `Contract a`) via Mote and then use the +`Contract.Test.Testnet.testTestnetContracts` function to execute them. This +allows setting up the Cardano Testnet only once per top-level groups and tests +passed to the `testTestnetContracts` and then use it in many independent tests. +The function will interpret a `MoteT` (effectful test tree) into `Aff`, which +you can then actually run. + +The [`ctl-scaffold` template](../templates/ctl-scaffold) provides a simple +`Mote`-based example. + +`Contract.Test.Testnet.testTestnetContracts` type is defined as follows: +```purescript +testTestnetContracts + :: TestnetConfig + -> TestPlanM ContractTest Unit + -> TestPlanM (Aff Unit) Unit +``` +It takes a configuration and a tree of Mote tests, where tests are of type +`ContractTest`. + +To create tests of type `ContractTest`, you should either use +`Contract.Test.Testnet.withWallets` or `Contract.Test.Testnet.noWallet`: + +```purescript +withWallets + :: forall (distr :: Type) (wallets :: Type) + . UtxoDistribution distr wallets + => distr + -> (wallets -> Contract Unit) + -> ContractTest + +noWallet :: Contract Unit -> ContractTest +noWallet test = withWallets unit (const test) +``` + +Usage of `testTestnetContracts` is similar to that of `runTestnetContract`, +and distributions are handled in the same way. Here's an example: + +```purescript +suite :: MoteT Aff (Aff Unit) Aff +suite = testTestnetContracts config do + test "Test 1" do + let + distribution :: Array BigInt /\ Array BigInt + distribution = ... + withWallets distribution \(alice /\ bob) -> do + ... + + test "Test 2" do + let + distribution :: Array BigInt + distribution = ... + withWallets distribution \alice -> do + ... + + test "Test 3" do + noWallet do + ... +``` + +#### Using Mote testing interface + +To define tests suites you can use `test`, group them with `group` and also +wrap tests or groups with `bracket` to execute custom actions before and +after tests/groups that are inside the bracket. Note that in Mote you can +define several tests and several groups in a single block, and bracket that +wraps them will be run for each such test or group. + +Internally `testTestnetContracts` places a bracket that sets up the CTL +environment and connects to the Cardano Testnet on the top level, so if you +want to connect only once wrap your tests or groups in a single group. In +the example above the environment and Testnet setup will happen 3 times. + +#### Internal implementation overview + +`Contract.Test.Testnet.testTestnetContracts` type is defined as follows: + +```purescript +type TestPlanM :: Type -> Type -> Type +type TestPlanM test a = MoteT Aff test Aff a + +testTestnetContracts + :: TestnetConfig + -> TestPlanM ContractTest Unit + -> TestPlanM (Aff Unit) Unit + +``` +where +* `test :: Type` is a type of tests themselves, + * in our case it's [`ContractTest`](../src/Internal/Test/ContractTest.purs), + which in a nutshell describes a function from some wallet UTxO distribution to + a `Contract r` + * wallet UTxO distribution is the one that you need to pattern-match on when + writing tests +* `m :: Type -> Type` is a monad where effects during the construction of the + test suite can be performed, + * here we use `Aff` again +* `a :: Type` is a result of the test suite, we use `Unit` here. + +`testTestnetContracts` also combines ADA distribution requirements of individual tests in a single ADA distribution requirement. This allows to create multiple wallets and +fund them in one step, during the Testnet setup. See the comments in the +[`Ctl.Internal.Testnet.Server` module](../src/Internal/Testnet/Contract.purs) for +more info. + +### Testing in Aff context + +If using Mote is not desired, it's possible to use the `Contract.Test.Testnet.runTestnetContract` function, +which takes a single `Contract`, connects to the Testnet and executes the passed +contract. This function runs in `Aff`; it will also throw an exception should +contract fail for any reason. The testnet is terminated after `Contract` execution. + +You can either call this function directly from your test's `main` or use any +library for grouping and describing tests which support `Aff` effects in test bodies. + +`Contract.Test.Testnet.runTestnetContract`'s type is defined as follows: + +```purescript +runTestnetContract + :: forall (distr :: Type) (wallets :: Type) (a :: Type) + . UtxoDistribution distr wallets + => TestnetConfig + -> distr + -> (wallets -> Contract a) + -> Aff a +``` + +`distr` is a specification of how many wallets and with how much funds should be +created. It should either be a `Unit` (for no wallets), nested tuples containing +`Array BigInt` or an `Array (Array BigInt)`, where each element of the inner array +specifies an UTxO amount in Lovelaces (0.000001 Ada). + +The `wallets` argument of the callback is either a `Unit`, a tuple of `KeyWallet`s +(with the same nesting level as in `distr`, which is guaranteed by +`UtxoDistribution`) or an `Array KeyWallet`. + +`wallets` should be pattern-matched on, and its components should be passed to +`withKeyWallet`: + +An example `Contract` with two actors using nested tuples: + +```purescript +let + distribution :: Array BigInt /\ Array BigInt + distribution = + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] /\ + [ BigNum.fromInt 2_000_000_000 ] +runTestnetContract config distribution \(alice /\ bob) -> do + withKeyWallet alice do + pure unit -- sign, balance, submit, etc. + withKeyWallet bob do + pure unit -- sign, balance, submit, etc. +``` + +An example `Contract` with two actors using `Array`: + +```purescript +let + distribution :: Array (Array BigInt) + distribution = + -- wallet one: two UTxOs + [ [ BigNum.fromInt 1_000_000_000, BigNum.fromInt 2_000_000_000] + -- wallet two: one UTxO + , [ BigNum.fromInt 2_000_000_000 ] + ] +runTestnetContract config distribution \wallets -> do + traverse_ ( \wallet -> do + withKeyWallet wallet do + pure unit -- sign, balance, submit, etc. + ) + wallets +``` + +In most cases at least two UTxOs per wallet are needed (one of which will be used +as collateral, so it should exceed `5_000_000` Lovelace). + +Internally `runTestnetContract` runs a contract in an `Aff.bracket`, which creates +a Testnet setup on setup and terminates it during the shutdown or in case of an +exception. Logs will be printed in case of an error. + +### Sharing wallet state between tests + +To execute tests that share the same wallet state, the use of +`Contract.Test.Testnet.runTestnetTestPlan` is suggested, which has a type of: + +```purescript +runTestnetTestPlan + :: TestnetConfig + -> ContractTestPlan + -> TestPlanM (Aff Unit) Unit +``` + +`runTestnetTestPlan` uses the exact same logic as `testTestnetContracts`, except it +requires that wallets are pre-allocated inside of the second parameter, which has a +type of `ContractTestPlan`. `Contract.Test.Testnet.sameWallets` is a helper +function that can be used to create a `ContractTestPlan` where all of the tests use +the same wallets that are defined in the `UtxoDistribution`, this function has a +type of: + +```purescript +sameWallets + :: forall (distr :: Type) (wallets :: Type) + . UtxoDistribution distr wallets + => distr + -> TestPlanM (wallets -> Contract Unit) Unit + -> ContractTestPlan +``` + +Usage of `runTestnetTestPlan` is similar to that of `testTestnetContracts`, except +that the distributions are handled slightly differently. Here's an example of +using `sameWallets`: + +```purescript +suite :: TestPlanM (Aff Unit) Unit +suite = runTestnetTestPlan config do + let + distribution :: Array BigInt /\ Array BigInt + distribution = ... + + sameWallets distribution $ + group "Test Plan" do + test "Test 1" \(alice /\ bob /\ charlie) -> do + ... + + test "Test 2" \(alice /\ bob /\ charlie) -> do + ... + + test "Test 3" \(alice /\ bob /\ charlie) -> do + ... +``` + +Another example for using `sameWallets` can be found [here](../test/Testnet/SameWallets.purs). + +### Writing checks in tests + +CTL will run contracts in your test bodies and will print errors for any failed +tests. For more complex checks you can use the [assertions library](./test-utils.md). + +### Note on SIGINT + +Due to `testTestnetContracts`/`runTestnetContract` adding listeners to the SIGINT +IPC signal, Node.js's default behavior of exiting on CTRL+C no longer occurs. This +was done to let cluster cleanup handlers run asynchronously. To restore the usual +exit-by-CTRL+C, we provide helpers to cancel an `Aff` fiber and set the exit code, +to let Node.js shut down gracefully when no more events are to be processed. + +```purescript +... +import Contract.Test.Utils (exitCode, interruptOnSignal) +import Data.Posix.Signal (Signal(SIGINT)) +import Effect.Aff (cancelWith, effectCanceler, launchAff) + +main :: Effect Unit +main = interruptOnSignal SIGINT =<< launchAff do + flip cancelWith (effectCanceler (exitCode 1)) do + ... test suite in Aff ... +``` + +### Testing with Nix + +You can run Testnet tests via CTL's `purescriptProject` as well. After creating +your project, you can use the `runLocalTestnetTest` attribute to create a Testnet testing +environment that is suitable for use with your flake's `checks`. An example: + +```nix +{ + some-testnet-test = project.runLocalTestnetTest { + name = "some-testnet-test"; + testMain = "Test.MyProject.Testnet"; + # The rest of the arguments are passed through to `runPursTest`: + env = { SOME_ENV_VAR = "${some-value}"; }; + }; +} +``` + +The usual approach is to put `projectname-testnet-test` in the `checks` attribute of +your project's `flake.nix`. This is done by default in the +[`ctl-scaffold` template](../templates/ctl-scaffold/flake.nix). + +## Cluster configuration options + +`TestnetConfig` type contains `clusterConfig` record with the following options: + +```purescript + { testnetMagic :: Int + , era :: Era + , slotLength :: Seconds + , epochSize :: Maybe UInt + } +``` + +- `slotLength` and `epochSize` define time-related protocol parameters. Epoch size + is specified in slots. + +### Current limitations + +* Non-default values of `epochSize` (current default is 80) break staking rewards - + see [this issue](https://github.com/mlabs-haskell/plutip/issues/149) for more info. + `slotLength` can be changed without any problems. + +## Using addresses with staking key components + +It's possible to use stake keys with the Testnet. `Contract.Test.Testnet.withStakeKey` +function can be used to modify the distribution spec: + +```purescript +let + privateStakeKey :: PrivateStakeKey + privateStakeKey = wrap $ unsafePartial $ fromJust + $ privateKeyFromBytes =<< hexToRawBytes + "633b1c4c4a075a538d37e062c1ed0706d3f0a94b013708e8f5ab0a0ca1df163d" + aliceUtxos = + [ BigNum.fromInt 2_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] + distribution = withStakeKey privateStakeKey aliceUtxos +``` + +Although stake keys serve no real purpose in the Testnet context, they allow the +use of base addresses, and thus allow the same code for Testnet testing, in-browser +tests, and production. + +Note that CTL re-distributes tADA from payment key-only ("enterprise") addresses to +base addresses, which requires a few transactions before the test can be run. These +transactions happen on the CTL side, because the Testnet can currently handle only +enterprise addresses (see [this issue](https://github.com/mlabs-haskell/plutip/issues/103)). + +## Limitations +* See the `epochSize` configuration option problem [here](#current-limitations). +* Currently there's no way to share wallets between separate tests (which is useful + for complex protocols). You can adapt [this PR](https://github.com/IndigoProtocol/cardano-transaction-lib/pull/1) (needs to be updated for the newer versions of CTL, likely won't need too many changes) if you need it now (and even better -- make a PR to CTL). +* If you've used the [`plutus-simple-model`](https://github.com/mlabs-haskell/plutus-simple-model) library then you might know that it allows to time travel in tests, which can be very useful for testing vesting schedules, etc. Testing with the Testnet doesn't allow this, as it's running a real network. A way around this problem can be to parametrize onchain logic by a time multiplier (and use a small one for tests). + +## See also + +- To actually write the test bodies, [assertions library](./test-utils.md) can be + useful [(usage example)](../examples/ContractTestUtils.purs). +- Take a look at CTL's Testnet tests for the usage examples: + - the entry point with `main` that runs Testnet tests is [here](../test/Testnet.purs), + - folder with various test suites is [here](../test/Testnet/). diff --git a/doc/cip-25-nfts.md b/doc/cip-25-nfts.md deleted file mode 100644 index 6c15688914..0000000000 --- a/doc/cip-25-nfts.md +++ /dev/null @@ -1,7 +0,0 @@ - - -# CIP-25 NFT Metadata standard - -CTL includes [CIP-25](https://cips.cardano.org/cip/CIP-0025) (v2) domain type definitions that enable creation of standard-compliant applications with ease. The definitions abstract away conversions between PlutusData and PureScript types. - -See [`Contract.Metadata`](https://plutonomicon.github.io/cardano-transaction-lib/Contract.Metadata.html#t:Cip25MetadataEntry) module. diff --git a/doc/comparisons.md b/doc/comparisons.md index 0a362e0109..083f1db9ef 100644 --- a/doc/comparisons.md +++ b/doc/comparisons.md @@ -6,6 +6,7 @@ This document highlights key differences between CTL and other Cardano offchain +- [Plutus Application Backend](#plutus-application-backend) - [Lucid](#lucid) - [Wallet support](#wallet-support) - [Query layer differences](#query-layer-differences) @@ -16,11 +17,29 @@ This document highlights key differences between CTL and other Cardano offchain +## Plutus Application Backend + +CTL is directly inspired by the Plutus Application Backend (PAB). Unlike PAB, however, CTL is a library and not a standalone process. Over the course of CTL's development, several questions have been raised as to how best create PAB-as-a-library: + +1. How do we get the transaction in the right format? + - This is handled by `cardano-serialization-lib`, a Rust library available as WASM +2. How do we query the chain? + - This has been solved using Ogmios & Kupo + - Thanks to [Catalyst](https://cardano.ideascale.com/c/idea/420791), we now support an alternative [BlockFrost](https://blockfrost.io/) backend as well ([docs](./blockfrost.md)) +3. How do we get wallet data? + - This is done via browser-based light wallet integration in the browser based on CIP-30 ([`purescript-cip30-typesafe`](https://github.com/mlabs-haskell/purescript-cip30-typesafe)) +4. How closely should we follow Plutus' `Contract` API? + - CTL's `Contract` model is **significantly** less restrictive than Plutus' and allows for arbitrary effects within the `Contract` monad + - Certain features cannot be directly translated into Purescript from Haskell due to differences between the two languages + - Some of the Plutus conventions do not make sense for us, due to differences between on-chain and off-chain + - Our API scope is a lot more extensive, as we provide support for wallet interactions, staking operations, and more support for balancer tweaking. + +For a more in-depth explanation of the differences between PAB and CTL (with code examples), refer to [`plutus-comparison.md`](./plutus-comparison.md). + ## Lucid ### Wallet support -- Lucid supports any CIP-30 compatible wallet. CTL supports a pre-defined list of wallets (however, the list can be extended easily). - Both CTL and Lucid support using [seed phrases and private keys](./key-management.md). - Lucid allows to use any address without a private key for querying - CTL does not allow that, but it's still possible to build transactions for other wallets to sign via [other means](./balancing.md). @@ -43,7 +62,7 @@ Lucid, on the other hand, provides a way to get a UTxO that contains a specified ### Supported backends - Both CTL and Lucid support [Blockfrost](./blockfrost.md) and [Kupo+Ogmios](./runtime.md) -- Lucid supports [Maestro](https://www.gomaestro.org/) +- Lucid also supports [Maestro](https://www.gomaestro.org/) - Both CTL and Lucid allow for custom backends - Lucid via `Provider` interface implementation, and CTL via a custom `QueryHandle`. ### Staking support @@ -52,13 +71,14 @@ Both [CTL](./staking.md) and [Lucid](https://lucid.spacebudz.io/docs/getting-sta ### Testing -CTL uses [Plutip](./plutip-testing.md), which is a tool to spawn real Cardano testnets on the fly, while Lucid uses an [emulator](https://lucid.spacebudz.io/docs/getting-started/test-emulate/). +CTL uses [Cardano Testnet](./cardano-testnet-testing.md), while Lucid uses an [emulator](https://lucid.spacebudz.io/docs/getting-started/test-emulate/). Additionally, CTL supports [testing with real wallets](./e2e-testing.md) via headless browsers and provides [an assertion library](./test-utils.md). ### API design -Lucid aims for simplicity, while CTL allows more fine-grained control over transaction building process. +Lucid aims for simplicity, while CTL allows more fine-grained control over transaction building process without losing the benefits of declarativeness. -- CTL uses [`cardano-serialization-lib`](https://github.com/Emurgo/cardano-serialization-lib/), while Lucid uses a fork of [`cardano-multiplatform-lib`](https://github.com/berry-pool/cardano-multiplatform-lib). Lucid allows to use CML's `TxBuilder` or [call CML directly](https://lucid.spacebudz.io/docs/advanced/cml/), while CTL allows to alter the transaction arbitrarily as PureScript data type either before or after balancing. In CTL, CSL types and method wrappers are a part of the internal interface, but technically they can be used as well. +- CTL uses [`cardano-serialization-lib`](https://github.com/Emurgo/cardano-serialization-lib/), while Lucid uses a fork of [`cardano-multiplatform-lib`](https://github.com/berry-pool/cardano-multiplatform-lib). Lucid allows to use CML's `TxBuilder` or [call CML directly](https://lucid.spacebudz.io/docs/advanced/cml/), while CTL allows to alter the transaction arbitrarily as PureScript data type either before or after balancing. +- In CTL, CSL types and method wrappers are used via [`purescript-cardano-serialization-lib`](https://github.com/mlabs-haskell/purescript-cardano-serialization-lib) and [`purescript-cardano-types`](https://github.com/mlabs-haskell/purescript-cardano-types). However, `TxBuilder` APIs from CSL are not provided by these packages. - Plutus Data conversion is handled via a [schema-enabled API](https://lucid.spacebudz.io/docs/advanced/type-casting/) in Lucid. CTL allows for automatic `ToData` / `FromData` deriving for some types, via `HasPlutusSchema`. diff --git a/doc/ctl-as-dependency.md b/doc/ctl-as-dependency.md index 0be2285aec..cef520e0ad 100644 --- a/doc/ctl-as-dependency.md +++ b/doc/ctl-as-dependency.md @@ -6,30 +6,22 @@ CTL can be imported as an additional dependency into a Purescript project built -- [Caveats](#caveats) -- [Using CTL's overlays](#using-ctls-overlays) +- [Using CTL's Nix overlays](#using-ctls-nix-overlays) - [Upgrading CTL](#upgrading-ctl) - [See also](#see-also) -## Caveats - -The following caveats alway applies when using CTL from your project: - -1. Only bundling with Webpack is supported (this is due to our internal dependency on `cardano-serialization-lib` which uses WASM with top-level `await`; only Webpack is reliably capable of bundling this properly) -2. The environment variable `BROWSER_RUNTIME` determines which version of `cardano-serialization-lib` is loaded by CTL, so you must use it as well (i.e. set it to `1` for the browser; leave it unset for NodeJS) - -## Using CTL's overlays +## Using CTL's Nix overlays CTL exposes two `overlay`s from its flake. You can use these in the Nix setup of your own project to use the same setup as we do, e.g. the same packages and PS builders: -- `overlays.purescript` contains Purescript builders to compile Purescript sources, build bundles with Webpack (`bundlePursProject`), run unit tests using NodeJS (`runPursTest`), and run CTL contracts on a private testnet using Plutip (`runPlutipTest`). -- `overlays.runtime` contains various packages and other tools used in CTL's runtime, including `ogmios`, `kupo`, and `plutip-server`. It also defines `buildCtlRuntime` and `launchCtlRuntime` to help you quickly launch all runtime services (see the [runtime docs](./runtime.md)) +- `overlays.purescript` contains Purescript builders to compile Purescript sources, build bundles with Webpack/esbuild (`bundlePursProject`), run unit tests using NodeJS (`runPursTest`), and run CTL contracts using Cardano Testnet (`runLocalTestnetTest`). +- `overlays.runtime` contains various packages and other tools used in CTL's runtime, including `ogmios`, `kupo`, and `cardano-node`. It also defines `buildCtlRuntime` and `launchCtlRuntime` to help you quickly launch all runtime services (see the [runtime docs](./runtime.md)) We've split the overlays into two components to allow users to more easily choose which parts of CTL's Nix infrastructure they would like to directly consume. For example, some users do not require a pre-packaged runtime and would prefer to build it themselves with more control over its components (e.g. by directly using `ogmios` from their own `inputs`). Such users might still like to use our `purescript` overlay -- splitting the `overlays` allows us to support this. `overlays.runtime` also contains several haskell.nix packages which may cause issues with `hackage.nix` versions in your own project. -Do note that `runPlutipTest` in `overlays.purescript` requires the presence of all of our runtime components. If you choose not to consume `overlays.runtime`, please ensure that your package set contains these (e.g. by adding them to your own `overlays` when instantiating `nixpkgs`). You can find a complete list of the required runtime services [here](./plutip-testing.md#architecture). +Do note that `runLocalTestnetTest` in `overlays.purescript` requires the presence of all of our runtime components. If you choose not to consume `overlays.runtime`, please ensure that your package set contains these (e.g. by adding them to your own `overlays` when instantiating `nixpkgs`). You can find a complete list of the required runtime services [here](./cardano-testnet-testing.md#architecture). To see an example project that uses both `overlays`, please refer to our [scaffolding template](../templates/ctl-scaffold/flake.nix). You can also use this template to conveniently initialize a new CTL-based project (`nix flake init -t github:Plutonomicon/cardano-transaction-lib` in a new directory). It will take a significant amount of time for spago to download the dependencies. @@ -75,14 +67,12 @@ Make sure to perform **all** of the following steps, otherwise you **will** enco 3. **Update your JS dependencies** -- If CTL has added any JS dependencies, these will also need to be added to your own `package.json` -- Similarly, if any of CTL's JS dependencies have changed versions, you will need to use the **exact** same version in your own `package.json` -- That is, avoid using the `~` or `^` prefixes (e.g use versions like `"1.6.51"` instead of `"^1.6.51"`) -- If you're using a `package-lock.json` (which is _highly_ recommended), you can update the lockfile with `npm i --package-lock-only` +- The NPM dependencies your project has must have the exact same versions CTL's own `package.json` specifies. +- You have to update `package-lock.json` by running `npm install`. If you are in a nix shell and use our setup that symlinks `./node_modules`, npm will complain about inability to write to the filesystem, use `npm i --package-lock-only` to skip writing to `node_modules`. If your `node_modules` are managed by Nix, you will have to re-enter the shell for the changes to apply. -4. **Update your webpack config** +4. **Update your webpack/esbuild config** -- Sometimes the WebPack configuration also comes with breaking changes. Common source of problems are changes to `resolve.fallback`, `plugins` and `experiments` fields of the WebPack config. Use `git diff old-revision new-revision webpack.config.js` in the root of a cloned CTL repo, or use `git blame`. +- Sometimes WebPack or esbuild configurations also come with breaking changes. Refer to the CHANGELOG. ## See also diff --git a/doc/development.md b/doc/development.md index 8928d5c6ab..08e7cd8305 100644 --- a/doc/development.md +++ b/doc/development.md @@ -22,6 +22,7 @@ This document outlines development workflows for CTL itself. You may also wish t - [JS](#js) - [Switching development networks](#switching-development-networks) - [Maintaining the template](#maintaining-the-template) +- [Updating the template](#updating-the-template) @@ -73,20 +74,20 @@ To **build** the project **without bundling and for a NodeJS environment**: - `npm run unit-test` for unit tests (no need for a runtime) - [entry point](../test/Unit.purs) - `npm run integration-test` for integration tests (requires a [runtime](./runtime.md#ctl-backend)) - [entry point](../test/Integration.purs) -- `npm run plutip-test` for Plutip integration tests (does not require a runtime) - [entry point](../test/Plutip.purs) -- `npm run staking-test` to run [Plutip](./plutip-testing.md)-powered tests for ADA staking functionality - [entry point](../test/Plutip/Staking.purs) +- `npm run testnet-test` for Cardano Testnet integration tests (does not require a runtime) - [entry point](../test/Testnet.purs) +- `npm run staking-test` to run [Cardano Testnet](./cardano-testnet-testing.md)-powered tests for ADA staking functionality - [entry point](../test/Testnet/Staking.purs) - `npm run blockfrost-test` for [Blockfrost-powered tests](./blockfrost.md) (does not require a runtime, but needs [some setup](./blockfrost.md#setting-up-a-blockfrost-powered-test-suite)) - [entry point](../test/Blockfrost/Contract.purs) - `npm run blockfrost-local-test` for self-hosted [Blockfrost-powered tests](./blockfrost.md) (requires a [local Blockfrost runtime](./blockfrost.md#running-blockfrost-locally)) - [entry point](../test/Blockfrost/Contract.purs) -- `npm run e2e-test` for [tests with a headless browser](./e2e-testing.md) (requires a runtime and the tests served via HTTP: `npm run start-runtime` and `npm run webpack-serve` or `esbuild-serve`) +- `npm run e2e-test` for [tests with a headless browser](./e2e-testing.md) (requires a runtime and the tests served via HTTP: `npm run start-runtime` and `npm run e2e-serve` or `esbuild-serve`) #### With Nix Here and below, `` should be replaced with [one of the supported systems](https://github.com/Plutonomicon/cardano-transaction-lib/blob/15fd9c5b683df47134dce4a0479f1edc30d4b6f7/flake.nix#L51) that you use, e.g. `x86_64-linux`. - Unit tests: `nix build .#checks..ctl-unit-test` -- [E2E tests in Nix with wallet mocks](./e2e-testing.md#using-cip-30-mock-with-plutip): `nix build -L .#checks..ctl-e2e-test` -- Contract tests ([Plutip](./plutip-testing.md)): `nix build -L .#checks..ctl-plutip-test` -- [Staking](./staking.md) tests ([Plutip](./plutip-testing.md)): `nix build -L .#checks..ctl-staking-test` +- [E2E tests in Nix with wallet mocks](./e2e-testing.md#using-cip-30-mock-with-cardano-testnet): `nix build -L .#checks..ctl-e2e-test` +- Contract tests ([Cardano Testnet](./cardano-testnet-testing.md)): `nix build -L .#checks..ctl-local-testnet-test` +- [Staking](./staking.md) tests ([Cardano Testnet](./cardano-testnet-testing.md)): `nix build -L .#checks..ctl-staking-test` #### Nix checks @@ -100,14 +101,14 @@ Here and below, `` should be replaced with [one of the supported systems To run or build/bundle the project for the browser: -- `npm run webpack-serve` will start a Webpack development server at `localhost:4008`, which is required for [E2E tests](./e2e-testing.md) +- `npm run {webpack|esbuild}-serve` will start a Webpack development server at `localhost:4008`, which is required for [E2E tests](./e2e-testing.md) - `npm run {webpack|esbuild}-bundle` will output a bundled example module to `dist` (or `nix build -L .#ctl-example-bundle-web-{webpack|esbuild}` to build an example module using Nix into `./result/`) -By default, Webpack will build a [Purescript module](../examples/ByUrl.purs) that serves multiple example `Contract`s depending on URL (see [here](./e2e-testing.md#serving-the-contract-to-be-tested)). You can point Webpack to another Purescript entrypoint by changing the `ps-bundle` variable in the Makefile or in the `main` argument in the flake's `packages.ctl-examples-bundle-web`. +By default, the bundler will build a [Purescript module](../examples/ByUrl.purs) that serves multiple example `Contract`s depending on URL (see [here](./e2e-testing.md#serving-the-contract-to-be-tested)). You can point the bundler to another Purescript entrypoint by changing the `ps-bundle` variable in the Makefile or in the `main` argument in the flake's `packages.ctl-examples-bundle-web`. -You will also need a light wallet extension pre-configured to run a `Contract`. +You will also need a light wallet extension pre-configured for the correct Cardano network to run a `Contract`. -**Note**: The `BROWSER_RUNTIME` environment variable must be set to `1` in order to build/bundle the project properly for the browser (e.g. `BROWSER_RUNTIME=1 webpack ...`). For Node environments, leave this variable unset. +**Note**: The `BROWSER_RUNTIME` environment variable must be set to `1` in order to build/bundle the project properly for the browser (e.g. `BROWSER_RUNTIME=1 webpack ...`). For NodeJS environments, leave this variable unset. **Note**: The `KUPO_HOST` environment variable must be set to the base URL of the Kupo service in order to successfully serve the project for the browser (by default, `KUPO_HOST=http://localhost:1442`). @@ -148,4 +149,13 @@ Set new `network.name` and `network.magic` in `runtime.nix`. Also see [Changing [The template](../templates/ctl-scaffold/) must be kept up-to-date with the repo. Although there are some checks for common problems in CI, it's still possible to forget to update the `package-lock.json` file. +## Updating the template + +1. Update the revision of CTL in the template's `flake.nix` +2. Update the npm packages in the `package.json` (if needed) +3. Run `npm i` to update the lockfile (if there are NPM dependency version changes) +4. Update the revisions in the template's `packages.dhall` (CTL version must match the one in `flake.nix`) +5. Run `spago2nix generate` +6. Run `nix develop` + [This helper script](../scripts/template-check.sh) can be used to make sure the template can be initialized properly from a given revision. diff --git a/doc/e2e-testing.md b/doc/e2e-testing.md index 402388558c..2aa978b280 100644 --- a/doc/e2e-testing.md +++ b/doc/e2e-testing.md @@ -22,7 +22,7 @@ CTL comes with advanced machinery for E2E testing in the browser, which can be u - [Using custom unauthorized extensions](#using-custom-unauthorized-extensions) - [Serving the Contract to be tested](#serving-the-contract-to-be-tested) - [Mocking CIP-30 interface](#mocking-cip-30-interface) - - [Using CIP-30 mock with Plutip](#using-cip-30-mock-with-plutip) + - [Using CIP-30 mock with Cardano Testnet](#using-cip-30-mock-with-cardano-testnet) @@ -112,6 +112,7 @@ The tests can set up using CLI arguments, environment variables, or both. CLI ar | Test timeout | `--test-timeout` | `E2E_TEST_TIMEOUT` | | Browser binary path or name | `--browser` | `E2E_BROWSER` | | Don't use headless mode | `--no-headless` | `E2E_NO_HEADLESS` | +| Pass browser logs to the shell console | `--pass-browser-logs` | `E2E_PASS_BROWSER_LOGS` | | Path to the user settings archive | `--settings-archive` | `E2E_SETTINGS_ARCHIVE` | | URL of settings archive asset | `--settings-archive-url` | `E2E_SETTINGS_ARCHIVE_URL` | | Path to the user data directory | `--chrome-user-data` | `E2E_CHROME_USER_DATA` | @@ -292,9 +293,9 @@ The `nami:` prefix should not be specified, otherwise CTL will refuse to overwri In order to use the keys, their corresponding address must be pre-funded using the [faucet](https://docs.cardano.org/cardano-testnet/tools/faucet) (beware of IP-based rate-limiting) or from another wallet. Most contracts require at least two UTxOs to run (one will be used as collateral), so it's best to make two transactions. -### Using CIP-30 mock with Plutip +### Using CIP-30 mock with Cardano Testnet -It's possible to run headless browser tests on top of a temporary plutip cluster. In this case, key generation and pre-funding will be handled by `plutip-server`, as well as deployment of all the query layer services. +It's possible to run headless browser tests on top of a Cardano Testnet cluster. To do that, it's enough to define a config name that: @@ -306,10 +307,10 @@ E.g.: ```purescript wallets :: Map E2EConfigName (ContractParams /\ Maybe WalletMock) wallets = Map.fromFoldable - [ "plutip-nami-mock" /\ mainnetNamiConfig /\ Just MockNami - , "plutip-gero-mock" /\ mainnetGeroConfig /\ Just MockGero - , "plutip-flint-mock" /\ mainnetFlintConfig /\ Just MockFlint - , "plutip-lode-mock" /\ mainnetLodeConfig /\ Just MockLode + [ "testnet-nami-mock" /\ mainnetNamiConfig /\ Just MockNami + , "testnet-gero-mock" /\ mainnetGeroConfig /\ Just MockGero + , "testnet-flint-mock" /\ mainnetFlintConfig /\ Just MockFlint + , "testnet-lode-mock" /\ mainnetLodeConfig /\ Just MockLode ] ``` @@ -326,4 +327,4 @@ Full example can be found [in the template](../templates/ctl-scaffold/test/E2E.p There are a few important caveats/limitations: - We only allow base addresses (with a stake pubkey hash present) to be used. If there's a need to use enterprise addresses, the users should move some ada to their own enterprise address, e.g. with `mustPayToPubKey` -- The amount of tAda is fixed to `1000000000000` and divided into 5 UTxOs equally +- The amount of tAda is fixed to `25_000_000_000` lovelace and divided into 5 UTxOs equally diff --git a/doc/faq.md b/doc/faq.md index e92226e6d2..14be88ea7c 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -8,6 +8,7 @@ This document lists common problems encountered by CTL users and developers. - [Bundling-related](#bundling-related) - [Q: `lib.something` is not a function, why?](#q-libsomething-is-not-a-function-why) + - [Q: `Module parse failed: 'import' and 'export' may appear only with 'sourceType: module'` error?](#q-module-parse-failed-import-and-export-may-appear-only-with-sourcetype-module-error) - [Q: I see `spago: Error: Remote host not found`, why?](#q-i-see-spago-error-remote-host-not-found-why) - [Q: I see `WebAssembly module is included in initial chunk.` error, why?](#q-i-see-webassembly-module-is-included-in-initial-chunk-error-why) - [Q: I see `Cannot use 'import.meta' outside a module` error in the browser, why?](#q-i-see-cannot-use-importmeta-outside-a-module-error-in-the-browser-why) @@ -27,7 +28,6 @@ This document lists common problems encountered by CTL users and developers. - [Package 'chromium-105.0.5195.125' is not supported on 'x86_64-darwin'](#package-chromium-10505195125-is-not-supported-on-x86_64-darwin) - [Miscellaneous](#miscellaneous) - [Q: Why am I getting `Error: (AtKey "coinsPerUtxoByte" MissingValue)`?](#q-why-am-i-getting-error-atkey-coinsperutxobyte-missingvalue) - - [Q: Why do I get an error from `foreign.js` when running Plutip tests locally?](#q-why-do-i-get-an-error-from-foreignjs-when-running-plutip-tests-locally) - [Q: How can I write my own Nix derivations using the project returned by `purescriptProject`?](#q-how-can-i-write-my-own-nix-derivations-using-the-project-returned-by-purescriptproject) @@ -39,6 +39,10 @@ This is probably because npm is used directly. This is something users have repo You can prevent `npm` from ever installing to local `node_modules` by enabling the `packageLockOnly` flag in the `shell` argument to `purescriptProject`. When enabled, `npm i` will always act as if the `--package-lock-only` flag has been passed. This is not enabled by default, but we recommend enabling it. +### Q: `Module parse failed: 'import' and 'export' may appear only with 'sourceType: module'` error? + +Make sure you've specified `"type": "module"` in your project's `package.json`. + ### Q: I see `spago: Error: Remote host not found`, why? An error like this one: @@ -78,7 +82,9 @@ Another thing to keep in mind is that due to [min-ada requirements](https://docs CTL does not consume wallet collateral normally, but it still can happen. -In order to get the collateral UTxO, CTL uses the wallet and then marks the returned UTxO as locked internally. But some wallets (e.g. Gero) do not return the collateral the moment it is set, waiting for Tx confirmation first. In case a collateral is set right before the contract is started, CTL can accidentally spend the collateral, because we rely on CTL's own query layer to get a list of available UTxOs, and the wallet state may lag behind it, not returning the collateral to filter out at that moment. +In order to get the collateral UTxO, CTL uses the wallet and then marks the returned UTxO as "locked" internally. But some wallets (e.g. Gero) do not return the collateral the moment it is set, waiting for Tx confirmation first. In case a collateral is set right before the contract is started, CTL can accidentally spend the collateral, because we rely on CTL's own query layer to get a list of available UTxOs without consulting with the wallet [in some cases](./query-layers.md), and the wallet state may lag behind the backend state. + +It is impossible to lose the collateral UTxO funds completely, though, because CTL always uses [CIP-40 collateral return](https://cips.cardano.org/cip/CIP-0040). ## Time-related @@ -92,8 +98,6 @@ To do anything time-related, it's best to rely on local node chain tip time, ins Time/slot conversion functions depend on `eraSummaries` [Ogmios local state query](https://ogmios.dev/mini-protocols/local-state-query/), that returns era bounds and slotting parameters details, required for proper slot arithmetic. The most common source of the problem is that Ogmios does not return enough epochs into the future. [A possible symptom](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1057) is `CannotFindTimeInEraSummaries` in the error message. -When using Plutip, a solution may be [to increase the `epochSize` parameter](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1057#issuecomment-1450692539). - ### Q: I'm getting `Uncomputable slot arithmetic; transaction's validity bounds go beyond the foreseeable end of the current era: PastHorizon` Ensure your transaction's validity range does not go over `SafeZone` slots of the current era. The reason for this kind of errors is that time-related estimations are slot-based, and future forks may change slot lengths. So there is only a relatively small time window in the future during which it is known that forks cannot occur. @@ -161,10 +165,6 @@ To disable, set `withChromium` to `false` in [`purescriptProject`'s `shell` argu This is because the node hasn't fully synced. The protocol parameter name changed from `coinsPerUtxoWord` to `coinsPerUtxoByte` in Babbage. CTL only supports the latest era, but Ogmios returns different protocol parameters format depending on current era of a local node. -### Q: Why do I get an error from `foreign.js` when running Plutip tests locally? - -The most likely reason for this is that spawning the external processes from `Contract.Test.Plutip` fails. Make sure that all of the required services are on your `$PATH` (see more [here](./runtime.md); you can also set `shell.withRuntime = true;` to ensure that these are always added to your shell environment when running `nix develop`). - ### Q: How can I write my own Nix derivations using the project returned by `purescriptProject`? If the different derivation builders that `purescriptProject` gives you out-of-the-box (e.g. `runPursTest`, `bundlePursProject`, etc...) are not sufficient, you can access the compiled project (all of the original `src` argument plus the `output` directory that `purs` produces) and the generated `node_modules` using the `compiled` and `nodeModules` attributes, respectively. These can be used to write your own derivations without needing to recompile the entire project (that is, the generated output can be shared between all of your Nix components). For example: diff --git a/doc/getting-started.md b/doc/getting-started.md index f758fa8472..31dbbfca3a 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -16,11 +16,6 @@ This guide will help you get started writing contracts with CTL. Please also see - [Executing contracts and the `ContractEnv`](#executing-contracts-and-the-contractenv) - [Making the `ContractEnv`](#making-the-contractenv) - [Building and submitting transactions](#building-and-submitting-transactions) - - [Using compiled scripts](#using-compiled-scripts) -- [Testing](#testing) - - [Without a light wallet](#without-a-light-wallet) - - [With a light wallet](#with-a-light-wallet) - - [Plutip integration](#plutip-integration) @@ -56,7 +51,7 @@ You can learn more about using CTL as a dependency [here](./ctl-as-dependency.md ### Other prerequisites -You will also need to become familiar with [CTL's runtime](./runtime.md) as its runtime services are required for executing virtually all contracts. +You will also need to become familiar with [CTL's runtime](./runtime.md) as its runtime services are required for executing virtually all contracts. If you want to avoid manual backend setup, use [blockfrost.io](./blockfrost.md). ## Importing CTL modules @@ -140,9 +135,13 @@ main = Contract.Monad.launchAff_ do -- we re-export this for you , kupoConfig: defaultKupoServerConfig } , networkId: TestnetId - , logLevel: Trace , walletSpec: Just ConnectToNami + , logLevel: Trace , customLogger: Nothing + , suppressLogs: false + , hooks: emptyHooks + , timeParams: defaultTimeParams + , synchronizationParams: defaultSynchronizationParams } runContract config someContract @@ -167,49 +166,49 @@ customOgmiosWsConfig = Unlike PAB, CTL obscures less of the build-balance-sign-submit pipeline for transactions and most of the steps are called individually. The general workflow in CTL is similar to the following: -- Build a transaction using `Contract.ScriptLookups`, `Contract.TxConstraints` and `Contract.BalanceTxConstraints` (it is also possible to directly build a `Transaction` if you require even greater low-level control over the process, although we recommend the constraints/lookups approach for most users): +- Build a transaction using [`cardano-transaction-builder`](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder): ```purescript contract = do let - constraints :: TxConstraints Unit Unit - constraints = - TxConstraints.mustPayToScript vhash unitDatum - (Value.lovelaceValueOf $ BigInt.fromInt 2_000_000) - - lookups :: ScriptLookups PlutusData - lookups = ScriptLookups.validator validator - - balanceTxConstraints :: BalanceTxConstraints.BalanceTxConstraintsBuilder - balanceTxConstraints = - BalanceTxConstraints.mustUseUtxosAtAddress address - <> BalanceTxConstraints.mustSendChangeToAddress address - <> BalanceTxConstraints.mustNotSpendUtxoWithOutRef nonSpendableOref - - -- `liftedE` will throw a runtime exception on `Left`s - unbalancedTx <- liftedE $ Lookups.mkUnbalancedTx lookups constraints + plan = + [ Pay $ TransactionOutput + { address: address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 1_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + unbalancedTx <- buildTx plan ... ``` -- Balance it using `Contract.Transaction.balanceTx` (or `Contract.Transaction.balanceTxWithConstraints` if you need to adjust the balancer behaviour) and then sign it using `signTransaction`: +- Balance it using `Contract.Transaction.balanceTx`, and then sign it using `signTransaction`: ```purescript contract = do ... + let + balanceTxConstraints :: BalanceTxConstraints.BalanceTxConstraintsBuilder + balanceTxConstraints = + BalanceTxConstraints.mustUseUtxosAtAddress address + <> BalanceTxConstraints.mustSendChangeToAddress address + <> BalanceTxConstraints.mustNotSpendUtxoWithOutRef nonSpendableOref -- `liftedE` will throw a runtime exception on `Left`s balancedTx <- - liftedE $ balanceTxWithConstraints unbalancedTx balanceTxConstraints + balanceTx unbalancedTx usedUtxos balanceTxConstraints balancedSignedTx <- signTransaction balancedTx ... ``` -- Submit using `Contract.Transaction.submit`: +- Submit using `Contract.Transaction.submit` and await for confirmation using `awaitTxConfirmed`: ```purescript contract = do ... txId <- submit balancedSignedTx + awaitTxConfirmed txId logInfo' $ "Tx ID: " <> show txId - ``` +``` ### Using compiled scripts @@ -227,6 +226,6 @@ See [here](./key-management.md) For full testing with browser-based light wallets see [E2E Testing in the Browser](./e2e-testing.md). -### Plutip integration +### Cardano Testnet integration -Plutip is a tool for testing contracts on a local testnet. See [CTL integration with Plutip](./plutip-testing.md). +See [CTL integration with Cardano Testnet](./cardano-testnet-testing.md). diff --git a/doc/importing-scripts.md b/doc/importing-scripts.md index 0e44ae2371..5d6461789d 100644 --- a/doc/importing-scripts.md +++ b/doc/importing-scripts.md @@ -6,11 +6,11 @@ - [Exporting scripts from Plutus or Plutarch](#exporting-scripts-from-plutus-or-plutarch) - [Using Plutonomy](#using-plutonomy) -- [Importing serialized scripts](#importing-serialized-scripts) - [Serializing Plutus scripts](#serializing-plutus-scripts) - [PlutusTx](#plutustx) - [Plutarch](#plutarch) - [plutarch-ctl-bridge](#plutarch-ctl-bridge) +- [Importing serialized scripts](#importing-serialized-scripts) @@ -31,7 +31,6 @@ The output file should be a Cardano envelope: - An example of a Plutus exporter can be found [here](https://github.com/Mr-Andersen/ctl-multisign-mre/blob/main/onchain/exporter/Main.hs). - For Plutarch, see [the-plutus-scaffold](https://github.com/mlabs-haskell/the-plutus-scaffold)'s [exporter](https://github.com/mlabs-haskell/the-plutus-scaffold/tree/main/onchain/exporter). - ### Using Plutonomy It makes sense to use [Plutonomy](https://github.com/well-typed/plutonomy) (an optimizer for UPLC) in the exporter: @@ -44,91 +43,6 @@ script = fromCompiledCode $ optimizeUPLCWith aggressiveOptimizerOptions $$(PlutusTx.compile [||policy||]) ``` -## Importing serialized scripts - -To use your own scripts, compile them to any subdirectory in the root of your project (where `webpack.config.js` is located) and add a relative path to `webpack.config.js` under the `resolve.alias` section. In CTL, we have the `Scripts` alias for this purpose. Note the capitalization of `Scripts`: it is necessary to disambiguate it from local folders. - -First, in your `webpack.config.js`, define an `alias` under `module.exports.resolve.alias` in order to `require` the compiled scripts from JS modules: - -```javascript -const path = require("path"); - -module.exports = { - // ... - resolve: { - modules: [process.env.NODE_PATH], - extensions: [".js"], - fallback: { - // ... - }, - alias: { - // You should update this path to the location of your compiled scripts, - // relative to `webpack.config.js` - Scripts: path.resolve(__dirname, "fixtures/scripts"), - }, - }, -}; -``` - -You must also add the following to `module.exports.module.rules`: - -```javascript -module.exports = { - // ... - module: { - rules: [ - { - test: /\.plutus$/i, - type: "asset/source", - }, - // ... - ], - }, -}; -``` - -This enables inlining your serialized scripts in `.js` files, to then be loaded in Purescript via the FFI: - -```javascript -// inline .plutus file as a string -exports.myscript = require("Scripts/myscript.plutus"); -``` - -And on the purescript side, the script can be loaded like so: - -```purescript -foreign import myscript :: String - -parseValidator :: Contract Validator -parseValidator = liftMaybe (error "Error decoding myscript") do - envelope <- decodeTextEnvelope myscript - Validator <$> Contract.TextEnvelope.plutusScriptV1FromEnvelope envelope -myContract cfg = runContract_ cfg $ do - validator <- parseValidator - ... -``` - -This way you avoid hardcoding your scripts directly to .purs files which could lead to synchronization issues should your scripts change. - -**Note**: The `alias` method above will only work in the browser when bundling with Webpack. In order to load the scripts for both browser and NodeJS environments, you can use the `BROWSER_RUNTIME` environment variable like so: - -```javascript -let script; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - script = require("Scripts/my-script.plutus"); -} else { - const fs = require("fs"); - const path = require("path"); - script = fs.readFileSync( - path.resolve(__dirname, "../../fixtures/scripts/my-script.plutus"), - "utf8" - ); -} -exports.myScript = script; -``` - -Note that the relative path passed to `path.resolve` for the NodeJS case starts from the `output` directory that the Purescript compiler produces. - ## Serializing Plutus scripts ### PlutusTx @@ -176,3 +90,7 @@ You can use [`ply`](https://github.com/mlabs-haskell/ply) and [`ply-ctl`](https: ### plutarch-ctl-bridge You can use [`plutarch-ctl-bridge`](https://github.com/mlabs-haskell/plutarch-ctl-bridge) to generate Purescript types from your Haskell type definitions and typed script wrappers from parametrized Plutarch scripts. See [example module](https://github.com/mlabs-haskell/plutarch-ctl-bridge/blob/main/example/Main.hs). + +## Importing serialized scripts + +To use your own scripts, compile them to any subdirectory in the root of your project and either dynamically load them from file (NodeJS) or use your bundler to include them as fixtures into the bundle ([instructions for WebPack](https://webpack.js.org/guides/asset-modules/), [for esbuild](https://esbuild.github.io/content-types/#external-file)). diff --git a/doc/key-management.md b/doc/key-management.md index f4635b65c5..65d95fe08d 100644 --- a/doc/key-management.md +++ b/doc/key-management.md @@ -66,7 +66,7 @@ Contract.Wallet.Key.mkKeyWalletFromMnemonic :: String -> Cip1852DerivationPath -> StakeKeyPresence -> Either String KeyWallet ``` -`Contract.Wallet.withKeyWalletFromMnemonic` is another helper function that lets to construct and use wallets on the fly, which is convenient for [Plutip tests](./plutip-testing.md). +`Contract.Wallet.withKeyWalletFromMnemonic` is another helper function that lets to construct and use wallets on the fly, which is convenient for [Cardano Testnet tests](./cardano-testnet-testing.md). In `ContractParams`, these values can be conveniently passed as the `walletSpec` via the `UseMnemonic` constructor: diff --git a/doc/keydir.md b/doc/keydir.md index 1afbe8ddd2..b933f02ba3 100644 --- a/doc/keydir.md +++ b/doc/keydir.md @@ -1,4 +1,4 @@ -# Keydir backend +# Running tests using a directory with private keys @@ -7,6 +7,7 @@ - [Generating private keys](#generating-private-keys) - [Funding your address](#funding-your-address) - [Setting up a directory for temporary keys](#setting-up-a-directory-for-temporary-keys) + - [See also](#see-also) @@ -73,6 +74,10 @@ directories. We don't dispose of the keys automatically, as there may be some on-chain state that's uniquely tied to them, which the user might not want to lose access to. +### See also + +- [Blockfrost-powered test suite](./blockfrost.md) for an example of how to use key-directory-based test suite with Blockfrost. + [mote]: https://github.com/garyb/purescript-mote [cardano-handbook-keys-addresses]: https://developers.cardano.org/docs/stake-pool-course/handbook/keys-addresses [ctl-generate-keys]: https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/scripts/generate-keys.sh diff --git a/doc/plutip-testing.md b/doc/plutip-testing.md index 85b11fd32d..a245dcdaff 100644 --- a/doc/plutip-testing.md +++ b/doc/plutip-testing.md @@ -1,322 +1,13 @@ -# CTL integration with Plutip - -[Plutip](https://github.com/mlabs-haskell/plutip) is a tool to run private Cardano testnets. CTL provides integration with Plutip via [`plutip-server` binary](https://github.com/Plutonomicon/cardano-transaction-lib/tree/develop/plutip-server) that exposes an HTTP interface to control local Cardano clusters. - -**Table of Contents** -- [Architecture](#architecture) -- [Testing contracts](#testing-contracts) - - [Testing with Mote](#testing-with-mote) - - [Overview](#overview) - - [Using Mote testing interface](#using-mote-testing-interface) - - [Internal implementation overview](#internal-implementation-overview) - - [Testing in Aff context](#testing-in-aff-context) - - [Writing checks in tests](#writing-checks-in-tests) - - [Note on running clusters](#note-on-running-clusters) - - [Note on SIGINT](#note-on-sigint) - - [Testing with Nix](#testing-with-nix) -- [Cluster configuration options](#cluster-configuration-options) - - [Current limitations](#current-limitations) -- [Using addresses with staking key components](#using-addresses-with-staking-key-components) -- [Limitations](#limitations) -- [See also](#see-also) +- [CTL integration with Plutip](#ctl-integration-with-plutip) -## Architecture - -CTL depends on a number of binaries in the `$PATH` to execute Plutip tests: - -- `plutip-server` to launch a local `cardano-node` cluster -- [`ogmios`](https://ogmios.dev/) -- [`kupo`](https://cardanosolutions.github.io/kupo/) - -All of these are provided by CTL's `overlays.runtime` (and are provided in CTL's own `devShell`). You **must** use the `runtime` overlay or otherwise make the services available in your package set (e.g. by defining them within your own `overlays` when instantiating `nixpkgs`) as `purescriptProject.runPlutipTest` expects all of them; an example of using CTL's overlays is in the [`ctl-scaffold` template](../templates/ctl-scaffold/flake.nix#L35). - -The services are NOT run by `docker-compose` (via `arion`) as is the case with `launchCtlRuntime`: instead they are started and stopped on each CTL `ContractTest` execution by CTL itself. - -If you have based your project on the [`ctl-scaffold` template](../templates/ctl-scaffold) then you have two options to run Plutip tests: -1. `nix develop` followed by `npm run test` (recommended for development) -2. `nix run .#checks.x86_64-linux.ctl-scaffold-plutip-test` - * where you'd usually replace `x86_64-linux` with the system you run tests on - * and `ctl-scaffold-plutip-test` with the name of the plutip test derivation for your project; - * note that building of your project via Nix will fail in case there are any PureScript compile-time warnings. - -## Testing contracts - -CTL can help you test the offchain `Contract`s from your project (and consequently the interaction of onchain and offchain code) by spinning up a disposable private testnet via Plutip and making all your `Contract`s interact with it. - -There are two approaches to writing such tests. - -### Testing with Mote - -#### Overview - -[Mote](https://github.com/garyb/purescript-mote) is a DSL for defining and grouping tests (plus other quality of life features, e.g. skipping marked tests). - -First (and more widely used) approach is to first build a tree of tests (in CTL's case a tree of `ContractTest` types -- basically a function from some distribution of funds to a `Contract a`) via Mote and then use the `Contract.Test.Plutip.testPlutipContracts` function to execute them. -This allows to set up a Plutip cluster only once per top-level groups and tests passed to the `testPlutipContracts` and then use it in many independent tests. -The function will interpret a `MoteT` (effectful test tree) into `Aff`, which you can then actually run. - -The [`ctl-scaffold` template](../templates/ctl-scaffold) provides a simple `Mote`-based example. - -`Contract.Test.Plutip.testPlutipContracts` type is defined as follows: -```purescript -testPlutipContracts - :: PlutipConfig - -> TestPlanM ContractTest Unit - -> TestPlanM (Aff Unit) Unit -``` - -It takes a plutip config and a tree of Mote tests, where tests are of type `ContractTest`. - -To create tests of type `ContractTest`, you should either use `Contract.Test.Plutip.withWallets` or `Contract.Test.Plutip.noWallet`: - -```purescript -withWallets - :: forall (distr :: Type) (wallets :: Type) - . UtxoDistribution distr wallets - => distr - -> (wallets -> Contract Unit) - -> ContractTest - -noWallet :: Contract Unit -> ContractTest -noWallet test = withWallets unit (const test) -``` - -Usage of `testPlutipContracts` is similar to that of `runPlutipContract`, and distributions are handled in the same way. Here's an example: - -```purescript -suite :: MoteT Aff (Aff Unit) Aff -suite = testPlutipContracts config do - test "Test 1" do - let - distribution :: Array BigInt /\ Array BigInt - distribution = ... - withWallets distribution \(alice /\ bob) -> do - ... - - test "Test 2" do - let - distribution :: Array BigInt - distribution = ... - withWallets distribution \alice -> do - ... - - test "Test 3" do - noWallet do - ... -``` - -#### Using Mote testing interface - -To define tests suites you can use `test`, group them with `group` and also wrap tests or groups with `bracket` to execute custom actions before and after tests/groups that are inside the bracket. -Note that in Mote you can define several tests and several groups in a single block, and bracket that wraps them will be run for each such test or group. - -Internally `testPlutipContracts` places a bracket that sets up the CTL environment and starts up the Plutip cluster on the top level, so if you want to launch cluster only once wrap your tests or groups in a single group. -In the example above the environment and cluster setup will happen 3 times. - -#### Internal implementation overview - -`Contract.Test.Plutip.testPlutipContracts` type is defined as follows (after expansion of the CTL's `TestPlanM` type synonym): -```purescript -type TestPlanM :: Type -> Type -> Type -type TestPlanM test a = MoteT Aff test Aff a - -testPlutipContracts - :: PlutipConfig - -> MoteT Aff ContractTest Aff Unit - -> MoteT Aff (Aff Unit) Aff Unit - --- Recall that `MoteT` has three type variables -newtype MoteT bracket test m a -``` -where -* `bracket :: Type -> Type` is where brackets will be run (before/setup is `bracket r` and after/shutdown is of type `r -> bracket Unit`), - * in our case it's `Aff` and is where the CTL environment and Plutip cluster setup will happen, - * also environment setup and Plutip startup and teardown will happen once per each top-level test or group inside the `testPlutipContracts` call, - * so wrap your tests or groups in a single group if you want for the cluster to start only once, -* `test :: Type` is a type of tests themselves, - * in our case it's [`ContractTest`](../src/Internal/Test/ContractTest.purs), which in a nutshell describes a function from some wallet UTxO distribution to a `Contract r` - * wallet UTxO distribution is the one that you need to pattern-match on when writing tests -* `m :: Type -> Type` is a monad where effects during the construction of the test suite can be performed, - * here we use `Aff` again -* `a :: Type` is a result of the test suite, we use `Unit` here. - -`testPlutipContracts` also combines distributions of individual tests in a single big distribution (via nested tuples) and modifies tests to pluck their required distributions out of the big one. -This allows to create wallets and fund them in one step, during the Plutip setup. -See the comments in the [`Ctl.Internal.Plutip.Server` module](../src/Internal/Plutip/Server.purs) for more info (relevant ones are in `execDistribution` and `testPlutipContracts` functions). - -In complicated protocols you might want to execute some `Contract`s in one test and then execute other `Contract`s which depend on some wallet-dependent state set up by the first batch of contracts, e.g. some authorization token is present at some wallet. -Keeping these steps in separate sequential tests allows to pinpoint where things failed much easier, but currently CTL uses separate wallets for each test without an easy way to refer to wallets in other tests, so you have to call first batch of contracts again to replicate the state of the wallets, which in turn might fail or mess up your protocol, because the chain state is shared between tests for each top-level group. -There's a patch to CTL you can adapt (and even better -- make a PR) if you need to share wallets between tests right now, see the [limitations](#limitations) doc for more info. -This functionality will probably be added to CTL later. - -### Testing in Aff context - -Second approach is to use the `Contract.Test.Plutip.runPlutipContract` function, which takes a single `Contract`, launches a Plutip cluster and executes the passed contract. -This function runs in `Aff`; it will also throw an exception should contract fail for any reason. -After the contract execution the Plutip cluster is terminated. -You can either call it directly from your test's main or use any library for grouping and describing tests which support effects in the test body, like Mote. - -`Contract.Test.Plutip.runPlutipContract`'s function type is defined as follows: -```purescript -runPlutipContract - :: forall (distr :: Type) (wallets :: Type) (a :: Type) - . UtxoDistribution distr wallets - => PlutipConfig - -> distr - -> (wallets -> Contract a) - -> Aff a -``` - -`distr` is a specification of how many wallets and with how much funds should be created. It should either be a `Unit` (for no wallets), nested tuples containing `Array BigInt` or an `Array (Array BigInt)`, where each element of the inner array specifies an UTxO amount in Lovelaces (0.000001 Ada). - -The `wallets` argument of the callback is either a `Unit`, a tuple of `KeyWallet`s (with the same nesting level as in `distr`, which is guaranteed by `UtxoDistribution`) or an `Array KeyWallet`. - -`wallets` should be pattern-matched on, and its components should be passed to `withKeyWallet`: - -An example `Contract` with two actors using nested tuples: - -```purescript -let - distribution :: Array BigInt /\ Array BigInt - distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 2_000_000_000 - ] /\ - [ BigInt.fromInt 2_000_000_000 ] -runPlutipContract config distribution \(alice /\ bob) -> do - withKeyWallet alice do - pure unit -- sign, balance, submit, etc. - withKeyWallet bob do - pure unit -- sign, balance, submit, etc. -``` - -An example `Contract` with two actors using `Array`: - -```purescript -let - distribution :: Array (Array BigInt) - distribution = - -- wallet one: two UTxOs - [ [ BigInt.fromInt 1_000_000_000, BigInt.fromInt 2_000_000_000] - -- wallet two: one UTxO - , [ BigInt.fromInt 2_000_000_000 ] - ] -runPlutipContract config distribution \wallets -> do - traverse_ ( \wallet -> do - withKeyWallet wallet do - pure unit -- sign, balance, submit, etc. - ) - wallets -``` - -In most cases at least two UTxOs per wallet are needed (one of which will be used as collateral, so it should exceed `5_000_000` Lovelace). - - -Internally `runPlutipContract` runs a contract in an `Aff.bracket`, which creates a Plutip cluster on setup and terminates it during the shutdown or in case of an exception. -Logs will be printed in case of an error. - -### Writing checks in tests - -CTL will run contracts in your test bodies and will print errors for any failed tests. -For more complex checks you can use the [assertions library](./test-utils.md). - -### Note on running clusters - -The communication with Plutip happens via the `plutip-server`'s HTTP interface, which allows to start or stop a cluster. -[`plutip-server`](../plutip-server) allows only once active cluster at a time. -CTL currently launches `plutip-server` and `kupo` on pre-defined ports, so you won't be able to launch multiple environments to get parallel cluster. - - - - -### Note on SIGINT - -Due to `testPlutipContracts`/`runPlutipContract` adding listeners to the SIGINT IPC signal, Node.js's default behaviour of exiting on CTRL+C no longer occurs. This was done to let cluster cleanup handlers run asynchronously. To restore the usual exit-by-CTRL+C, we provide helpers to cancel an `Aff` fiber and set the exit code, to let Node.js shut down gracefully when no more events are to be processed. - -```purescript -... -import Contract.Test.Utils (exitCode, interruptOnSignal) -import Data.Posix.Signal (Signal(SIGINT)) -import Effect.Aff (cancelWith, effectCanceler, launchAff) - -main :: Effect Unit -main = interruptOnSignal SIGINT =<< launchAff do - flip cancelWith (effectCanceler (exitCode 1)) do - ... test suite in Aff ... -``` - -### Testing with Nix - -You can run Plutip tests via CTL's `purescriptProject` as well. After creating your project, you can use the `runPlutipTest` attribute to create a Plutip testing environment that is suitable for use with your flake's `checks`. An example: - -```nix -{ - some-plutip-test = project.runPlutipTest { - name = "some-plutip-test"; - testMain = "Test.MyProject.Plutip"; - # The rest of the arguments are passed through to `runPursTest`: - env = { SOME_ENV_VAR = "${some-value}"; }; - }; -} -``` - -The usual approach is to put `projectname-plutip-test` in the `checks` attribute of your project's `flake.nix`. -This is done by default in the [`ctl-scaffold` template](../templates/ctl-scaffold/flake.nix). - -## Cluster configuration options - -`PlutipConfig` type contains `clusterConfig` record with the following options: - -```purescript -{ slotLength :: Seconds -, epochSize :: Maybe UInt -, maxTxSize :: Maybe UInt -, raiseExUnitsToMax :: Boolean -} -``` - -- `slotLength` and `epochSize` define time-related protocol parameters. Epoch size is specified in slots. -- `maxTxSize` (in bytes) allows to stress-test protocols with more restrictive transaction size limits. -- `raiseExUnitsToMax` allows to bypass execution units limit (useful when compiling the contract with tracing in development and without it in production). - -### Current limitations - -* Non-default values of `epochSize` (current default is 80) break staking rewards - see [this issue](https://github.com/mlabs-haskell/plutip/issues/149) for more info. `slotLength` can be changed without any problems. - -## Using addresses with staking key components - -It's possible to use stake keys with Plutip. `Contract.Test.Plutip.withStakeKey` function can be used to modify the distribution spec: - -```purescript -let - privateStakeKey :: PrivateStakeKey - privateStakeKey = wrap $ unsafePartial $ fromJust - $ privateKeyFromBytes =<< hexToRawBytes - "633b1c4c4a075a538d37e062c1ed0706d3f0a94b013708e8f5ab0a0ca1df163d" - aliceUtxos = - [ BigInt.fromInt 2_000_000_000 - , BigInt.fromInt 2_000_000_000 - ] - distribution = withStakeKey privateStakeKey aliceUtxos -``` - -Although stake keys serve no real purpose in plutip context, they allow to use base addresses, and thus allow to have the same code for plutip testing, in-browser tests and production. - -Note that CTL re-distributes tADA from payment key-only ("enterprise") addresses to base addresses, which requires a few transactions before the test can be run. These transactions happen on the CTL side, because Plutip can currently handle only enterprise addreses (see [this issue](https://github.com/mlabs-haskell/plutip/issues/103)). - -## Limitations -* See the `epochSize` configuration option problem [here](#current-limitations). -* Currently there's no way to share wallets between separate tests (which is useful for complex protocols). You can adapt [this PR](https://github.com/IndigoProtocol/cardano-transaction-lib/pull/1) (needs to be updated for the newer versions of CTL, likely won't need too many changes) if you need it now (and even better -- make a PR to CTL). -* If you've used the [`plutus-simple-model`](https://github.com/mlabs-haskell/plutus-simple-model) library then you might know that it allows to time travel in tests, which can be very useful for testing vesting schedules, etc. Testing with Plutip doesn't allow this, as it's running a real network. A way around this problem can be to parametrize onchain logic by a time multiplier (and use a small one for tests). - -## See also +# CTL integration with Plutip -- To actually write the test bodies, [assertions library](./test-utils.md) can be useful [(usage example)](../examples/ContractTestUtils.purs). -- Take a look at CTL's Plutip tests for the usage examples: - - the entry point with `main` that runs Plutip tests is [here](../test/Plutip.purs), - - folder with various test suites is [here](../test/Plutip/). +The use of [Plutip](https://github.com/mlabs-haskell/plutip) in CTL is +deprecated. For information on how to test with the Cardano Testnet, please +refer to the [CTL integration with Cardano Testnet](./cardano-testnet-testing.md) +documentation. diff --git a/doc/plutus-comparison.md b/doc/plutus-comparison.md index 8f813a3b63..65fa249b4c 100644 --- a/doc/plutus-comparison.md +++ b/doc/plutus-comparison.md @@ -1,8 +1,6 @@ # Comparing CTL and Plutus -This document outlines the core differences between CTL and Plutus (particularly in the context of the Plutus Application Backend [PAB]). CTL is of course directly inspired by Plutus and PAB and we have attempted to preserve a high degree of similarity between the two APIs. In many cases, it should be possible to copy-paste existing code written for PAB deployments and adjust it for CTL fairly easily (accounting of course for existing differences between Haskell and Purescript). Nevertheless, CTL and Plutus differ in several important ways, as outlined below. - -Note that differences between Haskell and Purescript, while also relevant to such a comparison, is beyond the scope of this document unless such differences have a direct bearing on divergences between the two CTL and Plutus. +This document outlines the core differences between CTL and Plutus Application Backend. CTL is directly inspired by PAB and we have attempted to preserve a high degree of similarity between the two APIs. Nevertheless, CTL and Plutus differ in several important ways, as outlined below. **Table of Contents** @@ -12,10 +10,10 @@ Note that differences between Haskell and Purescript, while also relevant to suc - [Library vs. process](#library-vs-process) - [The `Contract` type](#the-contract-type) - [API differences](#api-differences) - - [Transaction manipulation API](#transaction-manipulation-api) - - [Constraints and lookups](#constraints-and-lookups) - - [Babbage-era constraints](#babbage-era-constraints) - - [Typed scripts](#typed-scripts) + - [DEPRECATION WARNING](#deprecation-warning) + - [**DEPRECATED** Transaction manipulation API](#deprecated-transaction-manipulation-api) + - [**DEPRECATED** Constraints and lookups](#deprecated-constraints-and-lookups) + - [**DEPRECATED** Babbage-era constraints](#deprecated-babbage-era-constraints) - [Working with scripts](#working-with-scripts) - [Using scripts from the frontend](#using-scripts-from-the-frontend) - [Applying arguments to parameterized scripts](#applying-arguments-to-parameterized-scripts) @@ -25,13 +23,13 @@ Note that differences between Haskell and Purescript, while also relevant to suc ### Library vs. process -Unlike contracts written for PAB, which are compiled to a single process, CTL is a library. CTL itself can be [imported as a Purescript library](./ctl-as-dependency.md) and contracts written in CTL compile to Javascript that can be run in the browser or NodeJS. Accordingly, there is no need to activate endpoints in CTL -- contracts are executed by calling effectful functions written using the library. This distinction has influenced our adaption of Plutus' `Contract` type, as outlined [below](#the-contract-type). +Unlike contracts written for PAB, which are compiled to a single process, CTL is a library. CTL itself can be [imported as a Purescript library](./ctl-as-dependency.md) and offchain contracts written in CTL compile to Javascript that can be run in the browser or NodeJS. Accordingly, there is no need to activate endpoints in CTL -- contracts are executed by calling effectful functions written using the library. This distinction has influenced our adaption of Plutus' `Contract` type, as outlined [below](#the-contract-type). -Note, however, that CTL still requires a number of runtime dependencies. In some respects, this is similar to PAB, which also needs to communicate with plutus-chain-index and a running node. Please see the [documentation](./runtime.md) for more details on CTL's runtime. +Note, however, that CTL still requires a number of runtime dependencies. In some respects, this is similar to PAB, which also needs to communicate with plutus-chain-index and a running node. Please see the [runtime documentation](./runtime.md) for more details. ### The `Contract` type -Both CTL and Plutus define `Contract` monads for constructing, balancing, and submitting transactions. There are considerable differences between the two, however: +Both CTL and Plutus define `Contract` monads for constructing, balancing, and submitting transactions (not to be confused with smart contracts). There are considerable differences between the two, however: **CTL**: @@ -68,13 +66,17 @@ Finally, CTL's `Contract` is not parameterized by an error type as in Plutus. `C ## API differences -### Transaction manipulation API +### DEPRECATION WARNING + +The original constraints interface has been deprecated and will be removed. Use [`cardano-transaction-builder`](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder) for any new code. + +### **DEPRECATED** Transaction manipulation API | Plutus | CTL | | --------------------------- | ----------------------------- | | `submitTxConstraintsWith` | `submitTxFromConstraints` | -### Constraints and lookups +### **DEPRECATED** Constraints and lookups CTL has adapted Plutus' Alonzo-era constraints/lookups interface fairly closely and it functions largely the same. One key difference is that CTL does not, and cannot, have the notion of a "current" script. All scripts must be explicitly provided to CTL (serialized as CBOR, see below). This has led us to depart from Plutus' naming conventions for certain constraints/lookups: @@ -89,7 +91,7 @@ CTL has adapted Plutus' Alonzo-era constraints/lookups interface fairly closely Additionally, we implement `NativeScript` (multi-signature phase-1 script) support, which is not covered by Plutus. -#### Babbage-era constraints +#### **DEPRECATED** Babbage-era constraints CIPs 0031-0033 brought several improvements to Plutus and are supported from the Babbage era onwards: @@ -99,45 +101,15 @@ CIPs 0031-0033 brought several improvements to Plutus and are supported from the CTL has upgraded its constraints interface to work with these new features. At the time of writing, however, `plutus-apps` has not yet upgraded their constraints/lookups interface to support these new features. This means a direct comparison between `plutus-apps` and CTL regarding Babbage-era features is not currently possible. It also implies that, moving forward, CTL's constraints implementation will increasingly no longer match that of `plutus-apps`' to the same degree. -### Typed scripts - -Another difference between Plutus and CTL is our implementation of typed scripts. Recall that Plutus' `ValidatorTypes` class: - -```haskell -class ValidatorTypes (a :: Type) where - type RedeemerType a :: Type - type DatumType a :: Type - - type instance RedeemerType a = () - type instance DatumType a = () -``` - -Purescript lacks most of Haskell's more advanced type-level faculties, including type/data families. Purescript does, however, support functional dependencies, allowing us to encode `ValidatorTypes` as follows: - -```purescript -class ValidatorTypes :: Type -> Type -> Type -> Constraint -class - ( DatumType validator datum - , RedeemerType validator redeemer - ) <= - ValidatorTypes validator datum redeemer - -class DatumType :: Type -> Type -> Constraint -class DatumType validator datum | validator -> datum - -class RedeemerType :: Type -> Type -> Constraint -class RedeemerType validator redeemer | validator -> redeemer -``` - ### Working with scripts #### Using scripts from the frontend -As noted above, all scripts and various script newtypes (`Validator`, `MintingPolicy`, etc...) must be explicitly passed to CTL. Unlike Plutus, where on- and off-chain code can freely share Haskell values, scripts must be provided to CTL in a serialized format. The easiest way to do this is using `Contract.TextEnvelope.textEnvelope` along with the JS FFI. See the [getting started guide](getting-started.md#using-compiled-scripts) for more details. +As noted above, all scripts and various script newtypes (`Validator`, `MintingPolicy`, etc...) must be explicitly passed to CTL. Unlike Plutus, where on- and off-chain code can freely share Haskell values, scripts must be provided to CTL in a serialized format. The easiest way to do this is using `Contract.TextEnvelope` along with the JS FFI. See the [getting started guide](getting-started.md#using-compiled-scripts) for more details. #### Applying arguments to parameterized scripts -We support applying arguments to parameterized scripts with `Contract.Scripts.applyArgs`. It allows you to apply a list of `PlutusData` arguments to a `PlutusScript`. Using this allows you to dynamically apply arguments during contract execution, but also implies the following: +We support applying arguments to parameterized scripts with `Cardano.Plutus.ApplyArgs.applyArgs` (from [purescript-uplc-apply-args](https://github.com/mlabs-haskell/purescript-uplc-apply-args)). It allows you to apply a list of `PlutusData` arguments to a `PlutusScript`. Using this allows you to dynamically apply arguments during contract execution, but also implies the following: - All of your domain types must have `Contract.PlutusData.ToData` instances (or some other way of converting them to `PlutusData`) - You must employ a workaround, illustrated by the following examples, in your off-chain code to ensure that the applied scripts are valid for both on- and off-chain code. This essentially consists of creating an wrapper which accepts `Data` arguments for your parameterized scripts: diff --git a/doc/production.md b/doc/production.md new file mode 100644 index 0000000000..c450a32bbc --- /dev/null +++ b/doc/production.md @@ -0,0 +1,48 @@ + + + +- [Going to production with CTL](#going-to-production-with-ctl) + - [Setup security](#setup-security) + - [Achieving best performance](#achieving-best-performance) + - [Balancing](#balancing) + - [Monitoring](#monitoring) + + + +# Going to production with CTL + +## Setup security + +Ensure that: + +- You have thoroughly tested your dApp. Your tests should be based on security properties you want to maintain (who should/shouldn't be able to do X? under what conditions?). Write these properties down and review them as well. +- There are no private keys in the bundles +- Your private keys are stored securely (e.g. not served by the webserver) +- If you have private keys that are used specifically to control/shut down the system in case of a disaster, you are not storing them on the same server as the app. +- Blockfrost keys are not exposed to the user. If you run with Blockfrost, you have to set up a reverse proxy that attaches the project ID header. + +## Achieving best performance + +Most likely, you will need a custom query layer to scale your dApp. Kupo is not very performant when it comes to handling a lot of queries on mainnet if it is configured to index the whole blockchain: [it has a slightly different purpose](https://github.com/CardanoSolutions/kupo/issues/146#issuecomment-1810571796). + +The best approach would be to maintain your dApp state by folding incoming transactions (while handling rollbacks). Consider using [Ogmios chain-sync API](https://ogmios.dev/mini-protocols/local-chain-sync/). + +[Here's how to plug your own query layer as a "provider" into CTL](./custom-query-layers.md). + +## Balancing + +Use multiple backend instances if you have a lot of users, but avoid switching between different instances for a single user: CTL mildly relies on consistency of the state. + +How many instances to run? Compute the number based on the response times of your query layer and expected number of users. + +## Monitoring + +Set up monitoring and alerts for your backend services. + +Ensure that you actively check the following: + +- Disk space +- RAM usage +- Rate of failed requests to the query layer backend (e.g. kupo returns 503 when overloaded) +- Average response time +- Usage limits for Blockfrost diff --git a/doc/side-by-side-ctl-plutus-comparison.md b/doc/side-by-side-ctl-plutus-comparison.md index 61fea0b9ad..5bf75b70a2 100644 --- a/doc/side-by-side-ctl-plutus-comparison.md +++ b/doc/side-by-side-ctl-plutus-comparison.md @@ -11,10 +11,7 @@ both of them. - [About `Contract` in CTL and Plutus](#about-contract-in-ctl-and-plutus) -- [Contract comparison](#contract-comparison) - - [MustPayTo functions](#mustpayto-functions) - - [The `give` contract](#the-give-contract) - - [The `grab` contract](#the-grab-contract) +- [Contract code comparison](#contract-code-comparison) @@ -62,206 +59,6 @@ effectful actions are defined directly in terms of those provided by `Aff`, logging is provided by a configurable logger stored in `ContractEnv`. -## Contract comparison - -We can now begin to compare contracts. - -The most famous contracts are those contained as part of -the [Plutus pioneer program](https://plutus-pioneer-program.readthedocs.io/en/latest/pioneer/week2.html) in week2. -Both of them use the same on-chain contract that allows an arbitrary -datum and arbitrary redeemer. - -### MustPayTo functions - - -In the case of Plutus `Contract`, we use the function -`mustPayToOtherScript`, according to Plutus ledger, is defined as: - -```Haskell -{-# INLINABLE mustPayToOtherScript #-} --- | @mustPayToOtherScript vh d v@ locks the value @v@ with the given script --- hash @vh@ alonside a datum @d@. --- --- If used in 'Ledger.Constraints.OffChain', this constraint creates a script --- output with @vh@, @d@ and @v@ and adds @d@ in the transaction's datum --- witness set. --- --- If used in 'Ledger.Constraints.OnChain', this constraint verifies that @d@ is --- part of the datum witness set and that the script transaction output with --- @vh@, @d@ and @v@ is part of the transaction's outputs. -mustPayToOtherScript - :: forall i o. ValidatorHash -> Datum -> Value -> TxConstraints i o -``` - -While in the case of CTL we would use `mustPayToScript`: - -```PureScript --- | Note that CTL does not have explicit equivalents of Plutus' --- | `mustPayToTheScript` or `mustPayToOtherScript`, as we have no notion --- | of a "current" script. Thus, we have the single constraint --- | `mustPayToScript`, and all scripts must be explicitly provided to build --- | the transaction. -mustPayToScript - :: forall (i :: Type) (o :: Type) - . ValidatorHash - -> Datum - -> Value - -> TxConstraints i o -``` - -### The `give` contract - -Now we can write and compare the `give` contract. -This contract takes and amount of Ada from our wallet -an lock it to the script that validates any -transactions. - -```Haskell --- Haskell -give :: - forall (w :: Type) (s :: Type) (e :: Type). - AsContractError e => - Integer -> Contract w s e () -give amount = do - let tx = mustPayToOtherScript vHash (Datum $ Constr 0 []) - $ Ada.lovelaceValueOf amount - ledgerTx <- submitTx tx - void $ awaitTxConfirmed $ txId ledgerTx - logInfo @String $ printf "made a gift of %d lovelace" amount -``` - -We include some of the imports for the PureScript -contract. - -```PureScript --- PureScript -import Contract.PlutusData (PlutusData, unitDatum) -import Contract.ScriptLookups as Lookups -import Contract.TxConstraints as Constraints -import Contract.Prelude -import Data.BigInt as BigInt - -give :: ValidatorHash -> Contract TransactionHash -give vhash = do - let - constraints :: Constraints.TxConstraints Unit Unit - constraints = Constraints.mustPayToScript vhash unitDatum - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups PlutusData - lookups = mempty - - submitTxFromConstraints lookups constraints -``` - - -### The `grab` contract - -The Plutus `grab` example takes all the UTxOs locked by -the on-chain contract that always validates a transaction, and spends -them to get all in the wallet of the user running the example. -This isn't a problem as the example is intended to run inside a -Plutus `EmulatorTrace` in a local toy environment. - -```Haskell --- Haskell -grab :: forall w s e. AsContractError e => Contract w s e () -grab = do - utxos <- utxoAt scrAddress - let orefs = fst <$> Map.toList utxos - lookups = Constraints.unspentOutputs utxos <> - Constraints.otherScript validator - tx :: TxConstraints Void Void - tx = - mconcat [mustSpendScriptOutput oref $ Redeemer $ I 17 | oref <- orefs] - ledgerTx <- submitTxFromConstraints @Void lookups tx - void $ awaitTxConfirmed $ txId ledgerTx - logInfo @String $ "collected gifts" -``` - -To talk about the grab contract in CTL we need to talk about some -functions and types of CTL first. - -```PureScript -module Ctl.Internal.Plutus.Types.Transaction ... -. -. -. -type UtxoMap = Map TransactionInput TransactionOutputWithRefScript -``` - -```PureScript -module Contract.Utxos ... -. -. -. --- | Queries for utxos at the given Plutus `Address`. -utxosAt - :: forall (address :: Type) - . PlutusAddress address - => address - -> Contract UtxoMap -``` - - -In the case of the CTL version of `grab`, we cannot use all the UTxOs locked by -the validator that always validates, since the example is -intended to run in the `testnet` and other people could have some -values locked by the script. -This is the reason we assume we have already run the `give` contract to -pay some `testAda` to the validator first, and then We got a `TransactionHash`. -We would use the `TransactionHash` to locate the right UTxO to spend. - -```PureScript --- PureScript -grab - :: ValidatorHash - -> Validator - -> TransactionHash - -> Contract Unit -grab vhash validator txId = do - let scriptAddress = scriptHashAddress vhash Nothing - utxos <- fromMaybe Map.empty <$> utxosAt scriptAddress - case fst <$> find hasTransactionId (Map.toUnfoldable utxos :: Array _) of - Just txInput -> - let - lookups :: Lookups.ScriptLookups PlutusData - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints Unit Unit - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - in - void $ submitTxFromConstraints lookups constraints - _ -> - logInfo' $ "The id " - <> show txId - <> " does not have output locked at: " - <> show scriptAddress - where - hasTransactionId :: TransactionInput /\ _ -> Boolean - hasTransactionId (TransactionInput tx /\ _) = - tx.transactionId == txId -``` - -Notice the explicit signature in: - -```PureScript - fst <$> find hasTransactionId (Map.toUnfoldable utxos :: Array _) -``` - -Since PureScript has JS as the backend, `Array` is the most used container -(instead of `List` as in Haskell), so, we prefer the use of `Array` over `List` -whenever it's adequate. -A downside of this is the lack of pattern matching over arbitrary arrays. - - -Both versions of the contract use the same kind of constraints. -Both need to add the validator and the UTxOs to the `lookups` -and both need the `SpendScriptOutput` constraint. -In the case of Plutus, this is done by a special function -that accept lookups, while in CTL this is done by the explicit -construction of an unbalanced transaction. +## Contract code comparison +Compare the contracts defined in week2 of the [Plutus pioneer program](https://plutus-pioneer-program.readthedocs.io/en/latest/pioneer/week2.html) with the [`AlwaysSucceeds`](../examples/AlwaysSucceeds.purs) example in CTL. diff --git a/doc/staking.md b/doc/staking.md index a25f62006e..a93ba783e5 100644 --- a/doc/staking.md +++ b/doc/staking.md @@ -14,4 +14,4 @@ CTL supports all operations with stake: - Receiving rewards - Withdrawing rewards -[Our tests](../test/Plutip/Staking.purs) include examples for each of the supported cases. +[Our tests](../test/Testnet/Staking.purs) include examples for each of the supported cases. diff --git a/doc/test-plan.md b/doc/test-plan.md deleted file mode 100644 index 8cfb03bcd2..0000000000 --- a/doc/test-plan.md +++ /dev/null @@ -1,245 +0,0 @@ -# CTL Test Plan - -This document outlines CTL's test plan, i.e. a formalized description of testing CTL itself. - -**Table of Contents** - - - - -- [User interactions](#user-interactions) - - [Constraints/lookups](#constraintslookups) - - [Stake operations](#stake-operations) - - [Stake pools](#stake-pools) - - [Stake credential registration](#stake-credential-registration) - - [Delegation](#delegation) - - [Rewards withdrawal](#rewards-withdrawal) - - [Stake credential deregistration](#stake-credential-deregistration) - - [Other functionality](#other-functionality) -- [Acceptance criteria](#acceptance-criteria) - - [Example contracts as tests](#example-contracts-as-tests) - - [Test environments](#test-environments) - - [Unit and integration testing](#unit-and-integration-testing) - - [Required parsing tests](#required-parsing-tests) - - - -## User interactions - -This section outlines the parts of CTL's interface that we aim to guarantee function as expected. Each of the following functionality **must** be covered by an example contract (see our [Acceptance criteria](#acceptance-criteria) below for more details about coverage). - -### Constraints/lookups - -CTL's primary user interface is its constraints and lookups API, modeled after that of Plutus. We must ensure then that **all** of this interface is covered by complete examples (see [Acceptance criteria](#acceptance-criteria) below for a definition of an "example"). Each of the following constraints should be covered, along with the lookup that it implies (indicated in parentheses where applicable): - -- [x] `mustMintValue` (`mintingPolicy`). Also implies - - `mustMintCurrency` -- [x] `mustPayToScript` (`validator`) -- [x] `mustPayToScriptAddress` -- [x] `mustPayToPubKey` - - **Note**: This invokes the same code as `mustPayToPubKeyAddress`, but does not include a stake key component -- [x] `mustPayToPubKeyAddress` -- [x] `mustMintValueWithRedeemer` (`mintingPolicy`). Also implies - - `mustMintCurrencyWithRedeemer` -- [x] `mustSpendScriptOutput` -- [x] `mustSpendPubKeyOutput` -- [x] `mustBeSignedBy` -- [x] `mustHashDatum` -- [x] `mustIncludeDatum` -- [x] `mustPayToPubKeyWithDatum` -- [x] `mustPayToPubKeyAddressWithDatum` -- [x] `mustProduceAtLeastTotal`. Also implies - - [x] `mustProduceAtLeast` -- [x] `mustSatisfyAnyOf` -- [x] `mustSpendAtLeastTotal`. Also implies - - [x] `mustSpendAtLeast` -- [x] `mustValidateIn` - -The following constraints were added for `PlutusV2` features as part of our `v2.0.0` release. They do not have direct correspondances in `plutus-apps`: - -- [x] `mustMintCurrencyUsingScriptRef` -- [x] `mustMintCurrencyWithRedeemerUsingScriptRef` -- [x] `mustPayToScriptWithScriptRef` -- [x] `mustPayToScriptAddressWithScriptRef` -- [x] `mustPayToPubKeyAddressWithDatumAndScriptRef` -- [x] `mustPayToPubKeyAddressWithScriptRef` -- [x] `mustPayToPubKeyWithDatumAndScriptRef` -- [x] `mustPayToPubKeyWithScriptRef` -- [x] `mustReferenceOutput` -- [x] `mustSpendScriptOutputUsingScriptRef` - -That release also included the following constraints for working with native scripts, which also have no `plutus-apps` analogue: - -- [x] `mustPayToNativeScript` -- [x] `mustPayToNativeScriptAddress` -- [x] `mustSpendNativeScriptOutput` - -In addition, several redeemer combinations in a **single transaction** must be covered by tests or examples as well, namely - -- [x] Two or more `Mint` redeemers -- [x] Two or more `Spend` redeemers -- [x] (At least) One each of a `Spend` and `Mint` redeemer - -#### Stake operations - -New constraints for operations with stake will be added in `v3`. - -##### Stake pools - -- [x] mustRegisterPool -- [x] mustRetirePool - -##### Stake credential registration - -- [x] mustRegisterStakePubKey -- [x] mustRegisterStakeScript - -##### Delegation - -- [x] mustDelegateStakePubKey -- [x] mustDelegateStakePlutusScript -- [x] mustDelegateStakeNativeScript - -##### Rewards withdrawal - -- [x] mustWithdrawStakePubKey -- [x] mustWithdrawStakePlutusScript -- [x] mustWithdrawStakeNativeScript - -##### Stake credential deregistration - -- [x] mustDeregisterStakePubKey -- [x] mustDeregisterStakePlutusScript -- [x] mustDeregisterStakeNativeScript - -### Other functionality - -In addition to the constraints/lookups listed above, there are several other critical pieces of functionality that CTL must guarantee. This functionality is subject to the same criteria as our constraints/lookups. - -- `Contract.Transaction.*` - - [x] `balanceTx` - - [x] `signTransaction` - - [x] `submit` - - [x] `awaitTxConfirmed` (implies `awaitTxConfirmedWithTimeout`) - - [x] `getTxMetadata` -- `Contract.Scripts.*` - - [x] `validatorHash` - - [x] `mintingPolicy` - - [x] `applyArgs` - - [x] `getScriptByHash` - - [x] `getScriptsByHashes` -- `Contract.Hashing.*` - - [x] `datumHash` - - [x] `plutusScriptHash` -- `Contract.PlutusData.*` - - [x] `getDatumByHash` - - [x] `getDatumsByHashes` -- `Contract.Utxos.*` - - [x] `utxosAt` - -## Acceptance criteria - -Coverage of particular functionality is measured by the inclusion of the **public** interface in full example contracts and tests. CTL's public API is defined in its `Contract.*` modules. - -Most user interactions defined [above](#user-interactions) also call various parsers and serialization/deserialization code defined in CTL's private/internal modules. Acceptance criteria for these aspects of CTL are defined in [Unit testing](#unit-and-integration-testing) below. - -### Example contracts as tests - -In the case of CTL's constraints/lookups API, in order to be qualified as "covered", the relevant part of the API **must** be included in a **complete example** (such examples are currently contained in our [`examples/`](../examples) directory). Such examples must successfully - -- build an unbalanced transaction specified using the constraints/lookups interface - - **Note**: For implemented transaction features _not_ supported by our current constraints/lookups implementation, such as the features introduced by CIPs 31-33 (inline datums, etc...), modifying the transaction directly is also acceptable -- balance the transaction while calculating sufficient fees/execution units -- sign the transaction using the attached wallet (either a browser-based light wallet or our own `KeyWallet`) -- submit the transaction to the node - -The functionality to achieve the above **must** be taken from our public API. That is, we must consume the public interface directly in all example contracts rather than importing internal CTL modules (anything outside of `Contract.*`). - -#### Test environments - -Furthermore, **all** example contracts must be able to execute in both of the environments that CTL supports. The following sections will refer to two different approachs for testing CTL: - -- **Plutip** testing - - This represents CTL's support for running in a Node.js environment (for `KeyWallet` examples), without a browser or light wallet - - These examples must use our Plutip integrations (`Contract.Test.Plutip` and `purescriptProject.runPlutipTest` from our Nix infrastructure) - - As these do not require network access, they can be executed in an entirely pure environment - - These must be run on CI on each pull request against the CTL repository using `runPlutipTest` by adding the contract to `Test.Plutip` -- **e2e** (end-to-end) testing - - This represents our browser integration and uses real light wallets and a public testnet - - **All** currently supported wallets must be tested against each example contract - - In the future, all e2e tests using real light wallets and a headless Chromium instance might also be run on CI - - See [issue #929](https://github.com/Plutonomicon/cardano-transaction-lib/issues/929) for more details - -Example contracts should be implemented such that the same contract can be reused in both environments. An example module might look like: - -```purescript - -module Examples.MintsToken - ( example - ) where - -import Contract.Prelude - -import Contract.Config (ContractParams) -import Contract.Log (logInfo') -import Contract.Monad (launchAff_) - -example :: ContractParams -> Effect Unit -example cfg = launchAff_ do - runContract cfg do - logInfo' "Running Examples.MintsToken" - -- rest of the contract -``` - -Then, the exported `example` must be added to `Examples.ByUrl` to be run with `make e2e-test`. In some cases, it can be reused directly in a Plutip test (contained in the module `Test.Plutip`); in other cases, an indentical contract can be reimplemented inline in the Plutip test suite. - -The **only** exception to the above rule is when the particulars of a contract preclude running it in one of the environments. For example, a contract that requires interaction between two or more wallets cannot currently be adapted to our e2e testing (as it assumes one connected wallet with one account). - -### Unit and integration testing - -CTL relies heavily on various runtime components to provide the necessary information to perform chain queries and construct transactions. We depend on a large amount of parsers, including serialization/deserialization code (i.e. to and from CTL's own domain type to `cardano-serialization-lib` FFI types), to consume the responses to websocket and HTTP requests made against CTL's runtime. - -Although such parsers are included implicitly in the example contracts defined above, we must also ensure good coverage of edge cases that may arise when making runtime requests. Our approach to such testing can be formalized as: - -- **Unit tests** - - These tests rely on fixtures generated from runtime responses (see [`fixtures/`](../fixtures/test) for examples), stored in the same format as they are received in genuine responses - - The corresponding tests can be largely pure functions which read the fixture and parse it - - Success is defined as a parse returning a `Just` or `Right` value, depending on the parser - - Due to the large number and semi-random nature of our test fixtures, we do not require comparing parsed values to an expected result - - If possible, we should validate a parser against a component's _own_ test fixtures - - See `Test.Ogmios.GenerateFixtures` for an example of this approach, which uses Ogmios' generated test vectors for our own testing -- **Integration tests** - - These tests are run against a full runtime and make real requests to different components - - These are intended to augment the unit tests described above and are a step below our full example contracts - - These can be effects from the `Contract` interface and the underlying backends - -#### Required parsing tests - -Currently, we require parsing tests for the following data structures, organized by dependency (including runtime dependencies): - -- Ogmios - - [x] `ChainTipQR` - - [x] `CurrentEpoch` - - [x] `SystemStart` - - [x] `EraSummaries` - - [x] `ProtocolParameters` - - [x] `TxEvaluationR` - - [x] `SubmitTxR` -- `cardano-serialization-lib` - - `Transaction` - - [x] Serialization - - [x] Deserialization - - `TxBody` - - [x] Serialization - - [x] Deserialization - - `TransactionWitnessSet` - - [x] Serialization - - [x] Deserialization -- Kupo - - [ ] `KupoUtxoMap` - - [ ] `KupoDatum` - - [ ] `KupoScriptRef` - - [ ] `KupoUtxoSlot` - - [ ] `KupoMetadata` -- Blockfrost - - TODO diff --git a/doc/test-utils.md b/doc/test-utils.md index 0290683dc5..f2339d92b7 100644 --- a/doc/test-utils.md +++ b/doc/test-utils.md @@ -87,6 +87,6 @@ type ContractCheck a = Particular values can be constructed with utility functions, as demonstrated in the [ContractTestUtils example](../examples/ContractTestUtils.purs) (see `mkAssertions`). -An example for using checks in the tests is [here](../test/Plutip/Contract/Assert.purs). +An example for using checks in the tests is [here](../test/Testnet/Contract/Assert.purs). All the functions require `Labeled` arguments, that can be constructed with `label` function; or `noLabel`, if descriptive names in error messages are not needed. diff --git a/doc/testing.md b/doc/testing.md index 19de1f4297..c079c8eb77 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -4,11 +4,9 @@ This page summarizes various approaches to testing with CTL. -## Testing with Plutip +## Testing with Cardano Testnet -Plutip is a tool that allows to manage temporary `cardano-node` clusters. CTL has a test engine that controls these clusters and runs users' `Contract`s in their disposable environment. No setup is needed. - -[See here for more info](./plutip-testing.md). +[See here for more info](./cardano-testnet-testing.md). ## Testing with a headless browser (E2E testing) @@ -28,11 +26,11 @@ It is possible to test `Contract`s that explicitly use wallet connections in Nod See `Contract.Test.Cip30Mock` module. -## Plutip and CIP-30 mocking in headless browsers +## Cardano Testnet and CIP-30 mocking in headless browsers -We also provide abilities to test `Contract`s in a headless browser using query layer of a temporary Plutip cluster as backend and CIP-30 mock instead of a wallet. This method provides stronger guarantees than just CIP-30 mocking in NodeJS, while retaining the ability to be used in Nix builds (by not depending on a real light wallet extension). +We also provide abilities to test `Contract`s in a headless browser using query layer of a Cardano Testnet cluster as backend and CIP-30 mock instead of a wallet. This method provides stronger guarantees than just CIP-30 mocking in NodeJS, while retaining the ability to be used in Nix builds (by not depending on a real light wallet extension). -[See here for more info](./e2e-testing.md#using-cip-30-mock-with-plutip). +[See here for more info](./e2e-testing.md#using-cip-30-mock-with-cardano-testnet). ## Assertion helpers in PureScript diff --git a/doc/tx-chaining.md b/doc/tx-chaining.md index 3088503b0a..c8b5b60cae 100644 --- a/doc/tx-chaining.md +++ b/doc/tx-chaining.md @@ -6,6 +6,6 @@ Transaction chaining on Cardano is the ability to send transactions that depend In case the transactions come from multiple actors, some off-chain data delivery mechanism should be used - it's up to the application developers to implement it. -The only piece of data that is actually needed is the additional UTxOs that the CTL query layer is not (yet) aware of. `mustUseAdditionalUtxos` [balancer constraint](./balancing.md) can be used for that, as shown in the [transaction chaining example](../examples/TxChaining.purs). Additionally, `mustNotSpendUtxosWithOutRefs` can be used to forbid spending UTxOs that have been consumed. +The only piece of data that is actually needed is the additional UTxOs that the CTL query layer is not (yet) aware of. `mustUseAdditionalUtxos` [balancer constraint](./balancing.md) can be used for that, as shown in the [transaction chaining example](../examples/TxChaining.purs). Additionally, `mustNotSpendUtxosWithOutRefs` can be used to forbid attempting to spend UTxOs that have been consumed. `createAdditionalUtxos` is a helper function that can be used to build an UTxO set for use with `mustUseAdditionalUtxos`. `Contract.Backend.Ogmios.Mempool` module contains functions that allow to query the mempool for pending transactions (only works with Ogmios backend). See [here](https://ogmios.dev/mini-protocols/local-tx-monitor/) for more. diff --git a/doc/using-from-js.md b/doc/using-from-js.md index 4c977528d5..bd6f592563 100644 --- a/doc/using-from-js.md +++ b/doc/using-from-js.md @@ -1,32 +1,44 @@ -- [JavaScript SDKs](#javascript-sdks) - - [Defining APIs in PureScript](#defining-apis-in-purescript) - - [Using from NodeJS](#using-from-nodejs) - - [Bundling for NodeJS](#bundling-for-nodejs) - - [Calling from NodeJS](#calling-from-nodejs) - - [Using from the browser](#using-from-the-browser) - - [Bundling for the browser](#bundling-for-the-browser) - - [WebAssembly and conditional imports](#webassembly-and-conditional-imports) - - [Calling in the browser](#calling-in-the-browser) +- [Building JavaScript SDKs with CTL](#building-javascript-sdks-with-ctl) + - [SDK packaging for NodeJS](#sdk-packaging-for-nodejs) + - [SDK bundling for the browser](#sdk-bundling-for-the-browser) + - [Defining SDK APIs in PureScript](#defining-sdk-apis-in-purescript) + - [Calling the SDK API](#calling-the-sdk-api) - [See also](#see-also) -# JavaScript SDKs +# Building JavaScript SDKs with CTL Normally, dApps involve three parts: -- on-chain logic (Plutus or Plutarch scripts) -- off-chain logic (in our case, implemented using CTL) +- on-chain logic (Plutus, Plutarch or Aiken scripts) +- **off-chain logic** (in our case, implemented using CTL) - user interface -Building CTL-based JavaScript SDKs is the simplest way to connect user interfaces (most commonly, web apps) with off-chain logic. These SDKs expose app-specific APIs for web developers to plug into the user interface. SDKs are normally consumable as NPM packages. +Providing CTL-based JavaScript SDKs is the simplest way to connect user interfaces (most commonly, web apps) with off-chain logic. These SDKs expose app-specific APIs for web developers to plug into the user interface. SDKs are normally consumable as NPM packages. -## Defining APIs in PureScript +Explore [the template](../templates/ctl-scaffold/package.json) or CTL itself for an example setup. See [the WebPack config](../webpack.config.cjs) or the [esbuild config](../esbuild/config.js) we provide. -Developers should start from reading [this PureScript guide](https://book.purescript.org/chapter10.html#calling-purescript-from-javascript) that shows how to call PureScript from JS. Our (older) PureScript version is using CommonJS modules and not ES modules, so `import` statements should be replaced with `require`. +## SDK packaging for NodeJS + +NodeJS apps do not require to be bundled in order to be run (however, it is possible, see the [Makefile](../Makefile) options). + +An NPM package with `main` set to the compiled JS entry point (e.g. `./output/ApiModuleName.js`) is sufficient, but the runtime dependencies of said package must include the same package versions CTL itself uses in its `package.json`. + +## SDK bundling for the browser + +SDKs must be bundled to be usable in the browser. We support two bundlers: esbuild and WebPack. There are two options how to approach bundling and packaging: + +1. bundling a CTL-based SDK *before* consuming it as dependency in the app, i.e. putting the bundled sources in an NPM package. Bundling twice is not a good practice, and it is hard to even make it work, so in case this path is chosen, the developer should ensure that the SDK does not get bundled twice by the second bundler. + +2. **[recommended]** bundling a CTL-based SDK together with the UI part of the app. This is simpler, but in case a bundler different from esbuild or WebPack is used, problems may arise due to bundler differences. It should be possible to use other bundlers, as long as they support async top-level imports, WebAssembly and [`browser` package.json field](https://github.com/defunctzombie/package-browser-field-spec). + +## Defining SDK APIs in PureScript + +Developers should start from reading [this PureScript guide](https://book.purescript.org/chapter10.html#calling-purescript-from-javascript) that shows how to call PureScript from JS. Suppose we want to wrap a single `Contract` into an interface to call it from JS with Nami wallet. @@ -63,37 +75,12 @@ config = testnetNamiConfig -- use Nami wallet - `Contract.JsSdk` is a module containing synonyms for some `Contract.Monad` functions, but adapted for use in JS SDKs. - `fromAff` converts `Aff a` to `Effect (Promise a)`, and `unsafePerformEffect` removes the `Effect` wrapper that is not needed on the JS side. -## Using from NodeJS +## Calling the SDK API -### Bundling for NodeJS - -To prepare the module defined above for use from other NodeJS code, `spago bundle-module` should be used: - -```bash -spago bundle-module -m Api --to output.js -``` - -The resulting bundle will NOT include its NodeJS dependencies in the same file. - -It can be distributed via NPM by pointing `package.json` to it: - -```js -{ - ... - "main": "output.js", - ... - "dependencies": { - // same dependencies as CTL itself uses should be put here - } -} -``` - -### Calling from NodeJS - -The module above can be imported like this from NodeJS: +The module above can be imported like this: ```javascript -const { initialize, config, run, finalize } = require('./output.js'); +import { initialize, config, run, finalize } from 'your-api-package'; (async () => { const env = await initialize(config); @@ -107,93 +94,6 @@ const { initialize, config, run, finalize } = require('./output.js'); Notice that we used `finally` to finalize - this is because a running contract environment would prevent the script from exiting otherwise. Please read [this guide](./contract-environment.md) for info on how to manage the runtime environment correctly. -## Using from the browser - -### Bundling for the browser - -The recommended way to bundle CTL for the browser is to use WebPack. - -#### WebAssembly and conditional imports - -We depend on WebPack's `DefinePlugin` to conditionally load either NodeJS or browser variant of dependencies that have WebAssembly parts. - -That means that CTL _requires_ bundling it the same way when used as a dependency, as we do in development. If you intend to use another bundler, something like `DefinePlugin` should be used to transform the import headers from this: - -```javascript -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = require("@emurgo/cardano-serialization-lib-browser"); -} else { - lib = require("@emurgo/cardano-serialization-lib-nodejs"); -} -``` - -to only one of the import variants. - -Our default [WebPack config](../webpack.config.cjs) uses `BROWSER_RUNTIME` environment variable to differentiate between two bundling options: - -```js - plugins: [ - new webpack.DefinePlugin({ - BROWSER_RUNTIME: !!process.env.BROWSER_RUNTIME, - }), -``` - -There's [a claim that Vite bundler can also be used](https://github.com/Plutonomicon/cardano-transaction-lib/issues/79#issuecomment-1257036068), although we don't officially support this method. - -### Calling in the browser - -Webpack config contains `entry` field, pointing to the main file of the app. - -Assuming we want to use the example app from above, it can be populated like this: - -```js -import("./output.js").then( - async ({ initialize, config, run, finalize }) => { - - const env = await initialize(config); - try { - await run(env); - } finally { - await finalize(env); - } -}); -``` - -Note that `import` returns a `Promise`. - -The config also contains some setup for output target: - -```js - output: { - path: path.resolve(__dirname, "dist"), - filename: "bundle.js", - }, -``` - -But to actually build a page that can be opened in a browser, we use `HtmlWebpackPlugin`: - -```js - new HtmlWebpackPlugin({ - title: "ctl-scaffold", - template: "./index.html", - inject: false, // See stackoverflow.com/a/38292765/3067181 - }), -``` - -The HTML page should contain this import, pointing to output bundle filename: - -```html - -``` - -`type="module"` is required here. - - -`experiments.syncWebAssembly` WebPack setting must be set to `true` because CTL internal code expects it. - -The whole webpage can be served with `BROWSER_RUNTIME=1 webpack-dev-server --progress` or built with `BROWSER_RUNTIME=1 webpack --mode=production` - ## See also -- [How to import serialized Plutus scripts for NodeJS and the browser](./importing-scripts.md) +- [How to import Plutus scripts into CTL for NodeJS and the browser](./importing-scripts.md) diff --git a/esbuild/config.js b/esbuild/config.js index 0ed3d593ee..ce3de40604 100644 --- a/esbuild/config.js +++ b/esbuild/config.js @@ -7,9 +7,6 @@ export const buildOptions = ({ entryPoint, outfile }) => { const config = { entryPoints: [entryPoint], outfile: outfile, - define: { - BROWSER_RUNTIME: isBrowser ? "true" : '""' - }, plugins: [ wasmLoader({ mode: "deferred" @@ -24,8 +21,10 @@ export const buildOptions = ({ entryPoint, outfile }) => { // https://esbuild.github.io/api/#packages if (!isBrowser) { + // Keep dependencies outside of the bundle for nodejs config.packages = "external"; } else { + // Provide browser polyfills for NodeJS modules config.plugins.push( polyfillNode({ polyfills: { diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000000..36f30f1d94 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,33 @@ +import js from "@eslint/js"; +import globals from "globals"; + +export default [ + js.configs.recommended, + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.commonjs, + ...globals.es2021, + ...globals.node + }, + + ecmaVersion: "latest", + sourceType: "module" + }, + + rules: { + "no-var": 2, + "no-case-declarations": 0, + + "no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + caughtErrorsIgnorePattern: "^_", + vars: "local" + } + ] + } + } +]; diff --git a/examples/AdditionalUtxos.purs b/examples/AdditionalUtxos.purs index 6617e31442..7a8780ca3b 100644 --- a/examples/AdditionalUtxos.purs +++ b/examples/AdditionalUtxos.purs @@ -5,50 +5,64 @@ module Ctl.Examples.AdditionalUtxos import Contract.Prelude -import Contract.Address (scriptHashAddress) -import Contract.BalanceTxConstraints (BalanceTxConstraintsBuilder) -import Contract.BalanceTxConstraints (mustUseAdditionalUtxos) as BalancerConstraints -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Transaction.Builder + ( OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) +import Cardano.Types + ( OutputDatum(OutputDatum) + , PaymentCredential(PaymentCredential) + , PlutusScript + , ScriptHash + , Transaction + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Credential (Credential(ScriptHashCredential)) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.TransactionOutput (TransactionOutput(TransactionOutput)) +import Cardano.Types.TransactionUnspentOutput (fromUtxoMap) +import Contract.Address (mkAddress) +import Contract.BalanceTxConstraints + ( BalancerConstraints + , mustUseAdditionalUtxos + ) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData (Datum, PlutusData(Integer), unitRedeemer) -import Contract.ScriptLookups (ScriptLookups, UnbalancedTx) -import Contract.ScriptLookups (datum, unspentOutputs, validator) as Lookups -import Contract.Scripts (Validator, ValidatorHash, validatorHash) +import Contract.PlutusData (Datum, PlutusData(Integer)) import Contract.Sync (withoutSync) import Contract.Transaction ( ScriptRef(NativeScriptRef) - , TransactionInput , awaitTxConfirmed - , balanceTxWithConstraints + , balanceTx + , buildTx , createAdditionalUtxos , signTransaction , submit , withBalancedTx ) -import Contract.TxConstraints - ( DatumPresence(DatumInline, DatumWitness) - , TxConstraints - ) -import Contract.TxConstraints - ( mustPayToScript - , mustPayToScriptWithScriptRef - , mustSpendPubKeyOutput - , mustSpendScriptOutput - ) as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Utxos (UtxoMap) import Contract.Value (Value) import Contract.Value (lovelaceValueOf) as Value import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) -import Data.Array (fromFoldable) as Array -import Data.Map (difference, filter, keys) as Map +import Data.Map (difference, empty, filter) as Map import JS.BigInt (fromInt) as BigInt import Test.QuickCheck (arbitrary) import Test.QuickCheck.Gen (randomSampleOne) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example contractParams = @@ -58,9 +72,9 @@ contract :: Boolean -> Contract Unit contract testAdditionalUtxoOverlap = withoutSync do logInfo' "Running Examples.AdditionalUtxos" validator <- alwaysSucceedsScriptV2 - let vhash = validatorHash validator + let vhash = PlutusScript.hash validator { unbalancedTx, datum } <- payToValidator vhash - withBalancedTx unbalancedTx \balancedTx -> do + withBalancedTx unbalancedTx Map.empty mempty \balancedTx -> do balancedSignedTx <- signTransaction balancedTx txHash <- submit balancedSignedTx when testAdditionalUtxoOverlap $ awaitTxConfirmed txHash @@ -70,62 +84,65 @@ contract testAdditionalUtxoOverlap = withoutSync do spendFromValidator validator additionalUtxos datum payToValidator - :: ValidatorHash -> Contract { unbalancedTx :: UnbalancedTx, datum :: Datum } + :: ScriptHash + -> Contract + { unbalancedTx :: Transaction + , datum :: Datum + } payToValidator vhash = do scriptRef <- liftEffect (NativeScriptRef <$> randomSampleOne arbitrary) let value :: Value - value = Value.lovelaceValueOf $ BigInt.fromInt 2_000_000 - - datum :: Datum - datum = wrap $ Integer $ BigInt.fromInt 42 - - constraints :: TxConstraints - constraints = - Constraints.mustPayToScript vhash datum DatumWitness value - <> Constraints.mustPayToScriptWithScriptRef vhash datum DatumInline - scriptRef - value - - lookups :: ScriptLookups - lookups = Lookups.datum datum - - unbalancedTx <- mkUnbalancedTx lookups constraints - pure { unbalancedTx, datum } - -spendFromValidator :: Validator -> UtxoMap -> Datum -> Contract Unit -spendFromValidator validator additionalUtxos datum = do + value = Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + + datum = Integer $ BigInt.fromInt 42 + scriptAddress <- mkAddress (PaymentCredential $ ScriptHashCredential vhash) + Nothing + + tx <- buildTx + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum $ datum + , scriptRef: Nothing + } + , Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum $ datum + , scriptRef: Just scriptRef + } + ] + + pure { unbalancedTx: tx, datum } + +spendFromValidator :: PlutusScript -> UtxoMap -> Datum -> Contract Unit +spendFromValidator validator additionalUtxos _datum = do + addr <- mkAddress (wrap $ ScriptHashCredential $ PlutusScript.hash validator) + Nothing let scriptUtxos :: UtxoMap scriptUtxos = additionalUtxos # Map.filter \out -> - (unwrap (unwrap out).output).address - == scriptHashAddress (validatorHash validator) Nothing - - scriptOrefs :: Array TransactionInput - scriptOrefs = Array.fromFoldable $ Map.keys scriptUtxos + (unwrap out).address == addr - pubKeyOrefs :: Array TransactionInput - pubKeyOrefs = - Array.fromFoldable $ Map.keys $ Map.difference additionalUtxos scriptUtxos + spendScriptOutputs = fromUtxoMap scriptUtxos <#> \output -> + SpendOutput output $ Just $ PlutusScriptOutput (ScriptValue validator) + RedeemerDatum.unit + Nothing - constraints :: TxConstraints - constraints = - foldMap (flip Constraints.mustSpendScriptOutput unitRedeemer) scriptOrefs - <> foldMap Constraints.mustSpendPubKeyOutput pubKeyOrefs + spendPubkeyOutputs = + fromUtxoMap (Map.difference additionalUtxos scriptUtxos) <#> \output -> + SpendOutput output Nothing - lookups :: ScriptLookups - lookups = - Lookups.validator validator - <> Lookups.unspentOutputs additionalUtxos - <> Lookups.datum datum + plan = spendScriptOutputs <> spendPubkeyOutputs - balancerConstraints :: BalanceTxConstraintsBuilder + balancerConstraints :: BalancerConstraints balancerConstraints = - BalancerConstraints.mustUseAdditionalUtxos additionalUtxos + mustUseAdditionalUtxos additionalUtxos - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTxWithConstraints unbalancedTx balancerConstraints + unbalancedTx <- buildTx plan + balancedTx <- balanceTx unbalancedTx additionalUtxos balancerConstraints balancedSignedTx <- signTransaction balancedTx txHash <- submit balancedSignedTx diff --git a/examples/AlwaysMints.purs b/examples/AlwaysMints.purs index f8fddc2be2..fcbe987528 100644 --- a/examples/AlwaysMints.purs +++ b/examples/AlwaysMints.purs @@ -11,38 +11,52 @@ module Ctl.Examples.AlwaysMints import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(MintAsset) + ) +import Cardano.Types (PlutusScript) +import Cardano.Types.Int as Int +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftContractM, runContract) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (MintingPolicy(PlutusMintingPolicy)) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV1FromEnvelope) -import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) -import Contract.TxConstraints as Constraints -import Contract.Value as Value -import Ctl.Examples.Helpers (mkCurrencySymbol, mkTokenName) as Helpers -import JS.BigInt as BigInt +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) +import Ctl.Examples.Helpers (mkAssetName) as Helpers +import Data.Map as Map main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } contract :: Contract Unit contract = do logInfo' "Running Examples.AlwaysMints" - mp /\ cs <- Helpers.mkCurrencySymbol alwaysMintsPolicy - tn <- Helpers.mkTokenName "TheToken" - let - constraints :: Constraints.TxConstraints - constraints = Constraints.mustMintValue - $ Value.singleton cs tn - $ BigInt.fromInt 100 - - lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp - - txId <- submitTxFromConstraints lookups constraints - - awaitTxConfirmed txId + mintingPolicy <- alwaysMintsPolicy + let scriptHash = PlutusScript.hash mintingPolicy + tokenName <- Helpers.mkAssetName "TheToken" + awaitTxConfirmed <<< Transaction.hash =<< + submitTxFromBuildPlan Map.empty mempty + [ MintAsset + scriptHash + tokenName + (Int.fromInt 100) + ( PlutusScriptCredential (ScriptValue mintingPolicy) + RedeemerDatum.unit + ) + ] logInfo' "Tx submitted successfully!" example :: ContractParams -> Effect Unit @@ -51,11 +65,10 @@ example cfg = launchAff_ $ do foreign import alwaysMints :: String -alwaysMintsPolicyMaybe :: Maybe MintingPolicy -alwaysMintsPolicyMaybe = do - PlutusMintingPolicy <$> - (plutusScriptV1FromEnvelope =<< decodeTextEnvelope alwaysMints) +alwaysMintsPolicyMaybe :: Maybe PlutusScript +alwaysMintsPolicyMaybe = + plutusScriptFromEnvelope =<< decodeTextEnvelope alwaysMints -alwaysMintsPolicy :: Contract MintingPolicy +alwaysMintsPolicy :: Contract PlutusScript alwaysMintsPolicy = liftContractM "Error decoding alwaysMintsPolicy" alwaysMintsPolicyMaybe diff --git a/examples/AlwaysSucceeds.purs b/examples/AlwaysSucceeds.purs index 26f1677de8..5e2041ad76 100644 --- a/examples/AlwaysSucceeds.purs +++ b/examples/AlwaysSucceeds.purs @@ -12,41 +12,64 @@ module Ctl.Examples.AlwaysSucceeds import Contract.Prelude -import Contract.Address (scriptHashAddress) -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Credential (Credential(PubKeyCredential)) +import Cardano.Transaction.Builder + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) +import Cardano.Types + ( Credential(PubKeyHashCredential, ScriptHashCredential) + , PaymentCredential(PaymentCredential) + , PlutusScript + , ScriptHash + , StakeCredential(StakeCredential) + , TransactionHash + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash)) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.PlutusScript as Script +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) +import Contract.Address (mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData (unitDatum, unitRedeemer) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (Validator(Validator), ValidatorHash, validatorHash) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV1FromEnvelope) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction - ( TransactionHash - , _input - , awaitTxConfirmed + ( awaitTxConfirmed , lookupTxHash - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value import Contract.Wallet (ownStakePubKeyHashes) import Control.Monad.Error.Class (liftMaybe) import Data.Array (head) -import Data.Lens (view) +import Data.Map as Map import Effect.Exception (error) -import JS.BigInt as BigInt main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } contract :: Contract Unit contract = do logInfo' "Running Examples.AlwaysSucceeds" validator <- alwaysSucceedsScript - let vhash = validatorHash validator + let vhash = Script.hash validator logInfo' "Attempt to lock value" txId <- payToAlwaysSucceeds vhash awaitTxConfirmed txId @@ -57,45 +80,34 @@ example :: ContractParams -> Effect Unit example cfg = launchAff_ do runContract cfg contract -payToAlwaysSucceeds :: ValidatorHash -> Contract TransactionHash +payToAlwaysSucceeds :: ScriptHash -> Contract TransactionHash payToAlwaysSucceeds vhash = do -- Send to own stake credential. This is used to test mustPayToScriptAddress. mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - let - constraints :: TxConstraints - constraints = - case mbStakeKeyHash of - Nothing -> - Constraints.mustPayToScript vhash unitDatum - Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - Just stakeKeyHash -> - Constraints.mustPayToScriptAddress vhash - (PubKeyCredential $ unwrap stakeKeyHash) - unitDatum - Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + scriptAddress <- mkAddress (PaymentCredential $ ScriptHashCredential vhash) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> mbStakeKeyHash) + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] spendFromAlwaysSucceeds - :: ValidatorHash - -> Validator + :: ScriptHash + -> PlutusScript -> TransactionHash -> Contract Unit spendFromAlwaysSucceeds vhash validator txId = do -- Use own stake credential if available mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - let - scriptAddress = - scriptHashAddress vhash (PubKeyCredential <<< unwrap <$> mbStakeKeyHash) + scriptAddress <- mkAddress + (wrap $ ScriptHashCredential vhash) + (wrap <<< PubKeyHashCredential <<< unwrap <$> mbStakeKeyHash) utxos <- utxosAt scriptAddress - txInput <- + utxo <- liftM ( error ( "The id " @@ -104,23 +116,24 @@ spendFromAlwaysSucceeds vhash validator txId = do <> show scriptAddress ) ) - (view _input <$> head (lookupTxHash txId utxos)) - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId + $ head (lookupTxHash txId utxos) + spendTx <- submitTxFromBuildPlan (Map.union utxos $ toUtxoMap [ utxo ]) + mempty + [ SpendOutput + utxo + ( Just $ PlutusScriptOutput (ScriptValue validator) RedeemerDatum.unit + $ Just + $ DatumValue + $ PlutusData.unit + ) + ] + awaitTxConfirmed $ Transaction.hash spendTx logInfo' "Successfully spent locked values." -alwaysSucceedsScript :: Contract Validator +alwaysSucceedsScript :: Contract PlutusScript alwaysSucceedsScript = do liftMaybe (error "Error decoding alwaysSucceeds") do envelope <- decodeTextEnvelope alwaysSucceeds - Validator <$> plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope foreign import alwaysSucceeds :: String diff --git a/examples/AwaitTxConfirmedWithTimeout.purs b/examples/AwaitTxConfirmedWithTimeout.purs index 401328c886..d465229f8a 100644 --- a/examples/AwaitTxConfirmedWithTimeout.purs +++ b/examples/AwaitTxConfirmedWithTimeout.purs @@ -10,18 +10,26 @@ module Ctl.Examples.AwaitTxConfirmedWithTimeout import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.AsCbor (decodeCbor) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract, throwContractError) import Contract.Prim.ByteArray (hexToByteArrayUnsafe) -import Contract.Transaction - ( TransactionHash(TransactionHash) - , awaitTxConfirmedWithTimeout - ) +import Contract.Transaction (awaitTxConfirmedWithTimeout) import Control.Monad.Error.Class (try) +import Partial.Unsafe (unsafePartial) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -31,8 +39,9 @@ contract :: Contract Unit contract = do logInfo' "Running AwaitTxConfirmedWithTimeout" let - fakeHash = TransactionHash $ hexToByteArrayUnsafe - "ffffffffffff55555555555555555555a1af1b7534b51e60fad3fe9c164313e8" + fakeHash = unsafePartial $ fromJust $ decodeCbor $ wrap $ + hexToByteArrayUnsafe + "ffffffffffff55555555555555555555a1af1b7534b51e60fad3fe9c164313e8" result <- try $ awaitTxConfirmedWithTimeout (wrap 1.0) fakeHash case result of Left _ -> pure unit diff --git a/examples/BalanceTxConstraints.purs b/examples/BalanceTxConstraints.purs index 8b971bf57d..048013dcba 100644 --- a/examples/BalanceTxConstraints.purs +++ b/examples/BalanceTxConstraints.purs @@ -5,15 +5,20 @@ module Ctl.Examples.BalanceTxConstraints import Contract.Prelude +import Cardano.Types (Asset(Asset), BigNum) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Int as Int +import Cardano.Types.Mint as Mint +import Cardano.Types.PlutusScript as PlutusScript import Contract.Address (Address) import Contract.BalanceTxConstraints - ( BalanceTxConstraintsBuilder + ( BalancerConstraints , mustGenChangeOutsWithMaxTokenQuantity , mustNotSpendUtxoWithOutRef , mustSendChangeToAddress , mustUseCollateralUtxos , mustUseUtxosAtAddress - ) as BalanceTxConstraints + ) import Contract.Log (logInfo') import Contract.Monad (Contract, liftedM) import Contract.ScriptLookups as Lookups @@ -30,7 +35,7 @@ import Contract.Transaction ( TransactionHash , TransactionInput , awaitTxConfirmed - , balanceTxWithConstraints + , balanceTx , signTransaction , submit ) @@ -38,22 +43,22 @@ import Contract.TxConstraints as Constraints import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Utxos (utxosAt) import Contract.Value (CurrencySymbol, TokenName, Value) -import Contract.Value (singleton, valueOf) as Value +import Contract.Value (valueOf) as Value import Contract.Wallet ( KeyWallet - , getWalletAddressesWithNetworkTag + , getWalletAddresses , getWalletCollateral , ownPaymentPubKeyHashes , withKeyWallet ) import Control.Monad.Trans.Class (lift) import Ctl.Examples.AlwaysMints (alwaysMintsPolicy) -import Ctl.Examples.Helpers (mkCurrencySymbol, mkTokenName) as Helpers +import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head) import Data.Array (sort) as Array import Data.Map (fromFoldable, keys, member) as Map import Data.Set (findMin) as Set -import JS.BigInt (BigInt, fromInt) +import JS.BigInt as BigInt newtype ContractParams = ContractParams { aliceKeyWallet :: KeyWallet @@ -87,13 +92,13 @@ assertChangeOutputsPartitionedCorrectly = assertionToCheck let values :: Array Value values = - changeOutputs <#> _.amount <<< unwrap <<< _.output <<< unwrap + changeOutputs <#> _.amount <<< unwrap - tokenQuantities :: Array BigInt + tokenQuantities :: Array BigNum tokenQuantities = - Array.sort $ values <#> \v -> Value.valueOf v cs tn + Array.sort $ values <#> \v -> Value.valueOf (Asset cs tn) v - tokenQuantities == map fromInt [ 3, 4, 4 ] + tokenQuantities == map BigNum.fromInt [ 3, 4, 4 ] -- | Checks that the utxo with the specified output reference -- | (`nonSpendableOref`) is not consumed during transaction balancing. @@ -124,7 +129,7 @@ contract (ContractParams p) = do aliceAddress <- liftedM "Failed to get Alice's address" $ head - <$> (withKeyWallet p.aliceKeyWallet getWalletAddressesWithNetworkTag) + <$> (withKeyWallet p.aliceKeyWallet getWalletAddresses) alicePubKeyHash <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes @@ -137,7 +142,7 @@ contract (ContractParams p) = do bobAddress <- liftedM "Failed to get Bob's address" $ head - <$> (withKeyWallet p.bobKeyWallet getWalletAddressesWithNetworkTag) + <$> (withKeyWallet p.bobKeyWallet getWalletAddresses) bobsCollateralArray <- withKeyWallet p.bobKeyWallet do fold <$> getWalletCollateral @@ -149,30 +154,31 @@ contract (ContractParams p) = do nonSpendableOref <- liftedM "Failed to get utxos at Alice's address" (Set.findMin <<< Map.keys <$> utxosAt aliceAddress) - - mp /\ cs <- Helpers.mkCurrencySymbol alwaysMintsPolicy - tn <- Helpers.mkTokenName "The Token" + mp <- alwaysMintsPolicy + let cs = PlutusScript.hash mp + tn <- Helpers.mkAssetName "The Token" let constraints :: Constraints.TxConstraints constraints = - Constraints.mustMintValue (Value.singleton cs tn $ fromInt 11) + Constraints.mustMintValue (Mint.singleton cs tn $ Int.fromInt 11) <> foldMap Constraints.mustBeSignedBy [ alicePubKeyHash, bobPubKeyHash ] lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp + lookups = Lookups.plutusMintingPolicy mp - balanceTxConstraints :: BalanceTxConstraints.BalanceTxConstraintsBuilder + balanceTxConstraints :: BalancerConstraints balanceTxConstraints = - BalanceTxConstraints.mustGenChangeOutsWithMaxTokenQuantity (fromInt 4) - <> BalanceTxConstraints.mustUseUtxosAtAddress bobAddress - <> BalanceTxConstraints.mustSendChangeToAddress bobAddress - <> BalanceTxConstraints.mustNotSpendUtxoWithOutRef nonSpendableOref - <> BalanceTxConstraints.mustUseCollateralUtxos bobsCollateral + mustGenChangeOutsWithMaxTokenQuantity + (BigInt.fromInt 4) + <> mustUseUtxosAtAddress bobAddress + <> mustSendChangeToAddress bobAddress + <> mustNotSpendUtxoWithOutRef nonSpendableOref + <> mustUseCollateralUtxos bobsCollateral void $ runChecks checks $ lift do - unbalancedTx <- mkUnbalancedTx lookups constraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTxWithConstraints unbalancedTx balanceTxConstraints + balancedTx <- balanceTx unbalancedTx usedUtxos balanceTxConstraints balancedSignedTx <- (withKeyWallet p.bobKeyWallet <<< signTransaction) @@ -184,11 +190,11 @@ contract (ContractParams p) = do awaitTxConfirmed txHash logInfo' "Tx submitted successfully!" - let changeAddress = (unwrap bobAddress).address + let changeAddress = bobAddress pure { txHash , changeAddress - , nonSpendableAddress: (unwrap aliceAddress).address + , nonSpendableAddress: aliceAddress , mintedToken: cs /\ tn , nonSpendableOref } diff --git a/examples/ByUrl.purs b/examples/ByUrl.purs index e4f75e7e1f..57ef2b7a20 100644 --- a/examples/ByUrl.purs +++ b/examples/ByUrl.purs @@ -4,32 +4,16 @@ import Prelude import Contract.Config ( ContractParams - , WalletSpec - ( ConnectToNami - , ConnectToGero - , ConnectToLode - , ConnectToEternl - , ConnectToFlint - , ConnectToNuFi - , ConnectToLace - ) + , KnownWallet(Nami, Gero, Flint, Eternl, Lode, Lace, NuFi) + , WalletSpec(ConnectToGenericCip30) , blockfrostPublicPreprodServerConfig , blockfrostPublicPreviewServerConfig - , mainnetFlintConfig - , mainnetGeroConfig - , mainnetLodeConfig - , mainnetNamiConfig - , mainnetNuFiConfig + , mainnetConfig , mkBlockfrostBackendParams , testnetConfig - , testnetEternlConfig - , testnetFlintConfig - , testnetGeroConfig - , testnetLaceConfig - , testnetLodeConfig - , testnetNamiConfig - , testnetNuFiConfig + , walletName ) +import Contract.Log (logInfo') import Contract.Monad (Contract) import Contract.Test.E2E (E2EConfigName, E2ETestName, addLinks, route) import Ctl.Examples.AdditionalUtxos as AdditionalUtxos @@ -40,6 +24,7 @@ import Ctl.Examples.Cip30 as Cip30 import Ctl.Examples.Datums as Datums import Ctl.Examples.DropTokens as DropTokens import Ctl.Examples.ECDSA as ECDSA +import Ctl.Examples.IncludeDatum (contract) as IncludeDatum import Ctl.Examples.MintsMultipleTokens as MintsMultipleTokens import Ctl.Examples.NativeScriptMints as NativeScriptMints import Ctl.Examples.OneShotMinting as OneShotMinting @@ -47,7 +32,6 @@ import Ctl.Examples.PaysWithDatum as PaysWithDatum import Ctl.Examples.Pkh2Pkh as Pkh2Pkh import Ctl.Examples.PlutusV2.AlwaysSucceeds as AlwaysSucceedsV2 import Ctl.Examples.PlutusV2.OneShotMinting as OneShotMintingV2 -import Ctl.Examples.PlutusV2.ReferenceInputs as ReferenceInputsV2 import Ctl.Examples.PlutusV2.ReferenceInputsAndScripts as ReferenceInputsAndScriptsV2 import Ctl.Examples.Schnorr as Schnorr import Ctl.Examples.SendsToken as SendsToken @@ -56,9 +40,6 @@ import Ctl.Examples.SignMultiple as SignMultiple import Ctl.Examples.TxChaining as TxChaining import Ctl.Examples.Utxos as Utxos import Ctl.Examples.Wallet as Wallet -import Ctl.Internal.Wallet.Cip30Mock - ( WalletMock(MockNami, MockGero, MockFlint, MockLode, MockNuFi) - ) import Data.Map (Map) import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing), isNothing) @@ -77,6 +58,8 @@ main = do -- To set it up, run `npm run e2e-browser` and follow the instructions. mbApiKey <- getBlockfrostApiKey let + connectTo wallet = + Just $ ConnectToGenericCip30 (walletName wallet) { cip95: false } walletsWithBlockfrost = wallets `Map.union` if isNothing mbApiKey then Map.empty @@ -84,59 +67,59 @@ main = do Map.fromFoldable [ "blockfrost-nami-preview" /\ (mkBlockfrostPreviewConfig mbApiKey) - { walletSpec = Just ConnectToNami } + { walletSpec = connectTo Nami } /\ Nothing , "blockfrost-gero-preview" /\ (mkBlockfrostPreviewConfig mbApiKey) - { walletSpec = Just ConnectToGero } + { walletSpec = connectTo Gero } /\ Nothing , "blockfrost-eternl-preview" /\ (mkBlockfrostPreviewConfig mbApiKey) - { walletSpec = Just ConnectToEternl } + { walletSpec = connectTo Eternl } /\ Nothing , "blockfrost-lode-preview" /\ (mkBlockfrostPreviewConfig mbApiKey) - { walletSpec = Just ConnectToLode } + { walletSpec = connectTo Lode } /\ Nothing , "blockfrost-flint-preview" /\ (mkBlockfrostPreviewConfig mbApiKey) - { walletSpec = Just ConnectToFlint } + { walletSpec = connectTo Flint } /\ Nothing , "blockfrost-nufi-preview" /\ (mkBlockfrostPreviewConfig mbApiKey) - { walletSpec = Just ConnectToNuFi } + { walletSpec = connectTo NuFi } /\ Nothing , "blockfrost-lace-preview" /\ (mkBlockfrostPreviewConfig mbApiKey) - { walletSpec = Just ConnectToLace } + { walletSpec = connectTo Lace } /\ Nothing , "blockfrost-nami-preprod" /\ (mkBlockfrostPreprodConfig mbApiKey) - { walletSpec = Just ConnectToNami } + { walletSpec = connectTo Nami } /\ Nothing , "blockfrost-gero-preprod" /\ (mkBlockfrostPreprodConfig mbApiKey) - { walletSpec = Just ConnectToGero } + { walletSpec = connectTo Gero } /\ Nothing , "blockfrost-eternl-preprod" /\ (mkBlockfrostPreprodConfig mbApiKey) - { walletSpec = Just ConnectToEternl } + { walletSpec = connectTo Eternl } /\ Nothing , "blockfrost-lode-preprod" /\ (mkBlockfrostPreprodConfig mbApiKey) - { walletSpec = Just ConnectToLode } + { walletSpec = connectTo Lode } /\ Nothing , "blockfrost-flint-preprod" /\ (mkBlockfrostPreprodConfig mbApiKey) - { walletSpec = Just ConnectToFlint } + { walletSpec = connectTo Flint } /\ Nothing , "blockfrost-nufi-preprod" /\ (mkBlockfrostPreprodConfig mbApiKey) - { walletSpec = Just ConnectToNuFi } + { walletSpec = connectTo NuFi } /\ Nothing , "blockfrost-lace-preprod" /\ (mkBlockfrostPreprodConfig mbApiKey) - { walletSpec = Just ConnectToLace } + { walletSpec = connectTo Lace } /\ Nothing ] addLinks walletsWithBlockfrost examples @@ -153,26 +136,40 @@ getBlockfrostApiKey = do Console.log " localStorage.setItem('BLOCKFROST_API_KEY', 'your-key-here');" pure res -wallets :: Map E2EConfigName (ContractParams /\ Maybe WalletMock) -wallets = Map.fromFoldable - [ "nami" /\ testnetNamiConfig /\ Nothing - , "gero" /\ testnetGeroConfig /\ Nothing - , "flint" /\ testnetFlintConfig /\ Nothing - , "eternl" /\ testnetEternlConfig /\ Nothing - , "lode" /\ testnetLodeConfig /\ Nothing - , "nufi" /\ testnetNuFiConfig /\ Nothing - , "lace" /\ testnetLaceConfig /\ Nothing - , "nami-mock" /\ testnetNamiConfig /\ Just MockNami - , "gero-mock" /\ testnetGeroConfig /\ Just MockGero - , "flint-mock" /\ testnetFlintConfig /\ Just MockFlint - , "lode-mock" /\ testnetLodeConfig /\ Just MockLode - -- Plutip cluster's network ID is set to mainnet: - , "plutip-nami-mock" /\ mainnetNamiConfig /\ Just MockNami - , "plutip-gero-mock" /\ mainnetGeroConfig /\ Just MockGero - , "plutip-flint-mock" /\ mainnetFlintConfig /\ Just MockFlint - , "plutip-lode-mock" /\ mainnetLodeConfig /\ Just MockLode - , "plutip-nufi-mock" /\ mainnetNuFiConfig /\ Just MockNuFi +wallets :: Map E2EConfigName (ContractParams /\ Maybe String) +wallets = map (map walletName) <$> Map.fromFoldable + [ "nami" /\ testnetConfig' Nami /\ Nothing + , "gero" /\ testnetConfig' Gero /\ Nothing + , "flint" /\ testnetConfig' Flint /\ Nothing + , "eternl" /\ testnetConfig' Eternl /\ Nothing + , "lode" /\ testnetConfig' Lode /\ Nothing + , "nufi" /\ testnetConfig' NuFi /\ Nothing + , "lace" /\ testnetConfig' Lace /\ Nothing + , "nami-mainnet" /\ mainnetNamiConfig /\ Nothing + , "nami-mock" /\ testnetConfig' Nami /\ Just Nami + , "gero-mock" /\ testnetConfig' Gero /\ Just Gero + , "flint-mock" /\ testnetConfig' Flint /\ Just Flint + , "lode-mock" /\ testnetConfig' Lode /\ Just Lode + , "plutip-nami-mock" /\ testnetConfig' Nami /\ Just Nami + , "plutip-gero-mock" /\ testnetConfig' Gero /\ Just Gero + , "plutip-flint-mock" /\ testnetConfig' Flint /\ Just Flint + , "plutip-lode-mock" /\ testnetConfig' Lode /\ Just Lode + , "plutip-nufi-mock" /\ testnetConfig' NuFi /\ Just NuFi ] + where + testnetConfig' :: KnownWallet -> ContractParams + testnetConfig' wallet = + testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName wallet) { cip95: false } + } + + mainnetNamiConfig :: ContractParams + mainnetNamiConfig = + mainnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } mkBlockfrostPreviewConfig :: Maybe String -> ContractParams mkBlockfrostPreviewConfig apiKey = @@ -195,7 +192,7 @@ mkBlockfrostPreprodConfig apiKey = } examples :: Map E2ETestName (Contract Unit) -examples = Map.fromFoldable +examples = addSuccessLog <$> Map.fromFoldable [ "AdditionalUtxos" /\ AdditionalUtxos.contract false , "AlwaysMints" /\ AlwaysMints.contract , "NativeScriptMints" /\ NativeScriptMints.contract @@ -212,7 +209,6 @@ examples = Map.fromFoldable , "OneShotMinting" /\ OneShotMinting.contract , "OneShotMintingV2" /\ OneShotMintingV2.contract , "Cip30" /\ Cip30.contract - , "ReferenceInputs" /\ ReferenceInputsV2.contract , "ReferenceInputsAndScripts" /\ ReferenceInputsAndScriptsV2.contract , "Utxos" /\ Utxos.contract , "ApplyArgs" /\ ApplyArgs.contract @@ -226,4 +222,8 @@ examples = Map.fromFoldable ChangeGeneration.checkChangeOutputsDistribution 3 1 5 , "ChangeGeneration1-3" /\ ChangeGeneration.checkChangeOutputsDistribution 1 3 7 + , "IncludeDatum" /\ IncludeDatum.contract ] + +addSuccessLog :: Contract Unit -> Contract Unit +addSuccessLog contract = contract *> logInfo' "[CTL TEST SUCCESS]" diff --git a/examples/ChangeGeneration.purs b/examples/ChangeGeneration.purs index 1c416701e8..1c15e1bb57 100644 --- a/examples/ChangeGeneration.purs +++ b/examples/ChangeGeneration.purs @@ -2,35 +2,37 @@ module Ctl.Examples.ChangeGeneration (checkChangeOutputsDistribution) where import Prelude -import Contract.BalanceTxConstraints (mustSendChangeWithDatum) -import Contract.Monad (Contract) -import Contract.PlutusData - ( Datum(Datum) - , OutputDatum(OutputDatum) - , PlutusData(Integer) - , unitDatum +import Cardano.Transaction.Builder (TransactionBuilderStep(Pay)) +import Cardano.Types + ( Credential(ScriptHashCredential) + , OutputDatum(OutputDatumHash) + , PaymentCredential(PaymentCredential) + , TransactionOutput(TransactionOutput) + , _body + , _outputs ) -import Contract.ScriptLookups as Lookups +import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Contract.Address (mkAddress) +import Contract.BalanceTxConstraints (mustSendChangeWithDatum) +import Contract.Monad (Contract, liftedM) +import Contract.PlutusData (OutputDatum(OutputDatum), PlutusData(Integer)) import Contract.Scripts (validatorHash) import Contract.Transaction - ( _body - , _outputs - , awaitTxConfirmed - , balanceTxWithConstraints + ( awaitTxConfirmed + , balanceTx + , buildTx , signTransaction , submit ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value as Value -import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) +import Contract.Wallet (getWalletAddress) import Ctl.Examples.AlwaysSucceeds as AlwaysSucceeds -import Data.Array (fold, length, replicate, take, zip) -import Data.Lens (to, (^.)) +import Data.Array (length, replicate) +import Data.Lens ((^.)) +import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (unwrap) -import Data.Tuple (Tuple(Tuple)) import JS.BigInt (fromInt) as BigInt import Test.Spec.Assertions (shouldEqual) @@ -40,38 +42,42 @@ import Test.Spec.Assertions (shouldEqual) checkChangeOutputsDistribution :: Int -> Int -> Int -> Contract Unit checkChangeOutputsDistribution outputsToScript outputsToSelf expectedOutputs = do - pkhs <- ownPaymentPubKeyHashes - skhs <- ownStakePubKeyHashes validator <- AlwaysSucceeds.alwaysSucceedsScript + address <- liftedM "Failed to get own address" $ getWalletAddress let vhash = validatorHash validator - value = Value.lovelaceValueOf $ BigInt.fromInt 1000001 - - constraintsToSelf :: TxConstraints - constraintsToSelf = fold <<< take outputsToSelf <<< fold - $ replicate outputsToSelf - $ zip pkhs skhs <#> \(Tuple pkh mbSkh) -> case mbSkh of - Nothing -> Constraints.mustPayToPubKey pkh value - Just skh -> Constraints.mustPayToPubKeyAddress pkh skh value - - constraintsToScripts :: TxConstraints - constraintsToScripts = fold $ replicate outputsToScript - $ Constraints.mustPayToScript vhash unitDatum - Constraints.DatumWitness - value + scriptAddress <- mkAddress + (PaymentCredential $ ScriptHashCredential $ vhash) + Nothing + let + value = Value.lovelaceValueOf $ BigNum.fromInt 1000001 - constraints = constraintsToSelf <> constraintsToScripts + plan = + replicate outputsToSelf + ( Pay $ TransactionOutput + { address: address + , amount: value + , datum: Nothing + , scriptRef: Nothing + } + ) <> + replicate outputsToScript + ( Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ) - lookups :: Lookups.ScriptLookups - lookups = mempty - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTxWithConstraints unbalancedTx + unbalancedTx <- buildTx plan + balancedTx <- balanceTx unbalancedTx Map.empty -- just to check that attaching datums works - ( mustSendChangeWithDatum $ OutputDatum $ Datum $ Integer $ BigInt.fromInt + ( mustSendChangeWithDatum $ OutputDatum $ Integer $ BigInt.fromInt 1000 ) balancedSignedTx <- signTransaction balancedTx - let outputs = balancedTx ^. to unwrap <<< _body <<< _outputs + let outputs = balancedTx ^. _body <<< _outputs length outputs `shouldEqual` expectedOutputs txHash <- submit balancedSignedTx awaitTxConfirmed txHash diff --git a/examples/Cip30.purs b/examples/Cip30.purs index 4b6c43a752..eb45938f21 100644 --- a/examples/Cip30.purs +++ b/examples/Cip30.purs @@ -15,10 +15,16 @@ import Cardano.Wallet.Cip30 , getName ) import Cardano.Wallet.Cip30.TypeSafe as Cip30 -import Contract.Config (ContractParams, testnetNamiConfig) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftContractAffM, runContract) -import Contract.Prim.ByteArray (rawBytesFromAscii) +import Contract.Prim.ByteArray (byteArrayFromAscii) import Contract.Wallet ( getChangeAddress , getRewardAddresses @@ -30,7 +36,10 @@ import Data.Array (head) import Effect.Exception (error) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -62,7 +71,7 @@ contract = do _ <- performAndLog "getUnusedAddresses" getUnusedAddresses dataBytes <- liftContractAffM ("can't convert : " <> msg <> " to RawBytes") - (pure mDataBytes) + (pure $ wrap <$> mDataBytes) mRewardAddress <- performAndLog "getRewardAddresses" getRewardAddresses rewardAddr <- liftMaybe (error "can't get reward address") $ head mRewardAddress @@ -71,7 +80,7 @@ contract = do void $ performAndLog "signData rewardAddress" $ signData rewardAddr dataBytes where msg = "hello world!" - mDataBytes = rawBytesFromAscii msg + mDataBytes = byteArrayFromAscii msg performAndLog :: forall (a :: Type) diff --git a/examples/ContractTestUtils.purs b/examples/ContractTestUtils.purs index 0867350285..570776223b 100644 --- a/examples/ContractTestUtils.purs +++ b/examples/ContractTestUtils.purs @@ -11,27 +11,39 @@ module Ctl.Examples.ContractTestUtils import Contract.Prelude -import Contract.Address - ( Address - , PaymentPubKeyHash - , StakePubKeyHash - , getNetworkId - , payPubKeyHashBaseAddress - , payPubKeyHashEnterpriseAddress +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, MintAsset) ) -import Contract.AuxiliaryData (setTxMetadata) +import Cardano.Types + ( BigNum + , Coin + , ExUnits(ExUnits) + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , TransactionOutput(TransactionOutput) + , _body + , _datum + , _fee + , _output + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Credential (Credential(PubKeyHashCredential)) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.Int as Int +import Cardano.Types.PlutusScript (PlutusScript) +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.ScriptRef (ScriptRef(PlutusScriptRef)) +import Contract.Address (Address, PaymentPubKeyHash, StakePubKeyHash, mkAddress) import Contract.Hashing (datumHash) import Contract.Log (logInfo') -import Contract.Metadata (Cip25Metadata) import Contract.Monad (Contract, liftContractM, liftedM) import Contract.PlutusData (Datum, OutputDatum(OutputDatumHash)) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (MintingPolicy) import Contract.Test.Assert ( ContractCheck , assertOutputHasDatum , assertOutputHasRefScript - , assertTxHasMetadata , assertionToCheck , checkExUnitsNotExceed , checkGainAtAddress' @@ -41,20 +53,14 @@ import Contract.Test.Assert ) import Contract.Transaction ( TransactionHash - , TransactionOutputWithRefScript , TransactionUnspentOutput - , _output , awaitTxConfirmed , balanceTx - , getTxFinalFee + , buildTx , lookupTxHash - , scriptRefFromMintingPolicy , signTransaction , submit ) -import Contract.TxConstraints (DatumPresence(DatumWitness)) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Utxos (utxosAt) import Contract.Value (CurrencySymbol, TokenName, Value) import Contract.Value (lovelaceValueOf, singleton) as Value @@ -63,27 +69,24 @@ import Contract.Wallet , ownPaymentPubKeyHashes , ownStakePubKeyHashes ) -import Ctl.Examples.Helpers (mustPayToPubKeyStakeAddress) as Helpers import Data.Array (head) import Data.Lens (view) +import Data.Map as Map import Effect.Exception (throw) -import JS.BigInt (BigInt) -import JS.BigInt as BigInt type ContractParams = { receiverPkh :: PaymentPubKeyHash , receiverSkh :: Maybe StakePubKeyHash - , adaToSend :: BigInt - , mintingPolicy :: MintingPolicy - , tokensToMint :: Tuple3 CurrencySymbol TokenName BigInt + , adaToSend :: Coin + , mintingPolicy :: PlutusScript + , tokensToMint :: Tuple3 CurrencySymbol TokenName BigNum , datumToAttach :: Datum - , txMetadata :: Cip25Metadata } type ContractResult = { txHash :: TransactionHash - , txFinalFee :: BigInt - , txOutputUnderTest :: TransactionOutputWithRefScript + , txFinalFee :: Coin + , txOutputUnderTest :: TransactionOutput } mkChecks @@ -92,40 +95,40 @@ mkChecks mkChecks p = do senderAddress <- liftedM "Failed to get sender address" $ head <$> getWalletAddresses - receiverAddress <- - liftedM "Failed to get receiver address" (getReceiverAddress p) + receiverAddress <- getReceiverAddress p let dhash = datumHash p.datumToAttach pure [ checkGainAtAddress' (label receiverAddress "Receiver") - p.adaToSend + (BigNum.toBigInt $ unwrap p.adaToSend) , checkLossAtAddress (label senderAddress "Sender") case _ of - Just { txFinalFee } -> pure (p.adaToSend + txFinalFee) + Just { txFinalFee } -> pure + ( BigNum.toBigInt (unwrap p.adaToSend) + BigNum.toBigInt + (unwrap txFinalFee) + ) Nothing -> liftEffect $ throw "Unable to estimate expected loss in wallet" , checkTokenGainAtAddress' (label senderAddress "Sender") - ( uncurry3 (\cs tn amount -> cs /\ tn /\ amount) + ( uncurry3 (\cs tn amount -> cs /\ tn /\ BigNum.toBigInt amount) p.tokensToMint ) , checkExUnitsNotExceed - { mem: BigInt.fromInt 800, steps: BigInt.fromInt 161100 } + (ExUnits { mem: BigNum.fromInt 800, steps: BigNum.fromInt 161100 }) , assertionToCheck "Sender's output has a datum" \{ txOutputUnderTest } -> - assertOutputHasDatum (OutputDatumHash dhash) + assertOutputHasDatum (Just $ OutputDatumHash dhash) (label txOutputUnderTest "Sender's output with datum hash") , assertionToCheck "Output has a reference script" \{ txOutputUnderTest } -> assertOutputHasRefScript - (scriptRefFromMintingPolicy p.mintingPolicy) + (PlutusScriptRef p.mintingPolicy) (label txOutputUnderTest "Sender's output with reference script") - , assertionToCheck "Contains CIP-25 metadata" \{ txHash } -> - assertTxHasMetadata "CIP25 Metadata" txHash p.txMetadata ] mkContract :: ContractParams -> Contract ContractResult @@ -133,36 +136,40 @@ mkContract p = do logInfo' "Running Examples.ContractTestUtils" ownPkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes ownSkh <- join <<< head <$> ownStakePubKeyHashes + receiverAddress <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap p.receiverPkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> p.receiverSkh) + ownAddress <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap ownPkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> ownSkh) let - mustPayToPubKeyStakeAddressWithDatumAndScriptRef = - ownSkh # maybe Constraints.mustPayToPubKeyWithDatumAndScriptRef - \skh pkh -> - Constraints.mustPayToPubKeyAddressWithDatumAndScriptRef pkh skh - adaValue :: Value - adaValue = Value.lovelaceValueOf p.adaToSend + adaValue = Value.lovelaceValueOf (unwrap p.adaToSend) nonAdaValue :: Value nonAdaValue = uncurry3 Value.singleton p.tokensToMint - constraints :: Constraints.TxConstraints - constraints = mconcat - [ Helpers.mustPayToPubKeyStakeAddress p.receiverPkh p.receiverSkh adaValue - - , Constraints.mustMintValue nonAdaValue - - , mustPayToPubKeyStakeAddressWithDatumAndScriptRef ownPkh p.datumToAttach - DatumWitness - (scriptRefFromMintingPolicy p.mintingPolicy) - nonAdaValue + scriptHash /\ assetName /\ mintAmount /\ _ = p.tokensToMint + plan = + [ Pay $ TransactionOutput + { address: receiverAddress + , amount: adaValue + , datum: Nothing + , scriptRef: Nothing + } + , MintAsset scriptHash assetName (Int.newPositive mintAmount) + $ PlutusScriptCredential (ScriptValue p.mintingPolicy) + RedeemerDatum.unit + , Pay $ TransactionOutput + { address: ownAddress + , amount: nonAdaValue + , datum: Just $ OutputDatumHash $ hashPlutusData p.datumToAttach + , scriptRef: Just $ PlutusScriptRef p.mintingPolicy + } ] - lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy p.mintingPolicy - - unbalancedTx <- mkUnbalancedTx lookups constraints - unbalancedTxWithMetadata <- setTxMetadata unbalancedTx p.txMetadata - balancedTx <- balanceTx unbalancedTxWithMetadata + unbalancedTx <- buildTx plan + balancedTx <- balanceTx unbalancedTx Map.empty mempty balancedSignedTx <- signTransaction balancedTx txId <- submit balancedSignedTx @@ -182,21 +189,17 @@ mkContract p = do pure { txHash: txId - , txFinalFee: getTxFinalFee balancedSignedTx + , txFinalFee: view (_body <<< _fee) balancedSignedTx , txOutputUnderTest } where hasDatumHash :: TransactionUnspentOutput -> Boolean - hasDatumHash = view _output >>> unwrap >>> _.output >>> unwrap >>> _.datum >>> + hasDatumHash = view (_output <<< _datum) >>> case _ of - OutputDatumHash _ -> true + Just (OutputDatumHash _) -> true _ -> false -getReceiverAddress :: ContractParams -> Contract (Maybe Address) +getReceiverAddress :: ContractParams -> Contract Address getReceiverAddress { receiverPkh, receiverSkh } = - getNetworkId <#> \networkId -> - case receiverSkh of - Just skh -> - payPubKeyHashBaseAddress networkId receiverPkh skh - Nothing -> - payPubKeyHashEnterpriseAddress networkId receiverPkh + mkAddress (wrap $ PubKeyHashCredential $ unwrap receiverPkh) + (wrap <<< PubKeyHashCredential <<< unwrap <$> receiverSkh) diff --git a/examples/Datums.purs b/examples/Datums.purs index ca631287c5..a363cea92e 100644 --- a/examples/Datums.purs +++ b/examples/Datums.purs @@ -20,11 +20,13 @@ module Ctl.Examples.Datums (main, contract, example) where import Contract.Prelude +import Cardano.AsCbor (decodeCbor) import Contract.Config (ContractParams, testnetConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) import Contract.PlutusData (DataHash, getDatumByHash, getDatumsByHashes) -import Contract.Prim.ByteArray (hexToByteArrayUnsafe) +import Data.ByteArray (hexToByteArrayUnsafe) +import Partial.Unsafe (unsafePartial) main :: Effect Unit main = example testnetConfig @@ -44,7 +46,8 @@ contract = do ] where mkDatumHash :: String -> DataHash - mkDatumHash = wrap <<< hexToByteArrayUnsafe + mkDatumHash = unsafePartial $ fromJust <<< decodeCbor <<< wrap <<< + hexToByteArrayUnsafe example :: ContractParams -> Effect Unit example cfg = launchAff_ $ do diff --git a/examples/DropTokens.purs b/examples/DropTokens.purs index 6ef12aeeef..5381ddf79c 100644 --- a/examples/DropTokens.purs +++ b/examples/DropTokens.purs @@ -4,26 +4,32 @@ module Ctl.Examples.DropTokens (main, example, contract) where import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.Value as Value +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) import Contract.ScriptLookups as Lookups import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) import Contract.TxConstraints as Constraints import Contract.TxConstraints as Helpers -import Contract.Value - ( coinToValue - , flattenNonAdaAssets - , negation - , singleton - , valueToCoin - ) +import Contract.Value (singleton) import Contract.Wallet (getWalletBalance) import Data.Array as Array +import Partial.Unsafe (unsafePartial) import Test.Ctl.Fixtures (nullPaymentPubKeyHash) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -33,15 +39,16 @@ contract :: Contract Unit contract = do logInfo' "Running Examples.DropTokens" logInfo' "Going to get rid of half of the tokens available" - value <- getWalletBalance <#> fold + value <- unsafePartial $ getWalletBalance <#> fold let - tokenValue = value <> negation (coinToValue (valueToCoin value)) halfArray arr = Array.take (Array.length arr `div` 2) arr -- drop half of the tokens tokenValueHalf = - fold $ halfArray (flattenNonAdaAssets tokenValue) <#> - \(cs /\ tn /\ n) -> singleton cs tn n + unsafePartial $ fold + $ halfArray (MultiAsset.flatten $ Value.getMultiAsset value) + <#> + \(cs /\ tn /\ n) -> singleton cs tn n constraints :: Constraints.TxConstraints constraints = Helpers.mustPayToPubKey nullPaymentPubKeyHash tokenValueHalf diff --git a/examples/ECDSA.purs b/examples/ECDSA.purs index 5cec166130..42b5366af9 100644 --- a/examples/ECDSA.purs +++ b/examples/ECDSA.purs @@ -2,13 +2,30 @@ module Ctl.Examples.ECDSA (contract) where import Contract.Prelude -import Contract.Address (getNetworkId, validatorHashEnterpriseAddress) +import Cardano.Transaction.Builder + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) +import Cardano.Types + ( OutputDatum(OutputDatumHash) + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.Credential (Credential(ScriptHashCredential)) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (_input, fromUtxoMap, toUtxoMap) +import Contract.Address (mkAddress) import Contract.Crypto.Secp256k1.ECDSA ( ECDSAPublicKey , ECDSASignature , MessageHash , deriveEcdsaSecp256k1PublicKey , signEcdsaSecp256k1 + , unECDSAPublicKey + , unMessageHash ) import Contract.Crypto.Secp256k1.Utils ( hashMessageSha256 @@ -20,24 +37,23 @@ import Contract.Numeric.BigNum as BigNum import Contract.PlutusData ( class ToData , PlutusData(Constr) - , Redeemer(Redeemer) + , RedeemerDatum(RedeemerDatum) , toData - , unitDatum ) import Contract.Prim.ByteArray (byteArrayFromIntArrayUnsafe) -import Contract.ScriptLookups as Lookups import Contract.Scripts (Validator, validatorHash) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV2FromEnvelope) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash , awaitTxConfirmed - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value +import Data.Array as Array +import Data.Lens (view) import Data.Map as Map -import Data.Set as Set +import Noble.Secp256k1.ECDSA (unECDSASignature) newtype ECDSARedemeer = ECDSARedemeer { msg :: MessageHash @@ -50,7 +66,10 @@ derive instance Newtype ECDSARedemeer _ instance ToData ECDSARedemeer where toData (ECDSARedemeer { msg, sig, pk }) = Constr BigNum.zero - [ toData msg, toData sig, toData pk ] + [ toData $ unMessageHash msg + , toData $ unECDSASignature sig + , toData $ unECDSAPublicKey pk + ] contract :: Contract Unit contract = do @@ -59,54 +78,54 @@ contract = do -- | Prepare the ECDSA test by locking some funds at the validator address prepTest :: Contract TransactionHash prepTest = do - validator <- liftContractM "Caonnot get validator" getValidator + validator <- liftContractM "Cannot get validator" getValidator let valHash = validatorHash validator - - val = Value.lovelaceValueOf one - - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - - constraints :: Constraints.TxConstraints - constraints = Constraints.mustPayToScript valHash unitDatum - Constraints.DatumInline - val - txId <- submitTxFromConstraints lookups constraints + val = Value.lovelaceValueOf BigNum.one + scriptAddress <- mkAddress + (wrap $ ScriptHashCredential valHash) + Nothing + tx <- submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: val + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + let txId = Transaction.hash tx logInfo' $ "Submitted ECDSA test preparation tx: " <> show txId awaitTxConfirmed txId logInfo' $ "Transaction confirmed: " <> show txId - pure txId -- | Attempt to unlock one utxo using an ECDSA signature testVerification :: TransactionHash -> ECDSARedemeer -> Contract TransactionHash testVerification txId ecdsaRed = do - let red = Redeemer $ toData ecdsaRed + let redeemer = RedeemerDatum $ toData ecdsaRed validator <- liftContractM "Can't get validator" getValidator let valHash = validatorHash validator - netId <- getNetworkId - valAddr <- liftContractM "cannot get validator address" - (validatorHashEnterpriseAddress netId valHash) + valAddr <- mkAddress (wrap $ ScriptHashCredential valHash) Nothing scriptUtxos <- utxosAt valAddr - txIn <- liftContractM "No UTxOs found at validator address" - $ Set.toUnfoldable - $ Set.filter (unwrap >>> _.transactionId >>> eq txId) - $ Map.keys scriptUtxos - - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs - (Map.filterKeys ((unwrap >>> _.transactionId >>> eq txId)) scriptUtxos) - - constraints :: Constraints.TxConstraints - constraints = Constraints.mustSpendScriptOutput txIn red - txId' <- submitTxFromConstraints lookups constraints + utxo <- liftContractM "No UTxOs found at validator address" + $ Array.head + $ Array.filter (view _input >>> unwrap >>> _.transactionId >>> eq txId) + $ fromUtxoMap scriptUtxos + + tx <- submitTxFromBuildPlan (toUtxoMap [ utxo ]) mempty + [ SpendOutput utxo $ Just + $ PlutusScriptOutput + (ScriptValue validator) + redeemer + $ Just + $ DatumValue + $ PlutusData.unit + ] + let txId' = Transaction.hash tx logInfo' $ "Submitted ECDSA test verification tx: " <> show txId' awaitTxConfirmed txId' logInfo' $ "Transaction confirmed: " <> show txId' @@ -130,7 +149,7 @@ testECDSA txId = do getValidator :: Maybe Validator getValidator = - decodeTextEnvelope validateECDSA >>= plutusScriptV2FromEnvelope >>> map wrap + decodeTextEnvelope validateECDSA >>= plutusScriptFromEnvelope validateECDSA :: String validateECDSA = diff --git a/examples/ExUnits.purs b/examples/ExUnits.purs index 6340d689f1..1fdb5dfa06 100644 --- a/examples/ExUnits.purs +++ b/examples/ExUnits.purs @@ -2,44 +2,56 @@ module Ctl.Examples.ExUnits where import Contract.Prelude -import Contract.Address (scriptHashAddress) -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Credential (Credential(PubKeyCredential)) -import Contract.Log (logInfo') -import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData - ( Redeemer(Redeemer) - , toData - , unitDatum +import Cardano.Transaction.Builder + ( OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, SpendOutput) + ) +import Cardano.Types + ( Credential(ScriptHashCredential) + , OutputDatum(OutputDatum) + , PaymentCredential(PaymentCredential) + , TransactionOutput(TransactionOutput) ) -import Contract.ScriptLookups as Lookups -import Contract.Scripts - ( Validator(Validator) - , ValidatorHash - , validatorHash +import Cardano.Types.BigNum as BigNum +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) +import Contract.Address (mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName ) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV2FromEnvelope) +import Contract.Credential (Credential(PubKeyHashCredential)) +import Contract.Log (logInfo') +import Contract.Monad (Contract, launchAff_, runContract) +import Contract.PlutusData (RedeemerDatum(RedeemerDatum), toData) +import Contract.Scripts (Validator, ValidatorHash, validatorHash) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash - , _input , awaitTxConfirmed , lookupTxHash - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value import Contract.Wallet (ownStakePubKeyHashes) import Control.Monad.Error.Class (liftMaybe) import Data.Array (head) -import Data.Lens (view) +import Data.Map as Map import Effect.Exception (error) import JS.BigInt (BigInt) import JS.BigInt as BigInt main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } contract :: Contract Unit contract = do @@ -58,29 +70,17 @@ example cfg = launchAff_ do payToExUnits :: ValidatorHash -> Contract TransactionHash payToExUnits vhash = do - -- Send to own stake credential. This is used to test mustPayToScriptAddress. - mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - let - constraints :: TxConstraints - constraints = - case mbStakeKeyHash of - Nothing -> - Constraints.mustPayToScript vhash unitDatum - Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - Just stakeKeyHash -> - Constraints.mustPayToScriptAddress vhash - (PubKeyCredential $ unwrap stakeKeyHash) - unitDatum - Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + address <- mkAddress + (PaymentCredential $ ScriptHashCredential vhash) + Nothing + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Nothing + } + ] -- | ExUnits script loops a given number of iterations provided as redeemer. spendFromExUnits @@ -92,11 +92,11 @@ spendFromExUnits spendFromExUnits iters vhash validator txId = do -- Use own stake credential if available mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - let - scriptAddress = - scriptHashAddress vhash (PubKeyCredential <<< unwrap <$> mbStakeKeyHash) + scriptAddress <- + mkAddress (wrap $ ScriptHashCredential vhash) + (wrap <<< PubKeyHashCredential <<< unwrap <$> mbStakeKeyHash) utxos <- utxosAt scriptAddress - txInput <- + utxo <- liftM ( error ( "The id " @@ -105,24 +105,24 @@ spendFromExUnits iters vhash validator txId = do <> show scriptAddress ) ) - (view _input <$> head (lookupTxHash txId utxos)) - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput (Redeemer $ toData iters) + (head (lookupTxHash txId utxos)) - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId + spendTx <- submitTxFromBuildPlan (toUtxoMap [ utxo ]) + mempty + [ SpendOutput + utxo + $ Just + $ PlutusScriptOutput (ScriptValue validator) + (RedeemerDatum $ toData iters) + Nothing + ] + awaitTxConfirmed $ Transaction.hash spendTx logInfo' "Successfully spent locked values." exUnitsScript :: Contract Validator exUnitsScript = do liftMaybe (error "Error decoding exUnits") do envelope <- decodeTextEnvelope exUnits - Validator <$> plutusScriptV2FromEnvelope envelope + plutusScriptFromEnvelope envelope foreign import exUnits :: String diff --git a/examples/Gov/DelegateVoteAbstain.purs b/examples/Gov/DelegateVoteAbstain.purs new file mode 100644 index 0000000000..48d72e4bb4 --- /dev/null +++ b/examples/Gov/DelegateVoteAbstain.purs @@ -0,0 +1,61 @@ +module Ctl.Examples.Gov.DelegateVoteAbstain + ( contract + , example + , main + ) where + +import Contract.Prelude + +import Cardano.Transaction.Builder (TransactionBuilderStep(IssueCertificate)) +import Cardano.Types.Certificate (Certificate(VoteRegDelegCert)) +import Cardano.Types.Credential (Credential(PubKeyHashCredential)) +import Cardano.Types.DRep (DRep(AlwaysAbstain)) +import Cardano.Types.PublicKey (hash) as PublicKey +import Cardano.Types.Transaction (hash) as Transaction +import Contract.Config + ( ContractParams + , KnownWallet(Eternl) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) +import Contract.Log (logDebug', logInfo') +import Contract.Monad (Contract, launchAff_, runContract) +import Contract.ProtocolParameters (getProtocolParameters) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) +import Contract.Wallet (ownUnregisteredPubStakeKeys) +import Data.Array (head) as Array +import Data.Map (empty) as Map +import Effect.Exception (error) + +main :: Effect Unit +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Eternl) { cip95: true } + } + +example :: ContractParams -> Effect Unit +example = launchAff_ <<< flip runContract contract + +contract :: Contract Unit +contract = do + logInfo' "Running Examples.Gov.DelegateVoteAbstain" + + unregPubStakeKeys <- ownUnregisteredPubStakeKeys + logDebug' $ "Unregistered public stake keys: " <> show unregPubStakeKeys + + pubStakeKey <- liftM (error "Failed to get unregistered pub stake key") $ + Array.head unregPubStakeKeys + let stakeCred = wrap $ PubKeyHashCredential $ PublicKey.hash pubStakeKey + + stakeCredDeposit <- _.stakeAddressDeposit <<< unwrap <$> + getProtocolParameters + + tx <- submitTxFromBuildPlan Map.empty mempty + [ IssueCertificate + (VoteRegDelegCert stakeCred AlwaysAbstain stakeCredDeposit) + Nothing + ] + + awaitTxConfirmed $ Transaction.hash tx + logInfo' "Tx submitted successfully!" diff --git a/examples/Gov/Internal/Common.purs b/examples/Gov/Internal/Common.purs new file mode 100644 index 0000000000..8ef2e537fc --- /dev/null +++ b/examples/Gov/Internal/Common.purs @@ -0,0 +1,31 @@ +module Ctl.Examples.Gov.Internal.Common + ( asRewardAddress + , dummyAnchor + ) where + +import Contract.Prelude + +import Cardano.AsCbor (decodeCbor) +import Cardano.Types + ( Address(RewardAddress) + , Anchor(Anchor) + , RewardAddress + , URL(URL) + ) +import Contract.Prim.ByteArray (hexToByteArrayUnsafe) +import Partial.Unsafe (unsafePartial) + +asRewardAddress :: Address -> Maybe RewardAddress +asRewardAddress = case _ of + RewardAddress rewardAddr -> Just rewardAddr + _ -> Nothing + +dummyAnchor :: Anchor +dummyAnchor = + Anchor + { url: URL "https://example.com/" + , dataHash: + unsafePartial $ fromJust $ decodeCbor $ wrap $ + hexToByteArrayUnsafe + "94b8cac47761c1140c57a48d56ab15d27a842abff041b3798b8618fa84641f5a" + } diff --git a/examples/Gov/ManageDrep.purs b/examples/Gov/ManageDrep.purs new file mode 100644 index 0000000000..0966b7a228 --- /dev/null +++ b/examples/Gov/ManageDrep.purs @@ -0,0 +1,89 @@ +module Ctl.Examples.Gov.ManageDrep + ( ContractPath(RegDrep, UpdateDrep, UnregDrep) + , contract + , contractStep + , example + , main + ) where + +import Contract.Prelude + +import Cardano.Transaction.Builder (TransactionBuilderStep(IssueCertificate)) +import Cardano.Types + ( Anchor + , Certificate(RegDrepCert, UpdateDrepCert, UnregDrepCert) + , Credential(PubKeyHashCredential) + , Ed25519KeyHash + ) +import Cardano.Types.Transaction (hash) as Transaction +import Contract.Config + ( ContractParams + , KnownWallet(Eternl) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) +import Contract.Log (logInfo') +import Contract.Monad (Contract, launchAff_, runContract) +import Contract.ProtocolParameters (getProtocolParameters) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) +import Contract.Wallet (ownDrepPubKeyHash) +import Control.Monad.Error.Class (catchError, throwError) +import Ctl.Examples.Gov.Internal.Common (dummyAnchor) +import Data.Map (empty) as Map +import Data.String (Pattern(Pattern)) +import Data.String (contains) as String +import Effect.Exception (message) + +main :: Effect Unit +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Eternl) { cip95: true } + } + +example :: ContractParams -> Effect Unit +example = launchAff_ <<< flip runContract contract + +contract :: Contract Unit +contract = do + logInfo' "Running Examples.Gov.ManageDrep" + drepPkh <- contractStep RegDrep + logInfo' $ "Successfully registered DRep. DRepID: " <> show drepPkh + void $ contractStep $ UpdateDrep dummyAnchor + logInfo' "Successfully updated DRep metadata." + void $ contractStep UnregDrep + logInfo' "Successfully unregistered DRep." + +data ContractPath + = RegDrep + | UpdateDrep Anchor + | UnregDrep + +contractStep :: ContractPath -> Contract Ed25519KeyHash +contractStep path = do + drepPkh <- ownDrepPubKeyHash + let drepCred = PubKeyHashCredential drepPkh + drepDeposit <- _.drepDeposit <<< unwrap <$> getProtocolParameters + + let + submitTx = do + tx <- submitTxFromBuildPlan Map.empty mempty + [ IssueCertificate + ( case path of + RegDrep -> + RegDrepCert drepCred drepDeposit Nothing + UpdateDrep anchor -> + UpdateDrepCert drepCred $ Just anchor + UnregDrep -> + UnregDrepCert drepCred drepDeposit + ) + Nothing + ] + awaitTxConfirmed $ Transaction.hash tx + + submitTx `catchError` \err -> + unless + (String.contains (Pattern "knownDelegateRepresentative") $ message err) + (throwError err) + + pure drepPkh diff --git a/examples/Gov/ManageDrepScript.purs b/examples/Gov/ManageDrepScript.purs new file mode 100644 index 0000000000..e5595676dd --- /dev/null +++ b/examples/Gov/ManageDrepScript.purs @@ -0,0 +1,100 @@ +module Ctl.Examples.Gov.ManageDrepScript + ( ContractPath(RegDrep, UpdateDrep, UnregDrep) + , contract + , contractStep + , example + , main + ) where + +import Contract.Prelude + +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(IssueCertificate) + ) +import Cardano.Types + ( Anchor + , Certificate(RegDrepCert, UpdateDrepCert, UnregDrepCert) + , Credential(ScriptHashCredential) + , ScriptHash + ) +import Cardano.Types.PlutusScript (hash) as PlutusScript +import Cardano.Types.RedeemerDatum (unit) as RedeemerDatum +import Cardano.Types.Transaction (hash) as Transaction +import Contract.Config + ( ContractParams + , KnownWallet(Eternl) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) +import Contract.Log (logInfo') +import Contract.Monad (Contract, launchAff_, runContract) +import Contract.ProtocolParameters (getProtocolParameters) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) +import Control.Monad.Error.Class (catchError, throwError) +import Ctl.Examples.Gov.Internal.Common (dummyAnchor) +import Ctl.Examples.PlutusV3.Scripts.AlwaysMints (alwaysMintsPolicyScriptV3) +import Data.Map (empty) as Map +import Data.String (Pattern(Pattern)) +import Data.String (contains) as String +import Effect.Exception (message) + +main :: Effect Unit +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Eternl) { cip95: true } + } + +example :: ContractParams -> Effect Unit +example = launchAff_ <<< flip runContract contract + +contract :: Contract Unit +contract = do + logInfo' "Running Examples.Gov.ManageDrepScript" + drepScriptHash <- contractStep RegDrep + logInfo' $ "Successfully registered DRep. DRepID: " <> show drepScriptHash + void $ contractStep $ UpdateDrep dummyAnchor + logInfo' "Successfully updated DRep metadata." + void $ contractStep UnregDrep + logInfo' "Successfully unregistered DRep." + +data ContractPath + = RegDrep + | UpdateDrep Anchor + | UnregDrep + +contractStep :: ContractPath -> Contract ScriptHash +contractStep path = do + drepScript <- alwaysMintsPolicyScriptV3 + let + drepScriptHash = PlutusScript.hash drepScript + drepCred = ScriptHashCredential drepScriptHash + drepCredWitness = PlutusScriptCredential (ScriptValue drepScript) + RedeemerDatum.unit + + drepDeposit <- _.drepDeposit <<< unwrap <$> getProtocolParameters + + let + submitTx = do + tx <- submitTxFromBuildPlan Map.empty mempty + [ case path of + RegDrep -> + IssueCertificate (RegDrepCert drepCred drepDeposit Nothing) + (Just drepCredWitness) + UpdateDrep anchor -> + IssueCertificate (UpdateDrepCert drepCred $ Just anchor) + (Just drepCredWitness) + UnregDrep -> + IssueCertificate (UnregDrepCert drepCred drepDeposit) + (Just drepCredWitness) + ] + awaitTxConfirmed $ Transaction.hash tx + + submitTx `catchError` \err -> + unless + (String.contains (Pattern "knownDelegateRepresentative") $ message err) + (throwError err) + + pure drepScriptHash diff --git a/examples/Gov/SubmitVote.purs b/examples/Gov/SubmitVote.purs new file mode 100644 index 0000000000..1590a04c8b --- /dev/null +++ b/examples/Gov/SubmitVote.purs @@ -0,0 +1,99 @@ +module Ctl.Examples.Gov.SubmitVote + ( contract + , example + , main + ) where + +import Contract.Prelude + +import Cardano.Transaction.Builder + ( TransactionBuilderStep(SubmitProposal, SubmitVotingProcedure) + ) +import Cardano.Types + ( Credential(PubKeyHashCredential) + , GovernanceActionId + , Vote(VoteYes) + , Voter(Drep) + , VotingProcedure(VotingProcedure) + , VotingProposal(VotingProposal) + ) +import Cardano.Types (GovernanceAction(Info)) as GovAction +import Cardano.Types.Transaction (hash) as Transaction +import Contract.Config + ( ContractParams + , KnownWallet(Eternl) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) +import Contract.Log (logInfo') +import Contract.Monad (Contract, launchAff_, liftedM, runContract) +import Contract.ProtocolParameters (getProtocolParameters) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) +import Contract.Wallet (getRewardAddresses, ownDrepPubKeyHash) +import Ctl.Examples.Gov.Internal.Common (asRewardAddress, dummyAnchor) +import Ctl.Examples.Gov.ManageDrep (ContractPath(RegDrep), contractStep) as ManageDrep +import Data.Array (head) as Array +import Data.Map (empty, singleton) as Map + +main :: Effect Unit +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Eternl) { cip95: true } + } + +example :: ContractParams -> Effect Unit +example = launchAff_ <<< flip runContract contract + +contract :: Contract Unit +contract = do + logInfo' "Running Examples.Gov.SubmitVote" + void $ ManageDrep.contractStep ManageDrep.RegDrep + govActionId <- submitProposal + logInfo' $ "Successfully submitted voting proposal. Action id: " <> show + govActionId + submitVote govActionId + logInfo' "Successfully voted on the proposal." + +{- + { transactionId: unsafePartial fromJust $ decodeCbor $ wrap $ + hexToByteArrayUnsafe + "fec3c9c4c8bf9b02237bbdccca9460eee1e5b67a5052fdbd5eb1d7ec1719d9f0" + , index: zero + } +-} + +submitProposal :: Contract GovernanceActionId +submitProposal = do + govActionDeposit <- _.govActionDeposit <<< unwrap <$> getProtocolParameters + rewardAddr <- liftedM "Could not get reward address" $ + map (asRewardAddress <=< Array.head) + getRewardAddresses + + tx <- submitTxFromBuildPlan Map.empty mempty + [ SubmitProposal + ( VotingProposal + { govAction: GovAction.Info + , anchor: dummyAnchor + , deposit: unwrap govActionDeposit + , returnAddr: rewardAddr + } + ) + Nothing + ] + let txHash = Transaction.hash tx + awaitTxConfirmed txHash + pure $ wrap { transactionId: txHash, index: zero } + +submitVote :: GovernanceActionId -> Contract Unit +submitVote govActionId = do + drepCred <- PubKeyHashCredential <$> ownDrepPubKeyHash + + tx <- submitTxFromBuildPlan Map.empty mempty + [ SubmitVotingProcedure (Drep drepCred) + ( Map.singleton govActionId $ + VotingProcedure { vote: VoteYes, anchor: Nothing } + ) + Nothing + ] + awaitTxConfirmed $ Transaction.hash tx diff --git a/examples/Gov/SubmitVoteScript.purs b/examples/Gov/SubmitVoteScript.purs new file mode 100644 index 0000000000..55e43e6d3e --- /dev/null +++ b/examples/Gov/SubmitVoteScript.purs @@ -0,0 +1,108 @@ +module Ctl.Examples.Gov.SubmitVoteScript + ( contract + , example + , main + ) where + +import Contract.Prelude + +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SubmitProposal, SubmitVotingProcedure) + ) +import Cardano.Types + ( Credential(ScriptHashCredential) + , GovernanceActionId + , Vote(VoteYes) + , Voter(Drep) + , VotingProcedure(VotingProcedure) + , VotingProposal(VotingProposal) + ) +import Cardano.Types (GovernanceAction(Info)) as GovAction +import Cardano.Types.PlutusScript (hash) as PlutusScript +import Cardano.Types.RedeemerDatum (unit) as RedeemerDatum +import Cardano.Types.Transaction (hash) as Transaction +import Contract.Config + ( ContractParams + , KnownWallet(Eternl) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) +import Contract.Log (logInfo') +import Contract.Monad (Contract, launchAff_, liftedM, runContract) +import Contract.ProtocolParameters (getProtocolParameters) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) +import Contract.Wallet (getRewardAddresses) +import Ctl.Examples.Gov.Internal.Common (asRewardAddress, dummyAnchor) +import Ctl.Examples.Gov.ManageDrepScript (ContractPath(RegDrep), contractStep) as ManageDrep +import Ctl.Examples.PlutusV3.Scripts.AlwaysMints (alwaysMintsPolicyScriptV3) +import Data.Array (head) as Array +import Data.Map (empty, singleton) as Map + +main :: Effect Unit +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Eternl) { cip95: true } + } + +example :: ContractParams -> Effect Unit +example = launchAff_ <<< flip runContract contract + +contract :: Contract Unit +contract = do + logInfo' "Running Examples.Gov.SubmitVoteScript" + void $ ManageDrep.contractStep ManageDrep.RegDrep + govActionId <- submitProposal + logInfo' $ "Successfully submitted voting proposal. Action id: " <> show + govActionId + submitVote govActionId + logInfo' "Successfully voted on the proposal." + +{- + { transactionId: unsafePartial fromJust $ decodeCbor $ wrap $ + hexToByteArrayUnsafe + "78e7fa2f5ad34506208cbde6ced3c690df4f244000ba33b445da8d3791577ede" + , index: zero + } +-} + +submitProposal :: Contract GovernanceActionId +submitProposal = do + govActionDeposit <- _.govActionDeposit <<< unwrap <$> getProtocolParameters + rewardAddr <- liftedM "Could not get reward address" $ + map (asRewardAddress <=< Array.head) + getRewardAddresses + + tx <- submitTxFromBuildPlan Map.empty mempty + [ SubmitProposal + ( VotingProposal + { govAction: GovAction.Info + , anchor: dummyAnchor + , deposit: unwrap govActionDeposit + , returnAddr: rewardAddr + } + ) + Nothing + ] + let txHash = Transaction.hash tx + awaitTxConfirmed txHash + pure $ wrap { transactionId: txHash, index: zero } + +submitVote :: GovernanceActionId -> Contract Unit +submitVote govActionId = do + drepScript <- alwaysMintsPolicyScriptV3 + let + drepCred = ScriptHashCredential $ PlutusScript.hash drepScript + drepCredWitness = PlutusScriptCredential (ScriptValue drepScript) + RedeemerDatum.unit + + tx <- submitTxFromBuildPlan Map.empty mempty + [ SubmitVotingProcedure (Drep drepCred) + ( Map.singleton govActionId $ + VotingProcedure { vote: VoteYes, anchor: Nothing } + ) + (Just drepCredWitness) + ] + awaitTxConfirmed $ Transaction.hash tx diff --git a/examples/Helpers.purs b/examples/Helpers.purs index 9f5dbb6441..cb43614fd7 100644 --- a/examples/Helpers.purs +++ b/examples/Helpers.purs @@ -1,6 +1,5 @@ module Ctl.Examples.Helpers - ( mkCurrencySymbol - , mkTokenName + ( mkAssetName , mustPayToPubKeyStakeAddress , mustPayToPubKeyStakeAddressWithDatum , mustPayToPubKeyStakeAddressWithScriptRef @@ -9,39 +8,31 @@ module Ctl.Examples.Helpers import Contract.Prelude -import Contract.Address (PaymentPubKeyHash, StakePubKeyHash) +import Cardano.Types + ( AssetName + , PaymentPubKeyHash + , PlutusData + , ScriptRef + , StakePubKeyHash + , Transaction + , Value + ) +import Cardano.Types.AssetName as AssetName import Contract.Log (logInfo') import Contract.Monad (Contract, liftContractM) -import Contract.PlutusData (Datum) import Contract.Prim.ByteArray (byteArrayFromAscii) -import Contract.Scripts (MintingPolicy) -import Contract.Transaction - ( BalancedSignedTransaction - , ScriptRef - , awaitTxConfirmed - , submit - ) +import Contract.Transaction (awaitTxConfirmed, submit) import Contract.TxConstraints (DatumPresence) import Contract.TxConstraints as Constraints -import Contract.Value (CurrencySymbol, TokenName, Value) -import Contract.Value (mkTokenName, scriptCurrencySymbol) as Value - -mkCurrencySymbol - :: Contract MintingPolicy - -> Contract (MintingPolicy /\ CurrencySymbol) -mkCurrencySymbol mintingPolicy = do - mp <- mintingPolicy - let cs = Value.scriptCurrencySymbol mp - pure (mp /\ cs) -mkTokenName :: String -> Contract TokenName -mkTokenName = - liftContractM "Cannot make token name" - <<< (Value.mkTokenName <=< byteArrayFromAscii) +mkAssetName :: String -> Contract AssetName +mkAssetName str = + liftContractM ("Cannot make token name from: " <> str) + $ AssetName.mkAssetName + =<< byteArrayFromAscii str mustPayToPubKeyStakeAddress - :: forall (i :: Type) (o :: Type) - . PaymentPubKeyHash + :: PaymentPubKeyHash -> Maybe StakePubKeyHash -> Value -> Constraints.TxConstraints @@ -51,10 +42,9 @@ mustPayToPubKeyStakeAddress pkh (Just skh) = Constraints.mustPayToPubKeyAddress pkh skh mustPayToPubKeyStakeAddressWithDatum - :: forall (i :: Type) (o :: Type) - . PaymentPubKeyHash + :: PaymentPubKeyHash -> Maybe StakePubKeyHash - -> Datum + -> PlutusData -> DatumPresence -> Value -> Constraints.TxConstraints @@ -64,8 +54,7 @@ mustPayToPubKeyStakeAddressWithDatum pkh (Just skh) datum dtp = Constraints.mustPayToPubKeyAddressWithDatum pkh skh datum dtp mustPayToPubKeyStakeAddressWithScriptRef - :: forall (i :: Type) (o :: Type) - . PaymentPubKeyHash + :: PaymentPubKeyHash -> Maybe StakePubKeyHash -> ScriptRef -> Value @@ -75,8 +64,7 @@ mustPayToPubKeyStakeAddressWithScriptRef pkh Nothing scriptRef = mustPayToPubKeyStakeAddressWithScriptRef pkh (Just skh) scriptRef = Constraints.mustPayToPubKeyAddressWithScriptRef pkh skh scriptRef -submitAndLog - :: BalancedSignedTransaction -> Contract Unit +submitAndLog :: Transaction -> Contract Unit submitAndLog bsTx = do txId <- submit bsTx logInfo' $ "Tx ID: " <> show txId diff --git a/examples/IncludeDatum.purs b/examples/IncludeDatum.purs index 5a21a40944..7074c37d1e 100644 --- a/examples/IncludeDatum.purs +++ b/examples/IncludeDatum.purs @@ -3,7 +3,8 @@ -- | and then spends the script Utxo. The script only checks -- | that the value of the datum is equal to 42. module Ctl.Examples.IncludeDatum - ( example + ( contract + , example , only42Script , main , payToIncludeDatum @@ -12,64 +13,83 @@ module Ctl.Examples.IncludeDatum import Contract.Prelude -import Contract.Address (scriptHashAddress) -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Transaction.Builder + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) +import Cardano.Types + ( Credential(ScriptHashCredential) + , OutputDatum(OutputDatumHash) + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) +import Contract.Address (mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftContractM, runContract) -import Contract.PlutusData (Datum(Datum), PlutusData(Integer), unitRedeemer) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (Validator(Validator), ValidatorHash, validatorHash) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV1FromEnvelope) +import Contract.PlutusData (PlutusData(Integer)) +import Contract.Scripts (Validator, ValidatorHash, validatorHash) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash - , _input , awaitTxConfirmed , lookupTxHash - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value import Control.Monad.Error.Class (liftMaybe) import Data.Array (head) -import Data.Lens (view) +import Data.Map as Map import Effect.Exception (error) import JS.BigInt as BigInt main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit -example cfg = launchAff_ do - runContract cfg do - logInfo' "Running Examples.IncludeDatum" - validator <- only42Script - let vhash = validatorHash validator - logInfo' "Attempt to lock value" - txId <- payToIncludeDatum vhash - awaitTxConfirmed txId - logInfo' "Tx submitted successfully, Try to spend locked values" - spendFromIncludeDatum vhash validator txId +example = launchAff_ <<< flip runContract contract -datum :: Datum -datum = Datum $ Integer $ BigInt.fromInt 42 +contract :: Contract Unit +contract = do + logInfo' "Running Examples.IncludeDatum" + validator <- only42Script + let vhash = validatorHash validator + logInfo' "Attempt to lock value" + txId <- payToIncludeDatum vhash + awaitTxConfirmed txId + logInfo' "Tx submitted successfully, Try to spend locked values" + spendFromIncludeDatum vhash validator txId -payToIncludeDatum :: ValidatorHash -> Contract TransactionHash -payToIncludeDatum vhash = - let - constraints :: TxConstraints - constraints = - ( Constraints.mustPayToScript vhash datum Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - ) - <> Constraints.mustIncludeDatum datum +datum :: PlutusData +datum = Integer $ BigInt.fromInt 42 - lookups :: Lookups.ScriptLookups - lookups = mempty - in - submitTxFromConstraints lookups constraints +payToIncludeDatum :: ValidatorHash -> Contract TransactionHash +payToIncludeDatum vhash = do + address <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData datum + , scriptRef: Nothing + } + ] spendFromIncludeDatum :: ValidatorHash @@ -77,21 +97,20 @@ spendFromIncludeDatum -> TransactionHash -> Contract Unit spendFromIncludeDatum vhash validator txId = do - let scriptAddress = scriptHashAddress vhash Nothing + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing utxos <- utxosAt scriptAddress - txInput <- liftContractM "no locked output at address" - (view _input <$> head (lookupTxHash txId utxos)) - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - <> Constraints.mustIncludeDatum datum - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId + utxo <- liftContractM "no locked output at address" + (head (lookupTxHash txId utxos)) + spendTx <- submitTxFromBuildPlan (toUtxoMap [ utxo ]) + mempty + [ SpendOutput + utxo + ( Just $ PlutusScriptOutput (ScriptValue validator) RedeemerDatum.unit + $ Just + $ DatumValue datum + ) + ] + awaitTxConfirmed $ Transaction.hash spendTx logInfo' "Successfully spent locked values." -- | checks if the datum equals 42 @@ -99,7 +118,7 @@ only42Script :: Contract Validator only42Script = do liftMaybe (error "Error decoding includeDatum") do envelope <- decodeTextEnvelope includeDatum - Validator <$> plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope includeDatum :: String includeDatum = diff --git a/examples/KeyWallet/DelegateVoteAbstain.purs b/examples/KeyWallet/DelegateVoteAbstain.purs new file mode 100644 index 0000000000..cbc334d7c4 --- /dev/null +++ b/examples/KeyWallet/DelegateVoteAbstain.purs @@ -0,0 +1,13 @@ +module Ctl.Examples.KeyWallet.DelegateVoteAbstain + ( main + ) where + +import Contract.Prelude + +import Ctl.Examples.Gov.DelegateVoteAbstain (contract) as Gov.DelegateVoteAbstain +import Ctl.Examples.KeyWallet.Internal.Contract (runKeyWalletContract) + +main :: Effect Unit +main = + runKeyWalletContract \unlock -> + Gov.DelegateVoteAbstain.contract *> liftEffect unlock diff --git a/examples/KeyWallet/Internal/Cip30Contract.purs b/examples/KeyWallet/Internal/Cip30Contract.purs index b6dfdba97c..e10bb7d153 100644 --- a/examples/KeyWallet/Internal/Cip30Contract.purs +++ b/examples/KeyWallet/Internal/Cip30Contract.purs @@ -4,6 +4,8 @@ module Ctl.Examples.KeyWallet.Internal.Cip30Contract import Contract.Prelude +import Cardano.Types (RawBytes) +import Cardano.Types.PrivateKey as PrivateKey import Contract.Config ( PrivatePaymentKeySource(PrivatePaymentKeyValue) , WalletSpec(UseKeys) @@ -18,8 +20,7 @@ import Ctl.Examples.KeyWallet.Internal.Cip30HtmlForm , logError , mkForm ) as HtmlForm -import Ctl.Internal.Deserialization.Keys (privateKeyFromBytes) -import Ctl.Internal.Types.RawBytes (RawBytes, hexToRawBytes, rawBytesFromAscii) +import Data.ByteArray (hexToByteArray) import Data.Log.Formatter.Pretty (prettyFormatter) import Data.Log.Level (LogLevel) import Data.Log.Message (Message) @@ -32,15 +33,17 @@ runKeyWalletContract_ contract = HtmlForm.mkForm \input log' unlock -> launchAff_ $ flip catchError (errorHandler log' unlock) $ do privateKey <- liftMaybe (error "Failed to parse private key") - $ privateKeyFromBytes - =<< hexToRawBytes input.privateKey - message <- liftMaybe (error "Failed to encode message") $ - rawBytesFromAscii input.message + $ PrivateKey.fromRawBytes + =<< map wrap (hexToByteArray input.privateKey) + message <- liftMaybe (error "Failed to encode message") + $ map wrap + $ hexToByteArray input.message let cfg = testnetConfig { walletSpec = Just $ UseKeys (PrivatePaymentKeyValue $ wrap privateKey) Nothing + Nothing , customLogger = Just printLog } diff --git a/examples/KeyWallet/Internal/Contract.purs b/examples/KeyWallet/Internal/Contract.purs new file mode 100644 index 0000000000..04089b63db --- /dev/null +++ b/examples/KeyWallet/Internal/Contract.purs @@ -0,0 +1,60 @@ +module Ctl.Examples.KeyWallet.Internal.Contract + ( runKeyWalletContract + ) where + +import Contract.Prelude + +import Contract.Config + ( MnemonicSource(MnemonicString) + , StakeKeyPresence(WithStakeKey) + , WalletSpec(UseMnemonic) + , testnetConfig + ) +import Contract.Monad (Contract, launchAff_, runContract) +import Control.Monad.Error.Class (class MonadError, catchError) +import Ctl.Examples.KeyWallet.Internal.HtmlForm (Log, Unlock) +import Ctl.Examples.KeyWallet.Internal.HtmlForm + ( levelColor + , levelName + , logError + , mkForm + ) as HtmlForm +import Data.Log.Formatter.Pretty (prettyFormatter) +import Data.Log.Level (LogLevel) +import Data.Log.Message (Message) +import Effect.Class (class MonadEffect) +import Effect.Exception (Error, message) + +runKeyWalletContract :: (Unlock -> Contract Unit) -> Effect Unit +runKeyWalletContract contract = + HtmlForm.mkForm \input log' unlock -> + launchAff_ $ flip catchError (errorHandler log' unlock) $ do + let + cfg = testnetConfig + { walletSpec = Just $ UseMnemonic + (MnemonicString input.walletSeed) + { accountIndex: zero, addressIndex: zero } + WithStakeKey + , customLogger = Just printLog + } + + printLog :: LogLevel -> Message -> Aff Unit + printLog lgl m = liftEffect $ when (m.level >= lgl) $ do + prettyFormatter m >>= log + log' (HtmlForm.levelColor m.level) + ("[" <> HtmlForm.levelName m.level <> "] " <> m.message) + runContract cfg (contract unlock) + where + + errorHandler + :: forall (m :: Type -> Type) + . MonadError Error m + => MonadEffect m + => Log + -> Unlock + -> Error + -> m Unit + errorHandler log' unlock e = + liftEffect $ HtmlForm.logError e + *> log' "crimson" ("[ERROR] " <> message e) + *> unlock diff --git a/examples/KeyWallet/Internal/HtmlForm.js b/examples/KeyWallet/Internal/HtmlForm.js new file mode 100644 index 0000000000..56ef83eda4 --- /dev/null +++ b/examples/KeyWallet/Internal/HtmlForm.js @@ -0,0 +1,74 @@ +"use strict"; + +const form = ` + +
+
+ + +
+ +
+
+
+ +`; + +export function logError(error) { + return () => { + console.log(error); + }; +} + +export function mkForm(handler) { + return () => { + window.document.body.insertAdjacentHTML("beforeend", form); + const formEl = window.document.querySelector("form"); + const fieldsEl = window.document.querySelector("fieldset"); + const resultEl = window.document.querySelector("code"); + formEl.addEventListener("submit", event => { + event.preventDefault(); + resultEl.replaceChildren(); + + const data = new FormData(formEl); + const input = Object.fromEntries(data); + fieldsEl.setAttribute("disabled", "disabled"); + + const log = color => text => () => { + const line = document.createElement("div"); + line.style.color = color; + line.textContent = text; + resultEl.append(line); + }; + + const unlock = () => { + fieldsEl.setAttribute("disabled", "disabled"); + fieldsEl.removeAttribute("disabled"); + }; + + handler(input)(log)(unlock)(); + }); + }; +} diff --git a/examples/KeyWallet/Internal/HtmlForm.purs b/examples/KeyWallet/Internal/HtmlForm.purs new file mode 100644 index 0000000000..03f2130056 --- /dev/null +++ b/examples/KeyWallet/Internal/HtmlForm.purs @@ -0,0 +1,38 @@ +module Ctl.Examples.KeyWallet.Internal.HtmlForm + ( Form + , Log + , Unlock + , levelColor + , levelName + , logError + , mkForm + ) where + +import Contract.Prelude + +import Data.Log.Level (LogLevel(Trace, Debug, Warn, Info, Error)) +import Effect.Exception (Error) + +type Form = + { walletSeed :: String + } + +type Log = String -> String -> Effect Unit + +type Unlock = Effect Unit + +foreign import mkForm :: (Form -> Log -> Unlock -> Effect Unit) -> Effect Unit + +foreign import logError :: Error -> Effect Unit + +levelName :: LogLevel -> String +levelName Trace = "TRACE" +levelName Debug = "DEBUG" +levelName Info = "INFO" +levelName Warn = "WARN" +levelName Error = "ERROR" + +levelColor :: LogLevel -> String +levelColor Warn = "gold" +levelColor Error = "crimson" +levelColor _ = "black" diff --git a/examples/KeyWallet/Internal/Pkh2PkhContract.purs b/examples/KeyWallet/Internal/Pkh2PkhContract.purs index 53bb3d9b33..390258c929 100644 --- a/examples/KeyWallet/Internal/Pkh2PkhContract.purs +++ b/examples/KeyWallet/Internal/Pkh2PkhContract.purs @@ -4,12 +4,16 @@ module Ctl.Examples.KeyWallet.Internal.Pkh2PkhContract import Contract.Prelude +import Cardano.Types.BigNum (BigNum) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Ed25519KeyHash as Ed25519KeyHash import Contract.Address (PaymentPubKeyHash) import Contract.Config ( PrivatePaymentKeySource(PrivatePaymentKeyValue) , WalletSpec(UseKeys) , testnetConfig ) +import Contract.Keys (privateKeyFromBytes) import Contract.Monad (Contract, launchAff_, runContract) import Control.Monad.Error.Class (class MonadError, catchError, liftMaybe) import Ctl.Examples.KeyWallet.Internal.Pkh2PkhHtmlForm (Log, Unlock) @@ -19,35 +23,32 @@ import Ctl.Examples.KeyWallet.Internal.Pkh2PkhHtmlForm , logError , mkForm ) as HtmlForm -import Ctl.Internal.Deserialization.Keys (privateKeyFromBytes) -import Ctl.Internal.Serialization.Hash (ed25519KeyHashFromBech32) -import Ctl.Internal.Types.RawBytes (hexToRawBytes) +import Data.ByteArray (hexToByteArray) import Data.Log.Formatter.Pretty (prettyFormatter) import Data.Log.Level (LogLevel) import Data.Log.Message (Message) import Effect.Class (class MonadEffect) import Effect.Exception (Error, error, message) -import JS.BigInt (BigInt) -import JS.BigInt (fromString) as BigInt runKeyWalletContract_ - :: (PaymentPubKeyHash -> BigInt -> Unlock -> Contract Unit) -> Effect Unit + :: (PaymentPubKeyHash -> BigNum -> Unlock -> Contract Unit) -> Effect Unit runKeyWalletContract_ contract = HtmlForm.mkForm \input log' unlock -> launchAff_ $ flip catchError (errorHandler log' unlock) $ do privateKey <- liftMaybe (error "Failed to parse private key") $ privateKeyFromBytes - =<< hexToRawBytes input.privateKey + =<< map wrap (hexToByteArray input.privateKey) pkh <- liftMaybe (error "Failed to parse public key hash") - $ map (wrap <<< wrap) - $ ed25519KeyHashFromBech32 input.toPkh + $ map wrap + $ Ed25519KeyHash.fromBech32 input.toPkh lovelace <- liftMaybe (error "Failed to parse lovelace amount") $ - BigInt.fromString input.lovelace + BigNum.fromString input.lovelace let cfg = testnetConfig { walletSpec = Just $ UseKeys (PrivatePaymentKeyValue $ wrap privateKey) Nothing + Nothing , customLogger = Just printLog } diff --git a/examples/KeyWallet/ManageDrep.purs b/examples/KeyWallet/ManageDrep.purs new file mode 100644 index 0000000000..e3ab23731b --- /dev/null +++ b/examples/KeyWallet/ManageDrep.purs @@ -0,0 +1,13 @@ +module Ctl.Examples.KeyWallet.ManageDrep + ( main + ) where + +import Contract.Prelude + +import Ctl.Examples.Gov.ManageDrep (contract) as Gov.ManageDrep +import Ctl.Examples.KeyWallet.Internal.Contract (runKeyWalletContract) + +main :: Effect Unit +main = + runKeyWalletContract \unlock -> + Gov.ManageDrep.contract *> liftEffect unlock diff --git a/examples/KeyWallet/MintsAndSendsToken.purs b/examples/KeyWallet/MintsAndSendsToken.purs index c71a6ca6e8..d8fc5027a6 100644 --- a/examples/KeyWallet/MintsAndSendsToken.purs +++ b/examples/KeyWallet/MintsAndSendsToken.purs @@ -6,35 +6,41 @@ module Ctl.Examples.KeyWallet.MintsAndSendsToken (main) where import Contract.Prelude +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Int as Int +import Cardano.Types.Mint as Mint +import Cardano.Types.PlutusScript as PlutusScript import Contract.Log (logInfo') import Contract.ScriptLookups as Lookups import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) import Contract.TxConstraints as Constraints import Contract.Value as Value import Ctl.Examples.AlwaysMints (alwaysMintsPolicy) -import Ctl.Examples.Helpers - ( mkCurrencySymbol - , mkTokenName - ) as Helpers +import Ctl.Examples.Helpers (mkAssetName) as Helpers import Ctl.Examples.KeyWallet.Internal.Pkh2PkhContract (runKeyWalletContract_) +import Partial.Unsafe (unsafePartial) main :: Effect Unit main = runKeyWalletContract_ \pkh lovelace unlock -> do logInfo' "Running Examples.KeyWallet.MintsAndSendsToken" - mp /\ cs <- Helpers.mkCurrencySymbol alwaysMintsPolicy - tn <- Helpers.mkTokenName "TheToken" + mp <- alwaysMintsPolicy + let cs = PlutusScript.hash mp + tn <- Helpers.mkAssetName "TheToken" let constraints :: Constraints.TxConstraints constraints = mconcat - [ Constraints.mustMintValue (Value.singleton cs tn one) + [ Constraints.mustMintValue (Mint.singleton cs tn Int.one) , Constraints.mustPayToPubKey pkh - (Value.lovelaceValueOf lovelace <> Value.singleton cs tn one) + ( unsafePartial $ Value.lovelaceValueOf lovelace <> Value.singleton cs + tn + BigNum.one + ) ] lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp + lookups = Lookups.plutusMintingPolicy mp txId <- submitTxFromConstraints lookups constraints awaitTxConfirmed txId diff --git a/examples/KeyWallet/SignMultiple.purs b/examples/KeyWallet/SignMultiple.purs index fc998ca5a1..8d9c68db6d 100644 --- a/examples/KeyWallet/SignMultiple.purs +++ b/examples/KeyWallet/SignMultiple.purs @@ -2,12 +2,12 @@ module Ctl.Examples.KeyWallet.SignMultiple where import Contract.Prelude +import Cardano.Types (Transaction) import Contract.Log (logInfo') import Contract.Monad (Contract, throwContractError) import Contract.ScriptLookups as Lookups import Contract.Transaction - ( BalancedSignedTransaction - , TransactionHash + ( TransactionHash , awaitTxConfirmed , signTransaction , submit @@ -42,14 +42,24 @@ main = runKeyWalletContract_ \pkh lovelace unlock -> do lookups :: Lookups.ScriptLookups lookups = mempty - unbalancedTx0 <- mkUnbalancedTx lookups constraints - unbalancedTx1 <- mkUnbalancedTx lookups constraints + unbalancedTx0 /\ usedUtxos0 <- mkUnbalancedTx lookups constraints + unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups constraints - txIds <- withBalancedTxs [ unbalancedTx0, unbalancedTx1 ] $ \balancedTxs -> do - locked <- getLockedInputs - logInfo' $ "Locked inputs inside bracket (should be nonempty): " - <> show locked - traverse (submitAndLog <=< signTransaction) balancedTxs + txIds <- + withBalancedTxs + [ { transaction: unbalancedTx0 + , usedUtxos: usedUtxos0 + , balancerConstraints: mempty + } + , { transaction: unbalancedTx1 + , usedUtxos: usedUtxos1 + , balancerConstraints: mempty + } + ] $ \balancedTxs -> do + locked <- getLockedInputs + logInfo' $ "Locked inputs inside bracket (should be nonempty): " + <> show locked + traverse (submitAndLog <=< signTransaction) balancedTxs locked <- getLockedInputs logInfo' $ "Locked inputs after bracket (should be empty): " <> show locked @@ -65,7 +75,7 @@ main = runKeyWalletContract_ \pkh lovelace unlock -> do liftEffect unlock where submitAndLog - :: BalancedSignedTransaction + :: Transaction -> Contract TransactionHash submitAndLog bsTx = do txId <- submit bsTx diff --git a/examples/KeyWallet/SubmitVote.purs b/examples/KeyWallet/SubmitVote.purs new file mode 100644 index 0000000000..ee8822a6ea --- /dev/null +++ b/examples/KeyWallet/SubmitVote.purs @@ -0,0 +1,13 @@ +module Ctl.Examples.KeyWallet.SubmitVote + ( main + ) where + +import Contract.Prelude + +import Ctl.Examples.Gov.SubmitVote (contract) as Gov.SubmitVote +import Ctl.Examples.KeyWallet.Internal.Contract (runKeyWalletContract) + +main :: Effect Unit +main = + runKeyWalletContract \unlock -> + Gov.SubmitVote.contract *> liftEffect unlock diff --git a/examples/Lose7Ada.purs b/examples/Lose7Ada.purs index 43cbd25b9f..9d61939316 100644 --- a/examples/Lose7Ada.purs +++ b/examples/Lose7Ada.purs @@ -13,38 +13,63 @@ module Ctl.Examples.Lose7Ada import Contract.Prelude -import Contract.Address (scriptHashAddress) -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Transaction.Builder + ( OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) +import Cardano.Types + ( Credential(ScriptHashCredential) + , OutputDatum(OutputDatum) + , PaymentCredential(PaymentCredential) + , TransactionOutput(TransactionOutput) + , _isValid + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) +import Contract.Address (mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData (unitDatum, unitRedeemer) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (Validator(Validator), ValidatorHash, validatorHash) -import Contract.TextEnvelope - ( decodeTextEnvelope - , plutusScriptV1FromEnvelope - ) +import Contract.Scripts (Validator, ValidatorHash, validatorHash) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash - , TransactionInput(TransactionInput) , awaitTxConfirmed - , submitTxFromConstraints + , balanceTx + , buildTx + , lookupTxHash + , signTransaction + , submit + , submitTxFromBuildPlan ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) -import Contract.Value as Value +import Contract.Value (lovelaceValueOf, minus) as Value import Contract.Wallet (getWalletBalance) import Control.Monad.Error.Class (liftMaybe) +import Data.Array (head) import Data.Foldable (fold) import Data.Functor ((<$>)) +import Data.Lens ((.~)) import Data.Map as Map import Effect.Exception (error) -import JS.BigInt as BigInt +import Partial.Unsafe (unsafePartial) import Test.Spec.Assertions (shouldEqual) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -60,18 +85,16 @@ example cfg = launchAff_ do payToAlwaysFails :: ValidatorHash -> Contract TransactionHash payToAlwaysFails vhash = do - let - constraints :: TxConstraints - constraints = - Constraints.mustPayToScript vhash unitDatum - Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + scriptAddress <- + mkAddress (PaymentCredential $ ScriptHashCredential vhash) Nothing + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Nothing + } + ] spendFromAlwaysFails :: ValidatorHash @@ -79,47 +102,42 @@ spendFromAlwaysFails -> TransactionHash -> Contract Unit spendFromAlwaysFails vhash validator txId = do - balanceBefore <- fold <$> getWalletBalance - let scriptAddress = scriptHashAddress vhash Nothing + balanceBefore <- unsafePartial $ fold <$> getWalletBalance + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing utxos <- utxosAt scriptAddress - txInput <- liftM - ( error - ( "The id " - <> show txId - <> " does not have output locked at: " - <> show scriptAddress - ) - ) - (fst <$> find hasTransactionId (Map.toUnfoldable utxos :: Array _)) - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - <> Constraints.mustNotBeValid - - spendTxId <- submitTxFromConstraints lookups constraints + utxo <- + liftM + ( error + ( "The id " + <> show txId + <> " does not have output locked at: " + <> show scriptAddress + ) + ) + $ head (lookupTxHash txId utxos) + unbalancedTx <- + buildTx + [ SpendOutput + utxo + $ Just + $ PlutusScriptOutput (ScriptValue validator) RedeemerDatum.unit + Nothing + ] <#> _isValid .~ false + spendTx <- balanceTx unbalancedTx (toUtxoMap [ utxo ]) mempty + signedTx <- signTransaction (spendTx # _isValid .~ true) + spendTxId <- submit signedTx logInfo' $ "Tx ID: " <> show spendTxId awaitTxConfirmed spendTxId logInfo' "Successfully spent locked values." - - balance <- fold <$> getWalletBalance - let collateralLoss = Value.lovelaceValueOf $ BigInt.fromInt (-5_000_000) - balance `shouldEqual` (balanceBefore <> collateralLoss) - - where - hasTransactionId :: TransactionInput /\ _ -> Boolean - hasTransactionId (TransactionInput tx /\ _) = - tx.transactionId == txId + balance <- unsafePartial $ fold <$> getWalletBalance + let collateralLoss = Value.lovelaceValueOf $ BigNum.fromInt (5_000_000) + Just balance `shouldEqual` (Value.minus balanceBefore collateralLoss) alwaysFailsScript :: Contract Validator alwaysFailsScript = do liftMaybe (error "Error decoding alwaysFails") do envelope <- decodeTextEnvelope alwaysFails - Validator <$> plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope alwaysFails :: String alwaysFails = diff --git a/examples/ManyAssets.purs b/examples/ManyAssets.purs index 70a6bccf45..b640702ae4 100644 --- a/examples/ManyAssets.purs +++ b/examples/ManyAssets.purs @@ -8,27 +8,35 @@ module Ctl.Examples.ManyAssets import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Log (logInfo') -import Contract.Monad - ( Contract - , launchAff_ - , liftContractM - , liftedM - , runContract +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(MintAsset) + ) +import Cardano.Types.Int as Int +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName ) -import Contract.ScriptLookups as Lookups -import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) -import Contract.TxConstraints as Constraints -import Contract.Value (singleton) as Value -import Contract.Wallet (getWalletUtxos) -import Ctl.Examples.Helpers (mkCurrencySymbol, mkTokenName) as Helpers -import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyV2) -import Data.Array (head, range) as Array -import Data.Map (toUnfoldable) as Map +import Contract.Log (logInfo') +import Contract.Monad (Contract, launchAff_, runContract) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) +import Ctl.Examples.Helpers (mkAssetName) as Helpers +import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) +import Data.Array (range) as Array +import Data.Map as Map main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -43,26 +51,16 @@ mkContractWithAssertions -> Contract Unit mkContractWithAssertions exampleName = do logInfo' ("Running " <> exampleName) - utxos <- liftedM "Failed to get UTxOs from wallet" getWalletUtxos - oref <- - liftContractM "Utxo set is empty" - (fst <$> Array.head (Map.toUnfoldable utxos :: Array _)) - - mp /\ cs <- Helpers.mkCurrencySymbol (alwaysMintsPolicyV2) - tns <- for (Array.range 0 600) \i -> Helpers.mkTokenName $ "CTLNFT" <> show i + mp <- alwaysMintsPolicyScriptV2 + let cs = PlutusScript.hash mp + tns <- for (Array.range 0 600) \i -> Helpers.mkAssetName $ "CTLNFT" <> show i let - constraints :: Constraints.TxConstraints - constraints = - fold - (tns <#> \tn -> Constraints.mustMintValue (Value.singleton cs tn one)) - <> Constraints.mustSpendPubKeyOutput oref - - lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp - <> Lookups.unspentOutputs utxos + plan = + tns <#> \tn -> MintAsset cs tn (Int.fromInt one) + (PlutusScriptCredential (ScriptValue mp) RedeemerDatum.unit) - txHash <- submitTxFromConstraints lookups constraints + txHash <- Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty plan logInfo' $ "Tx ID: " <> show txHash awaitTxConfirmed txHash logInfo' "Tx submitted successfully!" diff --git a/examples/MintsMultipleTokens.purs b/examples/MintsMultipleTokens.purs index eb731b40d8..c3b8d414f9 100644 --- a/examples/MintsMultipleTokens.purs +++ b/examples/MintsMultipleTokens.purs @@ -12,62 +12,70 @@ module Ctl.Examples.MintsMultipleTokens import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(MintAsset) + ) +import Cardano.Types.Int as Int +import Cardano.Types.PlutusScript (PlutusScript) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.Transaction as Transaction +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData (PlutusData(Integer), Redeemer(Redeemer)) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (MintingPolicy(PlutusMintingPolicy)) -import Contract.TextEnvelope - ( decodeTextEnvelope - , plutusScriptV1FromEnvelope - ) -import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) -import Contract.TxConstraints as Constraints -import Contract.Value as Value +import Contract.PlutusData (PlutusData(Integer), RedeemerDatum(RedeemerDatum)) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) import Control.Monad.Error.Class (liftMaybe) -import Ctl.Examples.Helpers - ( mkCurrencySymbol - , mkTokenName - ) as Helpers +import Ctl.Examples.Helpers (mkAssetName) as Helpers +import Data.Map as Map import Effect.Exception (error) import JS.BigInt (fromInt) as BigInt main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } contract :: Contract Unit contract = do logInfo' "Running Examples.MintsMultipleTokens" - tn1 <- Helpers.mkTokenName "Token with a long name" - tn2 <- Helpers.mkTokenName "Token" - mp1 /\ cs1 <- Helpers.mkCurrencySymbol mintingPolicyRdmrInt1 - mp2 /\ cs2 <- Helpers.mkCurrencySymbol mintingPolicyRdmrInt2 - mp3 /\ cs3 <- Helpers.mkCurrencySymbol mintingPolicyRdmrInt3 + tn1 <- Helpers.mkAssetName "Token with a long name" + tn2 <- Helpers.mkAssetName "Token" + mp1 <- mintingPolicyRdmrInt1 + mp2 <- mintingPolicyRdmrInt2 + mp3 <- mintingPolicyRdmrInt3 + let + cs1 = PlutusScript.hash mp1 + cs2 = PlutusScript.hash mp2 + cs3 = PlutusScript.hash mp3 let - constraints :: Constraints.TxConstraints - constraints = mconcat - [ Constraints.mustMintValueWithRedeemer - (Redeemer $ Integer (BigInt.fromInt 1)) - (Value.singleton cs1 tn1 one <> Value.singleton cs1 tn2 one) - , Constraints.mustMintValueWithRedeemer - (Redeemer $ Integer (BigInt.fromInt 2)) - (Value.singleton cs2 tn1 one <> Value.singleton cs2 tn2 one) - , Constraints.mustMintValueWithRedeemer - (Redeemer $ Integer (BigInt.fromInt 3)) - (Value.singleton cs3 tn1 one <> Value.singleton cs3 tn2 one) + plan = + [ MintAsset cs1 tn1 Int.one + ( PlutusScriptCredential (ScriptValue mp1) $ RedeemerDatum $ Integer + (BigInt.fromInt 1) + ) + , MintAsset cs2 tn2 Int.one + ( PlutusScriptCredential (ScriptValue mp2) $ RedeemerDatum $ Integer + (BigInt.fromInt 2) + ) + , MintAsset cs3 tn2 Int.one + ( PlutusScriptCredential (ScriptValue mp3) $ RedeemerDatum $ Integer + (BigInt.fromInt 3) + ) ] - lookups :: Lookups.ScriptLookups - lookups = - Lookups.mintingPolicy mp1 - <> Lookups.mintingPolicy mp2 - <> Lookups.mintingPolicy mp3 - - txId <- submitTxFromConstraints lookups constraints - - awaitTxConfirmed txId + tx <- submitTxFromBuildPlan Map.empty mempty plan + awaitTxConfirmed $ Transaction.hash tx logInfo' $ "Tx submitted successfully!" example :: ContractParams -> Effect Unit @@ -78,20 +86,20 @@ foreign import redeemer1Script :: String foreign import redeemer2Script :: String foreign import redeemer3Script :: String -mintingPolicyRdmrInt1 :: Contract MintingPolicy +mintingPolicyRdmrInt1 :: Contract PlutusScript mintingPolicyRdmrInt1 = do liftMaybe (error "Error decoding redeemer1Script") do envelope <- decodeTextEnvelope redeemer1Script - PlutusMintingPolicy <$> plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope -mintingPolicyRdmrInt2 :: Contract MintingPolicy +mintingPolicyRdmrInt2 :: Contract PlutusScript mintingPolicyRdmrInt2 = do liftMaybe (error "Error decoding redeemer2Script") do envelope <- decodeTextEnvelope redeemer2Script - PlutusMintingPolicy <$> plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope -mintingPolicyRdmrInt3 :: Contract MintingPolicy +mintingPolicyRdmrInt3 :: Contract PlutusScript mintingPolicyRdmrInt3 = do liftMaybe (error "Error decoding redeemer3Script") do envelope <- decodeTextEnvelope redeemer3Script - PlutusMintingPolicy <$> plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope diff --git a/examples/MultipleRedeemers.purs b/examples/MultipleRedeemers.purs index f5bef4b0bc..2e7c6a4300 100644 --- a/examples/MultipleRedeemers.purs +++ b/examples/MultipleRedeemers.purs @@ -8,35 +8,29 @@ module Ctl.Examples.MultipleRedeemers import Contract.Prelude -import Contract.Address (scriptHashAddress) +import Cardano.Types (AssetName, Credential(ScriptHashCredential)) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Int as Int +import Cardano.Types.Mint as Mint +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.Value as Value +import Contract.Address (mkAddress) import Contract.Monad (Contract) import Contract.PlutusData ( PlutusData(Integer) - , Redeemer(Redeemer) + , RedeemerDatum(RedeemerDatum) , toData ) import Contract.ScriptLookups as Lookups -import Contract.Scripts - ( Validator(Validator) - , validatorHash - ) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV1FromEnvelope) +import Contract.Scripts (Validator, validatorHash) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) -import Contract.Value as Value import Control.Monad.Error.Class (liftMaybe) -import Ctl.Examples.Helpers - ( mkCurrencySymbol - , mkTokenName - ) -import Ctl.Examples.MintsMultipleTokens - ( mintingPolicyRdmrInt3 - ) -import Ctl.Examples.PlutusV2.ReferenceInputsAndScripts - ( mintAlwaysMintsV2ToTheScript - ) -import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyV2) +import Ctl.Examples.Helpers (mkAssetName) +import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) import Data.List as List import Data.Map as Map import Data.Traversable (sequence) @@ -45,10 +39,10 @@ import JS.BigInt as BigInt contract :: Contract Unit contract = do - tokenName <- mkTokenName "Token" + tokenName <- mkAssetName "Token" validator1 <- redeemerIs1Validator validator2 <- redeemerIs2Validator - mintingPolicy <- alwaysMintsPolicyV2 + mintingPolicy <- alwaysMintsPolicyScriptV2 -- Lock tokens on different script addresses @@ -64,16 +58,16 @@ contract = do constraints = (mconcat $ fst <$> lcs) :: Constraints.TxConstraints txHash <- submitTxFromConstraints - (Lookups.mintingPolicy mintingPolicy <> lookups) + (Lookups.plutusMintingPolicy mintingPolicy <> lookups) constraints void $ awaitTxConfirmed txHash contractWithMintRedeemers :: Contract Unit contractWithMintRedeemers = do - tokenName <- mkTokenName "Token" + tokenName <- mkAssetName "Token" validator1 <- redeemerIs1Validator - mintingPolicy <- alwaysMintsPolicyV2 - mp /\ cs <- mkCurrencySymbol mintingPolicyRdmrInt3 + mintingPolicy <- alwaysMintsPolicyScriptV2 + let cs = PlutusScript.hash mintingPolicy -- Lock tokens on script address @@ -87,12 +81,13 @@ contractWithMintRedeemers = do let mintingConstraints = ( Constraints.mustMintValueWithRedeemer - (Redeemer $ Integer $ BigInt.fromInt 3) - (Value.singleton cs tokenName one) + (RedeemerDatum $ Integer $ BigInt.fromInt 3) + (Mint.singleton cs tokenName Int.one) ) txHash <- submitTxFromConstraints - ( Lookups.mintingPolicy mintingPolicy <> Lookups.mintingPolicy mp <> - unlockingLookups + ( Lookups.plutusMintingPolicy mintingPolicy + <> Lookups.plutusMintingPolicy mintingPolicy + <> unlockingLookups ) (unlockingConstraints <> mintingConstraints) void $ awaitTxConfirmed txHash @@ -105,12 +100,12 @@ spendLockedByIntOutputParams ) spendLockedByIntOutputParams (validator /\ redeemerVal) = do let vhash = validatorHash validator - utxo <- utxosAt (scriptHashAddress vhash Nothing) + utxo <- utxosAt =<< mkAddress (wrap $ ScriptHashCredential vhash) Nothing constraints <- pure $ mconcat do input <- List.fromFoldable $ Map.keys utxo pure $ ( Constraints.mustSpendScriptOutput input - $ Redeemer + $ RedeemerDatum $ toData $ Integer $ BigInt.fromInt redeemerVal @@ -127,18 +122,44 @@ redeemerIs1Validator :: Contract Validator redeemerIs1Validator = do liftMaybe (error "Error decoding redeemerIs1Script") do envelope <- decodeTextEnvelope redeemerIs1Script - Validator <$> plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope -- | checks whether redeemer is 2 redeemerIs2Validator :: Contract Validator redeemerIs2Validator = do liftMaybe (error "Error decoding redeemerIs2Script") do envelope <- decodeTextEnvelope redeemerIs2Script - Validator <$> plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope -- | checks whether redeemer is 3 redeemerIs3Validator :: Contract Validator redeemerIs3Validator = do liftMaybe (error "Error decoding redeemerIs3Script") do envelope <- decodeTextEnvelope redeemerIs3Script - Validator <$> plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope + +mintAlwaysMintsV2ToTheScript + :: AssetName -> Validator -> Int -> Contract Unit +mintAlwaysMintsV2ToTheScript tokenName validator sum = do + mp <- alwaysMintsPolicyScriptV2 + let cs = PlutusScript.hash mp + + let + vhash = PlutusScript.hash validator + + constraints :: Constraints.TxConstraints + constraints = mconcat + [ Constraints.mustMintValue + $ Mint.singleton cs tokenName + $ Int.fromInt sum + , Constraints.mustPayToScript vhash PlutusData.unit + Constraints.DatumWitness + $ Value.singleton cs tokenName + $ BigNum.fromInt sum + ] + + lookups :: Lookups.ScriptLookups + lookups = Lookups.plutusMintingPolicy mp + + txHash <- submitTxFromConstraints lookups constraints + void $ awaitTxConfirmed txHash diff --git a/examples/NativeScriptMints.purs b/examples/NativeScriptMints.purs index eb3cc0d0d6..62fe5fa1b8 100644 --- a/examples/NativeScriptMints.purs +++ b/examples/NativeScriptMints.purs @@ -4,36 +4,47 @@ module Ctl.Examples.NativeScriptMints (main, example, contract, pkhPolicy) where import Contract.Prelude -import Contract.Address - ( PaymentPubKeyHash +import Cardano.Transaction.Builder + ( CredentialWitness(NativeScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, MintAsset) + ) +import Cardano.Types + ( BigNum + , Credential(PubKeyHashCredential) + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Int as Int +import Cardano.Types.NativeScript as NativeScript +import Cardano.Types.Transaction as Transaction +import Contract.Address (PaymentPubKeyHash, mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName ) -import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) -import Contract.ScriptLookups as Lookups -import Contract.Scripts - ( MintingPolicy(NativeMintingPolicy) - , NativeScript(ScriptPubkey) - ) -import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) -import Contract.TxConstraints as Constraints +import Contract.Scripts (NativeScript(ScriptPubkey)) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) import Contract.Value (CurrencySymbol, TokenName) import Contract.Value as Value -import Contract.Wallet - ( ownPaymentPubKeyHashes - , ownStakePubKeyHashes - ) -import Ctl.Examples.Helpers - ( mkCurrencySymbol - , mkTokenName - , mustPayToPubKeyStakeAddress - ) as Helpers +import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) +import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head) -import JS.BigInt (BigInt) +import Data.Map as Map import JS.BigInt as BigInt main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } contract :: Contract Unit contract = do @@ -41,51 +52,48 @@ contract = do pkh <- liftedM "Couldn't get own pkh" $ head <$> ownPaymentPubKeyHashes - mp /\ cs <- Helpers.mkCurrencySymbol <<< pure $ pkhPolicy pkh - tn <- Helpers.mkTokenName "NSToken" - - let - constraints :: Constraints.TxConstraints - constraints = - Constraints.mustMintCurrencyUsingNativeScript - (nsPolicy pkh) - tn $ BigInt.fromInt 100 - - lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp + let mintingPolicy = pkhPolicy pkh + let scriptHash = NativeScript.hash mintingPolicy + assetName <- Helpers.mkAssetName "NSToken" - txId <- submitTxFromConstraints lookups constraints + txId <- Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ MintAsset + scriptHash + assetName + (Int.fromInt 100) + (NativeScriptCredential (ScriptValue mintingPolicy)) + ] awaitTxConfirmed txId logInfo' "Minted successfully" - toSelfContract cs tn $ BigInt.fromInt 50 + toSelfContract scriptHash assetName $ BigNum.fromInt 50 -toSelfContract :: CurrencySymbol -> TokenName -> BigInt -> Contract Unit +toSelfContract :: CurrencySymbol -> TokenName -> BigNum -> Contract Unit toSelfContract cs tn amount = do pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes skh <- join <<< head <$> ownStakePubKeyHashes - + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) let - constraints :: Constraints.TxConstraints - constraints = Helpers.mustPayToPubKeyStakeAddress pkh skh - $ Value.singleton cs tn - $ amount - - lookups :: Lookups.ScriptLookups - lookups = mempty - - txId <- submitTxFromConstraints lookups constraints - - awaitTxConfirmed txId + plan = + [ Pay $ TransactionOutput + { address + , amount: Value.singleton cs tn amount + , datum: Nothing + , scriptRef: Nothing + } + ] + + tx <- submitTxFromBuildPlan Map.empty mempty plan + + awaitTxConfirmed $ Transaction.hash tx logInfo' $ "Moved " <> show (BigInt.fromInt 50) <> " to self successfully" example :: ContractParams -> Effect Unit example cfg = launchAff_ $ do runContract cfg contract -nsPolicy :: PaymentPubKeyHash -> NativeScript -nsPolicy = ScriptPubkey <<< unwrap <<< unwrap - -pkhPolicy :: PaymentPubKeyHash -> MintingPolicy -pkhPolicy = NativeMintingPolicy <<< nsPolicy +pkhPolicy :: PaymentPubKeyHash -> NativeScript +pkhPolicy = ScriptPubkey <<< unwrap diff --git a/examples/OneShotMinting.purs b/examples/OneShotMinting.purs index b37bb08e28..694fc63e02 100644 --- a/examples/OneShotMinting.purs +++ b/examples/OneShotMinting.purs @@ -1,4 +1,5 @@ --- | This module demonstrates how `applyArgs` from `Contract.Scripts` can be +-- | This module demonstrates how `applyArgs` from `Cardano.Plutus.ApplyArgs` +-- | (from https://github.com/mlabs-haskell/purescript-uplc-apply-args) can be -- | used to build scripts with the provided arguments applied. It creates a -- | transaction that mints an NFT using the one-shot minting policy. module Ctl.Examples.OneShotMinting @@ -7,13 +8,31 @@ module Ctl.Examples.OneShotMinting , main , mkContractWithAssertions , mkOneShotMintingPolicy - , oneShotMintingPolicy , oneShotMintingPolicyScript ) where import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Plutus.ApplyArgs (applyArgs) +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, MintAsset) + ) +import Cardano.Types (_body, _fee, _input) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Int as Int +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (fromUtxoMap) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad ( Contract @@ -24,46 +43,42 @@ import Contract.Monad , runContract ) import Contract.PlutusData (PlutusData, toData) -import Contract.ScriptLookups as Lookups -import Contract.Scripts - ( ApplyArgsError - , MintingPolicy(PlutusMintingPolicy) - , PlutusScript - , applyArgs - ) +import Contract.Scripts (PlutusScript) import Contract.Test.Assert ( ContractCheck , checkLossInWallet , checkTokenGainInWallet' , runChecks ) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV1FromEnvelope) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionInput , awaitTxConfirmed - , submitTxFromConstraintsReturningFee + , submitTxFromBuildPlan ) -import Contract.TxConstraints as Constraints -import Contract.Value (CurrencySymbol, TokenName) -import Contract.Value (singleton) as Value +import Contract.Value (AssetName, ScriptHash) import Contract.Wallet (getWalletUtxos) import Control.Monad.Error.Class (liftMaybe) import Control.Monad.Trans.Class (lift) -import Ctl.Examples.Helpers (mkCurrencySymbol, mkTokenName) as Helpers +import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head, singleton) as Array -import Data.Map (toUnfoldable) as Map +import Data.Lens ((^.)) +import Data.Map (empty) as Map import Effect.Exception (error, throw) import JS.BigInt (BigInt) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do runContract cfg contract mkChecks - :: (CurrencySymbol /\ TokenName /\ BigInt) + :: (ScriptHash /\ AssetName /\ BigInt) -> Array (ContractCheck { txFinalFee :: BigInt }) mkChecks nft = [ checkTokenGainInWallet' nft @@ -76,57 +91,53 @@ mkChecks nft = contract :: Contract Unit contract = - mkContractWithAssertions "Examples.OneShotMinting" oneShotMintingPolicy + mkContractWithAssertions "Examples.OneShotMinting" oneShotMintingPolicyScript mkContractWithAssertions :: String - -> (TransactionInput -> Contract MintingPolicy) + -> (TransactionInput -> Contract PlutusScript) -> Contract Unit mkContractWithAssertions exampleName mkMintingPolicy = do logInfo' ("Running " <> exampleName) - utxos <- liftedM "Failed to get UTxOs from wallet" getWalletUtxos + utxos <- liftedM "Failed to get UTxOs from wallet" $ getWalletUtxos <#> map + fromUtxoMap oref <- liftContractM "Utxo set is empty" - (fst <$> Array.head (Map.toUnfoldable utxos :: Array _)) + (Array.head utxos) - mp /\ cs <- Helpers.mkCurrencySymbol (mkMintingPolicy oref) - tn <- Helpers.mkTokenName "CTLNFT" + ps <- mkMintingPolicy (oref ^. _input) + let cs = PlutusScript.hash ps + tn <- Helpers.mkAssetName "CTLNFT" let - constraints :: Constraints.TxConstraints - constraints = - Constraints.mustMintValue (Value.singleton cs tn one) - <> Constraints.mustSpendPubKeyOutput oref - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.mintingPolicy mp - <> Lookups.unspentOutputs utxos + plan = + [ MintAsset cs tn (Int.fromInt one) + (PlutusScriptCredential (ScriptValue ps) RedeemerDatum.unit) + , SpendOutput (oref) Nothing + ] let checks = mkChecks (cs /\ tn /\ one) void $ runChecks checks $ lift do - { txHash, txFinalFee } <- - submitTxFromConstraintsReturningFee lookups constraints + tx <- submitTxFromBuildPlan Map.empty mempty plan + let + txHash = Transaction.hash tx + txFinalFee = tx ^. _body <<< _fee logInfo' $ "Tx ID: " <> show txHash awaitTxConfirmed txHash logInfo' "Tx submitted successfully!" - pure { txFinalFee } - -oneShotMintingPolicy :: TransactionInput -> Contract MintingPolicy -oneShotMintingPolicy = - map PlutusMintingPolicy <<< oneShotMintingPolicyScript + pure { txFinalFee: BigNum.toBigInt $ unwrap txFinalFee } oneShotMintingPolicyScript :: TransactionInput -> Contract PlutusScript oneShotMintingPolicyScript txInput = do script <- liftMaybe (error "Error decoding oneShotMinting") do envelope <- decodeTextEnvelope oneShotMinting - plutusScriptV1FromEnvelope envelope + plutusScriptFromEnvelope envelope liftContractE $ mkOneShotMintingPolicy script txInput mkOneShotMintingPolicy :: PlutusScript -> TransactionInput - -> Either ApplyArgsError PlutusScript + -> Either String PlutusScript mkOneShotMintingPolicy unappliedMintingPolicy oref = let mintingPolicyArgs :: Array PlutusData diff --git a/examples/PaysWithDatum.purs b/examples/PaysWithDatum.purs index 1cc9efded2..bea549b6a3 100644 --- a/examples/PaysWithDatum.purs +++ b/examples/PaysWithDatum.purs @@ -8,16 +8,21 @@ module Ctl.Examples.PaysWithDatum (contract, example, main) where import Contract.Prelude -import Contract.Address - ( Address +import Cardano.Types (TransactionOutput) +import Cardano.Types.BigNum as BigNum +import Contract.Address (Address) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName ) -import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Hashing (datumHash) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) import Contract.PlutusData ( DataHash - , Datum(Datum) , OutputDatum(OutputDatum, OutputDatumHash) , PlutusData(Integer) ) @@ -33,7 +38,6 @@ import Contract.Test.Assert ) import Contract.Transaction ( TransactionHash - , TransactionOutputWithRefScript , awaitTxConfirmed , submitTxFromConstraints ) @@ -54,12 +58,15 @@ import JS.BigInt (fromInt) as BigInt type ContractResult = { address :: Address , txHash :: TransactionHash - , datum :: Datum + , datum :: PlutusData , datumHash :: DataHash } main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example = launchAff_ <<< flip runContract contract @@ -73,11 +80,11 @@ contract = do address <- liftedM "Could not get own address" (head <$> getWalletAddresses) let - datum = Datum $ Integer $ BigInt.fromInt 42 + datum = Integer $ BigInt.fromInt 42 datumHash' = datumHash datum value :: Value - value = Value.lovelaceValueOf (BigInt.fromInt 2_000_000) + value = Value.lovelaceValueOf (BigNum.fromInt 2_000_000) constraints :: Constraints.TxConstraints constraints = @@ -126,6 +133,6 @@ assertTxCreatesOutputWithDatumHash = assertionToCheck hasOutputWithOutputDatum (OutputDatumHash datumHash) outputs hasOutputWithOutputDatum - :: OutputDatum -> Array TransactionOutputWithRefScript -> Boolean + :: OutputDatum -> Array TransactionOutput -> Boolean hasOutputWithOutputDatum datum = - any (eq datum <<< _.datum <<< unwrap <<< _.output <<< unwrap) + any (eq (Just datum) <<< _.datum <<< unwrap) diff --git a/examples/Pkh2Pkh.purs b/examples/Pkh2Pkh.purs index 85b3752d72..fe1ff36502 100644 --- a/examples/Pkh2Pkh.purs +++ b/examples/Pkh2Pkh.purs @@ -5,41 +5,48 @@ module Ctl.Examples.Pkh2Pkh (main, contract, example) where import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Transaction.Builder (TransactionBuilderStep(Pay)) +import Cardano.Types + ( OutputDatum(OutputDatumHash) + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) -import Contract.ScriptLookups as Lookups -import Contract.Transaction - ( awaitTxConfirmedWithTimeout - , submitTxFromConstraints - ) -import Contract.TxConstraints as Constraints +import Contract.Transaction (awaitTxConfirmedWithTimeout, submitTxFromBuildPlan) import Contract.Value as Value -import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) +import Contract.Wallet (getWalletAddresses) import Data.Array (head) -import JS.BigInt as BigInt +import Data.Map as Map main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } contract :: Contract Unit contract = do logInfo' "Running Examples.Pkh2Pkh" - pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes - skh <- liftedM "Failed to get own SKH" $ join <<< head <$> - ownStakePubKeyHashes - - let - constraints :: Constraints.TxConstraints - constraints = Constraints.mustPayToPubKeyAddress pkh skh - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - txId <- submitTxFromConstraints lookups constraints - + address <- liftedM "Failed to get own address" $ head <$> getWalletAddresses + txId <- Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] awaitTxConfirmedWithTimeout (wrap 100.0) txId logInfo' $ "Tx submitted successfully!" diff --git a/examples/PlutusV2/AlwaysSucceeds.purs b/examples/PlutusV2/AlwaysSucceeds.purs index 70122b3f72..ba43f5b11e 100644 --- a/examples/PlutusV2/AlwaysSucceeds.purs +++ b/examples/PlutusV2/AlwaysSucceeds.purs @@ -1,21 +1,25 @@ -- | This module demonstrates how the `Contract` interface can be used to build, -- | balance, and submit a smart-contract transaction. It creates a transaction -- | that pays two Ada to the `AlwaysSucceeds` script address -module Ctl.Examples.PlutusV2.AlwaysSucceeds (main, example, contract) where +module Ctl.Examples.PlutusV2.AlwaysSucceeds + ( contract + , example + , main + ) where import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Log (logInfo') -import Contract.Monad - ( Contract - , launchAff_ - , runContract +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName ) +import Contract.Log (logInfo') +import Contract.Monad (Contract, launchAff_, runContract) import Contract.Scripts (validatorHash) -import Contract.Transaction - ( awaitTxConfirmed - ) +import Contract.Transaction (awaitTxConfirmed) import Ctl.Examples.AlwaysSucceeds ( payToAlwaysSucceeds , spendFromAlwaysSucceeds @@ -23,7 +27,10 @@ import Ctl.Examples.AlwaysSucceeds import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } contract :: Contract Unit contract = do @@ -39,4 +46,3 @@ contract = do example :: ContractParams -> Effect Unit example cfg = launchAff_ do runContract cfg contract - diff --git a/examples/PlutusV2/InlineDatum.purs b/examples/PlutusV2/InlineDatum.purs index d2f2eca5ff..a0d1e7e7cb 100644 --- a/examples/PlutusV2/InlineDatum.purs +++ b/examples/PlutusV2/InlineDatum.purs @@ -13,23 +13,26 @@ module Ctl.Examples.PlutusV2.InlineDatum import Contract.Prelude -import Contract.Address (scriptHashAddress) -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Types (Credential(ScriptHashCredential)) +import Cardano.Types.BigNum as BigNum +import Contract.Address (mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData - ( Datum(Datum) - , PlutusData(Integer) - , Redeemer(Redeemer) - ) +import Contract.PlutusData (PlutusData(Integer), RedeemerDatum(RedeemerDatum)) import Contract.ScriptLookups as Lookups -import Contract.Scripts (Validator(Validator), ValidatorHash, validatorHash) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV2FromEnvelope) +import Contract.Scripts (Validator, ValidatorHash, validatorHash) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( OutputDatum(OutputDatum) , TransactionHash , TransactionInput(TransactionInput) - , TransactionOutputWithRefScript(TransactionOutputWithRefScript) , awaitTxConfirmed , submitTxFromConstraints ) @@ -44,7 +47,10 @@ import JS.BigInt as BigInt import Test.Spec.Assertions (shouldEqual) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -64,15 +70,12 @@ plutusData = Integer $ BigInt.fromInt 31415927 payToCheckDatumIsInline :: ValidatorHash -> Contract TransactionHash payToCheckDatumIsInline vhash = do let - datum :: Datum - datum = Datum plutusData - constraints :: TxConstraints constraints = - Constraints.mustPayToScript vhash datum + Constraints.mustPayToScript vhash plutusData Constraints.DatumInline $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 + $ BigNum.fromInt 2_000_000 lookups :: Lookups.ScriptLookups lookups = mempty @@ -85,7 +88,7 @@ spendFromCheckDatumIsInline -> TransactionHash -> Contract Unit spendFromCheckDatumIsInline vhash validator txId = do - let scriptAddress = scriptHashAddress vhash Nothing + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing utxos <- utxosAt scriptAddress txInput <- liftM @@ -98,8 +101,8 @@ spendFromCheckDatumIsInline vhash validator txId = do ) (fst <$> find hasTransactionId (Map.toUnfoldable utxos :: Array _)) let - redeemer :: Redeemer - redeemer = Redeemer plutusData + redeemer :: RedeemerDatum + redeemer = RedeemerDatum plutusData lookups :: Lookups.ScriptLookups lookups = Lookups.validator validator @@ -121,15 +124,13 @@ spendFromCheckDatumIsInline vhash validator txId = do payToCheckDatumIsInlineWrong :: ValidatorHash -> Contract TransactionHash payToCheckDatumIsInlineWrong vhash = do let - datum :: Datum - datum = Datum plutusData constraints :: TxConstraints constraints = - Constraints.mustPayToScript vhash datum + Constraints.mustPayToScript vhash plutusData Constraints.DatumWitness $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 + $ BigNum.fromInt 2_000_000 lookups :: Lookups.ScriptLookups lookups = mempty @@ -141,19 +142,18 @@ readFromCheckDatumIsInline -> TransactionHash -> Contract Unit readFromCheckDatumIsInline vhash txId = do - let scriptAddress = scriptHashAddress vhash Nothing + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing utxos <- utxosAt scriptAddress - TransactionOutputWithRefScript { output } <- - liftM - ( error - ( "The id " - <> show txId - <> " does not have output locked at: " - <> show scriptAddress - ) - ) - (snd <$> find hasTransactionId (Map.toUnfoldable utxos :: Array _)) - (unwrap output).datum `shouldEqual` OutputDatum (Datum plutusData) + output <- liftM + ( error + ( "The id " + <> show txId + <> " does not have output locked at: " + <> show scriptAddress + ) + ) + (snd <$> find hasTransactionId (Map.toUnfoldable utxos :: Array _)) + (unwrap output).datum `shouldEqual` Just (OutputDatum plutusData) logInfo' "Successfully read inline datum." where @@ -165,6 +165,6 @@ checkDatumIsInlineScript :: Contract Validator checkDatumIsInlineScript = do liftMaybe (error "Error decoding checkDatumIsInline") do envelope <- decodeTextEnvelope checkDatumIsInline - Validator <$> plutusScriptV2FromEnvelope envelope + plutusScriptFromEnvelope envelope foreign import checkDatumIsInline :: String diff --git a/examples/PlutusV2/OneShotMinting.purs b/examples/PlutusV2/OneShotMinting.purs index 83c1d44136..e8ec3979e9 100644 --- a/examples/PlutusV2/OneShotMinting.purs +++ b/examples/PlutusV2/OneShotMinting.purs @@ -1,4 +1,5 @@ --- | This module demonstrates how `applyArgs` from `Contract.Scripts` can be +-- | This module demonstrates how `applyArgs` from `Cardano.Plutus.ApplyArgs` +-- | (from https://github.com/mlabs-haskell/purescript-uplc-apply-args) can be -- | used to build PlutusV2 scripts with the provided arguments applied. It -- | creates a transaction that mints an NFT using the one-shot minting policy. module Ctl.Examples.PlutusV2.OneShotMinting @@ -6,20 +7,20 @@ module Ctl.Examples.PlutusV2.OneShotMinting , example , main , oneShotMintingPolicyScriptV2 - , oneShotMintingPolicyV2 ) where import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Monad - ( Contract - , launchAff_ - , liftContractE - , runContract +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName ) -import Contract.Scripts (MintingPolicy(PlutusMintingPolicy), PlutusScript) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV2FromEnvelope) +import Contract.Monad (Contract, launchAff_, liftContractE, runContract) +import Contract.Scripts (PlutusScript) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction (TransactionInput) import Control.Monad.Error.Class (liftMaybe) import Ctl.Examples.OneShotMinting @@ -29,7 +30,10 @@ import Ctl.Examples.OneShotMinting import Effect.Exception (error) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -38,17 +42,13 @@ example cfg = launchAff_ do contract :: Contract Unit contract = mkContractWithAssertions "Examples.PlutusV2.OneShotMinting" - oneShotMintingPolicyV2 - -oneShotMintingPolicyV2 :: TransactionInput -> Contract MintingPolicy -oneShotMintingPolicyV2 = - map PlutusMintingPolicy <<< oneShotMintingPolicyScriptV2 + oneShotMintingPolicyScriptV2 oneShotMintingPolicyScriptV2 :: TransactionInput -> Contract PlutusScript oneShotMintingPolicyScriptV2 txInput = do script <- liftMaybe (error "Error decoding oneShotMinting") do envelope <- decodeTextEnvelope oneShotMinting - plutusScriptV2FromEnvelope envelope + plutusScriptFromEnvelope envelope liftContractE $ mkOneShotMintingPolicy script txInput diff --git a/examples/PlutusV2/ReferenceInputs.purs b/examples/PlutusV2/ReferenceInputs.purs deleted file mode 100644 index d97f614b00..0000000000 --- a/examples/PlutusV2/ReferenceInputs.purs +++ /dev/null @@ -1,119 +0,0 @@ -module Ctl.Examples.PlutusV2.ReferenceInputs (contract, example, main) where - -import Contract.Prelude - -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Log (logInfo') -import Contract.Monad - ( Contract - , launchAff_ - , liftContractM - , liftedM - , runContract - ) -import Contract.ScriptLookups as Lookups -import Contract.Test.Assert - ( ContractAssertionFailure(CustomFailure) - , ContractCheck - , assertContract - , assertionToCheck - , runChecks - ) -import Contract.Transaction - ( BalancedSignedTransaction - , TransactionInput - , _body - , _referenceInputs - , awaitTxConfirmed - , balanceTx - , signTransaction - , submit - ) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) -import Contract.Value (lovelaceValueOf) as Value -import Contract.Wallet - ( getWalletUtxos - , ownPaymentPubKeyHashes - , ownStakePubKeyHashes - ) -import Control.Monad.Trans.Class (lift) -import Ctl.Examples.Helpers (mustPayToPubKeyStakeAddress) as Helpers -import Data.Array (head) as Array -import Data.Lens.Getter ((^.)) -import Data.Map (member, toUnfoldable) as Map -import Data.Set (member) as Set -import JS.BigInt (fromInt) as BigInt - -main :: Effect Unit -main = example testnetNamiConfig - -example :: ContractParams -> Effect Unit -example = launchAff_ <<< flip runContract contract - -contract :: Contract Unit -contract = do - logInfo' "Running Examples.PlutusV2.ReferenceInputs" - - pkh <- liftedM "Failed to get own PKH" - (Array.head <$> ownPaymentPubKeyHashes) - skh <- join <<< Array.head <$> ownStakePubKeyHashes - - utxos <- liftedM "Failed to get UTxOs from wallet" getWalletUtxos - oref <- - liftContractM "Utxo set is empty" - (fst <$> Array.head (Map.toUnfoldable utxos :: Array _)) - - let - constraints :: Constraints.TxConstraints - constraints = mconcat - [ Constraints.mustReferenceOutput oref - , Helpers.mustPayToPubKeyStakeAddress pkh skh - (Value.lovelaceValueOf $ BigInt.fromInt 2_000_000) - ] - - lookups :: Lookups.ScriptLookups - lookups = mempty - - void $ runChecks checks $ lift do - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedSignedTx <- signTransaction =<< balanceTx unbalancedTx - txHash <- submit balancedSignedTx - logInfo' $ "Tx ID: " <> show txHash - awaitTxConfirmed txHash - logInfo' "Tx submitted successfully!" - - pure { referenceInput: oref, balancedSignedTx } - -type ContractResult = - { referenceInput :: TransactionInput - , balancedSignedTx :: BalancedSignedTransaction - } - -assertTxContainsReferenceInput :: ContractCheck ContractResult -assertTxContainsReferenceInput = - assertionToCheck "Tx contains a reference input" - \{ balancedSignedTx, referenceInput } -> do - let - assertionFailure :: ContractAssertionFailure - assertionFailure = CustomFailure - "Could not find given input in `referenceInputs`" - assertContract assertionFailure do - Set.member referenceInput - (unwrap balancedSignedTx ^. _body <<< _referenceInputs) - -assertReferenceInputNotSpent :: ContractCheck ContractResult -assertReferenceInputNotSpent = assertionToCheck "A reference input UTxO" - \{ referenceInput } -> do - let - assertionFailure :: ContractAssertionFailure - assertionFailure = CustomFailure "Reference input has been spent" - utxos <- lift $ liftedM "Failed to get UTxOs from wallet" getWalletUtxos - assertContract assertionFailure do - Map.member referenceInput utxos - -checks :: Array (ContractCheck ContractResult) -checks = - [ assertTxContainsReferenceInput - , assertReferenceInputNotSpent - ] diff --git a/examples/PlutusV2/ReferenceInputsAndScripts.purs b/examples/PlutusV2/ReferenceInputsAndScripts.purs index b0a453bf91..c19a2fd965 100644 --- a/examples/PlutusV2/ReferenceInputsAndScripts.purs +++ b/examples/PlutusV2/ReferenceInputsAndScripts.purs @@ -2,71 +2,64 @@ module Ctl.Examples.PlutusV2.ReferenceInputsAndScripts ( contract , example , main - , mintAlwaysMintsV2ToTheScript ) where import Contract.Prelude -import Contract.Address - ( PaymentPubKeyHash - , StakePubKeyHash - , scriptHashAddress +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , OutputWitness(PlutusScriptOutput) + , RefInputAction(ReferenceInput) + , ScriptWitness(ScriptReference) + , TransactionBuilderStep(MintAsset, SpendOutput, Pay) ) -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Log (logInfo') -import Contract.Monad - ( Contract - , launchAff_ - , liftContractM - , liftedM - , runContract +import Cardano.Types + ( Credential(ScriptHashCredential) + , OutputDatum(OutputDatum) + , ScriptHash + , TransactionOutput(TransactionOutput) + , TransactionUnspentOutput ) -import Contract.PlutusData (unitDatum, unitRedeemer) -import Contract.ScriptLookups as Lookups -import Contract.Scripts - ( MintingPolicy(PlutusMintingPolicy) - , MintingPolicyHash - , PlutusScript - , Validator - , ValidatorHash - , mintingPolicyHash - , validatorHash +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Int as Int +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Contract.Address (mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName ) +import Contract.Log (logInfo') +import Contract.Monad (Contract, launchAff_, liftContractM, runContract) +import Contract.Scripts (PlutusScript) import Contract.Transaction ( ScriptRef(PlutusScriptRef) , TransactionHash - , TransactionInput(TransactionInput) - , TransactionOutputWithRefScript + , TransactionOutput , awaitTxConfirmed - , mkTxUnspentOut - , submitTxFromConstraints - ) -import Contract.TxConstraints - ( DatumPresence(DatumWitness) - , InputWithScriptRef(RefInput) - , TxConstraints + , lookupTxHash + , submitTxFromBuildPlan ) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value (TokenName, Value) import Contract.Value as Value -import Contract.Wallet - ( getWalletAddresses - , ownPaymentPubKeyHashes - , ownStakePubKeyHashes - ) -import Ctl.Examples.Helpers (mkTokenName) as Helpers -import Ctl.Examples.PlutusV2.Scripts.AlwaysMints - ( alwaysMintsPolicyScriptV2 - , alwaysMintsPolicyV2 - ) +import Ctl.Examples.Helpers (mkAssetName) as Helpers +import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) -import Data.Array (head) -import Data.Map (toUnfoldable) as Map -import JS.BigInt (fromInt) as BigInt +import Data.Array (find) as Array +import Data.Map (empty, toUnfoldable) as Map +import Effect.Exception (error) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -77,13 +70,13 @@ contract = do logInfo' "Running Examples.PlutusV2.ReferenceInputsAndScripts" validator <- alwaysSucceedsScriptV2 mintsScript <- alwaysMintsPolicyScriptV2 - tokenName <- Helpers.mkTokenName "TheToken" + tokenName <- Helpers.mkAssetName "TheToken" let - vhash :: ValidatorHash - vhash = validatorHash validator + vhash :: ScriptHash + vhash = PlutusScript.hash validator validatorRef :: ScriptRef - validatorRef = PlutusScriptRef (unwrap validator) + validatorRef = PlutusScriptRef validator mpRef :: ScriptRef mpRef = PlutusScriptRef mintsScript @@ -92,121 +85,93 @@ contract = do txId <- payToAlwaysSucceedsAndCreateScriptRefOutput vhash validatorRef mpRef awaitTxConfirmed txId logInfo' "Tx submitted successfully, Try to spend locked values" - spendFromAlwaysSucceeds vhash txId (unwrap validator) mintsScript + spendFromAlwaysSucceeds vhash txId validator mintsScript tokenName payToAlwaysSucceedsAndCreateScriptRefOutput - :: ValidatorHash -> ScriptRef -> ScriptRef -> Contract TransactionHash + :: ScriptHash -> ScriptRef -> ScriptRef -> Contract TransactionHash payToAlwaysSucceedsAndCreateScriptRefOutput vhash validatorRef mpRef = do - pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes - skh <- join <<< head <$> ownStakePubKeyHashes + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing let value :: Value - value = Value.lovelaceValueOf (BigInt.fromInt 2_000_000) - - createOutputWithScriptRef :: ScriptRef -> TxConstraints - createOutputWithScriptRef scriptRef = - mustPayToPubKeyStakeAddressWithScriptRef pkh skh scriptRef value - - constraints :: TxConstraints - constraints = - Constraints.mustPayToScript vhash unitDatum DatumWitness value - <> createOutputWithScriptRef validatorRef - <> createOutputWithScriptRef mpRef - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + value = Value.lovelaceValueOf (BigNum.fromInt 2_000_000) + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Just validatorRef + } + , Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Just mpRef + } + , Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Nothing + } + ] spendFromAlwaysSucceeds - :: ValidatorHash + :: ScriptHash -> TransactionHash -> PlutusScript -> PlutusScript -> TokenName -> Contract Unit spendFromAlwaysSucceeds vhash txId validator mp tokenName = do - let scriptAddress = scriptHashAddress vhash Nothing - ownAddress <- liftedM "Failed to get own address" $ head <$> - getWalletAddresses - (utxos :: Array _) <- Map.toUnfoldable <$> utxosAt ownAddress + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing scriptAddressUtxos <- utxosAt scriptAddress - - txInput /\ _ <- - liftContractM "Could not find unspent output locked at script address" - $ find hasTransactionId (Map.toUnfoldable scriptAddressUtxos :: Array _) - - refValidatorInput /\ refValidatorOutput <- + utxo <- + liftM + ( error + ( "The id " + <> show txId + <> " does not have output locked at: " + <> show scriptAddress + ) + ) + $ Array.find hasNoRefScript + $ lookupTxHash txId scriptAddressUtxos + + refValidatorInput /\ _ <- liftContractM "Could not find unspent output containing ref validator" - $ find (hasRefPlutusScript validator) utxos + $ Array.find (hasRefPlutusScript validator) + $ Map.toUnfoldable scriptAddressUtxos - refMpInput /\ refMpOutput <- + refMpInput /\ _ <- liftContractM "Could not find unspent output containing ref minting policy" - $ find (hasRefPlutusScript mp) utxos + $ Array.find (hasRefPlutusScript mp) + $ Map.toUnfoldable scriptAddressUtxos let - mph :: MintingPolicyHash - mph = mintingPolicyHash (PlutusMintingPolicy mp) - - constraints :: TxConstraints - constraints = mconcat - [ Constraints.mustSpendScriptOutputUsingScriptRef txInput unitRedeemer - (RefInput $ mkTxUnspentOut refValidatorInput refValidatorOutput) - - , Constraints.mustMintCurrencyUsingScriptRef mph tokenName one - (RefInput $ mkTxUnspentOut refMpInput refMpOutput) - ] - - lookups :: Lookups.ScriptLookups - lookups = Lookups.unspentOutputs scriptAddressUtxos - - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId + mph = PlutusScript.hash mp + spendTx <- submitTxFromBuildPlan scriptAddressUtxos mempty + [ SpendOutput + utxo + ( Just + $ PlutusScriptOutput + (ScriptReference refValidatorInput ReferenceInput) + RedeemerDatum.unit + Nothing + ) + , MintAsset mph tokenName (Int.fromInt 1) + $ PlutusScriptCredential (ScriptReference refMpInput ReferenceInput) + RedeemerDatum.unit + ] + awaitTxConfirmed $ Transaction.hash spendTx logInfo' "Successfully spent locked values and minted tokens." where - hasTransactionId :: TransactionInput /\ _ -> Boolean - hasTransactionId (TransactionInput txInput /\ _) = - txInput.transactionId == txId - hasRefPlutusScript - :: PlutusScript -> _ /\ TransactionOutputWithRefScript -> Boolean + :: PlutusScript + -> _ /\ TransactionOutput + -> Boolean hasRefPlutusScript plutusScript (_ /\ txOutput) = (unwrap txOutput).scriptRef == Just (PlutusScriptRef plutusScript) -mustPayToPubKeyStakeAddressWithScriptRef - :: forall (i :: Type) (o :: Type) - . PaymentPubKeyHash - -> Maybe StakePubKeyHash - -> ScriptRef - -> Value - -> TxConstraints -mustPayToPubKeyStakeAddressWithScriptRef pkh Nothing = - Constraints.mustPayToPubKeyWithScriptRef pkh -mustPayToPubKeyStakeAddressWithScriptRef pkh (Just skh) = - Constraints.mustPayToPubKeyAddressWithScriptRef pkh skh - -mintAlwaysMintsV2ToTheScript - :: TokenName -> Validator -> Int -> Contract Unit -mintAlwaysMintsV2ToTheScript tokenName validator sum = do - mp <- alwaysMintsPolicyV2 - let cs = Value.scriptCurrencySymbol mp - - let - vhash = validatorHash validator - - constraints :: Constraints.TxConstraints - constraints = mconcat - [ Constraints.mustMintValue - $ Value.singleton cs tokenName - $ BigInt.fromInt sum - , Constraints.mustPayToScript vhash unitDatum Constraints.DatumWitness - $ Value.singleton cs tokenName - $ BigInt.fromInt sum - ] - - lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp - - txHash <- submitTxFromConstraints lookups constraints - void $ awaitTxConfirmed txHash + hasNoRefScript :: TransactionUnspentOutput -> Boolean + hasNoRefScript utxo = isNothing (unwrap (unwrap utxo).output).scriptRef diff --git a/examples/PlutusV2/ReferenceScripts.purs b/examples/PlutusV2/ReferenceScripts.purs deleted file mode 100644 index a52783f7ac..0000000000 --- a/examples/PlutusV2/ReferenceScripts.purs +++ /dev/null @@ -1,120 +0,0 @@ -module Ctl.Examples.PlutusV2.ReferenceScripts - ( main - , example - , contract - ) where - -import Contract.Prelude - -import Contract.Address (scriptHashAddress) -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Credential (Credential(PubKeyCredential)) -import Contract.Log (logInfo') -import Contract.Monad (Contract, launchAff_, liftContractM, runContract) -import Contract.PlutusData (unitDatum, unitRedeemer) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (ValidatorHash, validatorHash) -import Contract.Transaction - ( ScriptRef(PlutusScriptRef) - , TransactionHash - , TransactionInput(TransactionInput) - , awaitTxConfirmed - , mkTxUnspentOut - , submitTxFromConstraints - ) -import Contract.TxConstraints - ( DatumPresence(DatumWitness) - , InputWithScriptRef(SpendInput) - , TxConstraints - ) -import Contract.TxConstraints as Constraints -import Contract.Utxos (utxosAt) -import Contract.Value (lovelaceValueOf) as Value -import Contract.Wallet (ownStakePubKeyHashes) -import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) -import Data.Array (head) -import Data.Map (toUnfoldable) as Map -import JS.BigInt (fromInt) as BigInt - -main :: Effect Unit -main = example testnetNamiConfig - -example :: ContractParams -> Effect Unit -example cfg = launchAff_ do - runContract cfg contract - -contract :: Contract Unit -contract = do - logInfo' "Running Examples.PlutusV2.ReferenceScripts" - validator <- alwaysSucceedsScriptV2 - let - vhash :: ValidatorHash - vhash = validatorHash validator - - scriptRef :: ScriptRef - scriptRef = PlutusScriptRef (unwrap validator) - - logInfo' "Attempt to lock value" - txId <- payWithScriptRefToAlwaysSucceeds vhash scriptRef - awaitTxConfirmed txId - logInfo' "Tx submitted successfully, Try to spend locked values" - spendFromAlwaysSucceeds vhash txId - -payWithScriptRefToAlwaysSucceeds - :: ValidatorHash -> ScriptRef -> Contract TransactionHash -payWithScriptRefToAlwaysSucceeds vhash scriptRef = do - -- Send to own stake credential. This is used to test - -- `mustPayToScriptAddressWithScriptRef` - mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - let - constraints :: TxConstraints - constraints = - case mbStakeKeyHash of - Nothing -> - Constraints.mustPayToScriptWithScriptRef vhash unitDatum DatumWitness - scriptRef - (Value.lovelaceValueOf $ BigInt.fromInt 2_000_000) - Just stakeKeyHash -> - Constraints.mustPayToScriptAddressWithScriptRef - vhash - (PubKeyCredential $ unwrap stakeKeyHash) - unitDatum - DatumWitness - scriptRef - (Value.lovelaceValueOf $ BigInt.fromInt 2_000_000) - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints - -spendFromAlwaysSucceeds :: ValidatorHash -> TransactionHash -> Contract Unit -spendFromAlwaysSucceeds vhash txId = do - -- Send to own stake credential. This is used to test - -- `mustPayToScriptAddressWithScriptRef` - mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - let - scriptAddress = - scriptHashAddress vhash (PubKeyCredential <<< unwrap <$> mbStakeKeyHash) - utxos <- utxosAt scriptAddress - - txInput /\ txOutput <- - liftContractM "Could not find unspent output locked at script address" - $ find hasTransactionId (Map.toUnfoldable utxos :: Array _) - - let - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutputUsingScriptRef txInput unitRedeemer - (SpendInput $ mkTxUnspentOut txInput txOutput) - - lookups :: Lookups.ScriptLookups - lookups = mempty - - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId - logInfo' "Successfully spent locked values." - where - hasTransactionId :: TransactionInput /\ _ -> Boolean - hasTransactionId (TransactionInput tx /\ _) = - tx.transactionId == txId diff --git a/examples/PlutusV2/Scripts/AlwaysMints.purs b/examples/PlutusV2/Scripts/AlwaysMints.purs index 15b9f072e3..c353aac092 100644 --- a/examples/PlutusV2/Scripts/AlwaysMints.purs +++ b/examples/PlutusV2/Scripts/AlwaysMints.purs @@ -1,24 +1,20 @@ module Ctl.Examples.PlutusV2.Scripts.AlwaysMints ( alwaysMintsPolicyScriptV2 - , alwaysMintsPolicyV2 ) where import Contract.Prelude import Contract.Monad (Contract) -import Contract.Scripts (MintingPolicy(PlutusMintingPolicy), PlutusScript) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV2FromEnvelope) +import Contract.Scripts (PlutusScript) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Control.Monad.Error.Class (liftMaybe) import Effect.Exception (error) -alwaysMintsPolicyV2 :: Contract MintingPolicy -alwaysMintsPolicyV2 = PlutusMintingPolicy <$> alwaysMintsPolicyScriptV2 - alwaysMintsPolicyScriptV2 :: Contract PlutusScript alwaysMintsPolicyScriptV2 = do liftMaybe (error "Error decoding alwaysMintsV2") do envelope <- decodeTextEnvelope alwaysMintsV2 - plutusScriptV2FromEnvelope envelope + plutusScriptFromEnvelope envelope alwaysMintsV2 :: String alwaysMintsV2 = diff --git a/examples/PlutusV2/Scripts/AlwaysSucceeds.purs b/examples/PlutusV2/Scripts/AlwaysSucceeds.purs index 6fd1387c79..77a11df5db 100644 --- a/examples/PlutusV2/Scripts/AlwaysSucceeds.purs +++ b/examples/PlutusV2/Scripts/AlwaysSucceeds.purs @@ -4,17 +4,17 @@ module Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds import Contract.Prelude +import Cardano.Types (PlutusScript) import Contract.Monad (Contract) -import Contract.Scripts (Validator(Validator)) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV2FromEnvelope) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Control.Monad.Error.Class (liftMaybe) import Effect.Exception (error) -alwaysSucceedsScriptV2 :: Contract Validator +alwaysSucceedsScriptV2 :: Contract PlutusScript alwaysSucceedsScriptV2 = do liftMaybe (error "Error decoding alwaysSucceeds") do envelope <- decodeTextEnvelope alwaysSucceedsV2 - Validator <$> plutusScriptV2FromEnvelope envelope + plutusScriptFromEnvelope envelope alwaysSucceedsV2 :: String alwaysSucceedsV2 = diff --git a/examples/PlutusV3/Scripts/AlwaysMints.purs b/examples/PlutusV3/Scripts/AlwaysMints.purs new file mode 100644 index 0000000000..4e7b827351 --- /dev/null +++ b/examples/PlutusV3/Scripts/AlwaysMints.purs @@ -0,0 +1,27 @@ +module Ctl.Examples.PlutusV3.Scripts.AlwaysMints + ( alwaysMintsPolicyScriptV3 + ) where + +import Contract.Prelude + +import Contract.Monad (Contract) +import Contract.Scripts (PlutusScript) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) +import Control.Monad.Error.Class (liftMaybe) +import Effect.Exception (error) + +alwaysMintsPolicyScriptV3 :: Contract PlutusScript +alwaysMintsPolicyScriptV3 = + liftMaybe (error "Error decoding alwaysMintsV3") do + envelope <- decodeTextEnvelope alwaysMintsV3 + plutusScriptFromEnvelope envelope + +alwaysMintsV3 :: String +alwaysMintsV3 = + """ + { + "cborHex": "46450101002499", + "description": "always-mints", + "type": "PlutusScriptV3" + } + """ diff --git a/examples/SatisfiesAnyOf.purs b/examples/SatisfiesAnyOf.purs deleted file mode 100644 index f7862b3606..0000000000 --- a/examples/SatisfiesAnyOf.purs +++ /dev/null @@ -1,55 +0,0 @@ --- | This module creates an unbalanced transaction --- | with the `mustSatisfyAnyOf` constraint in which --- | the evaluation of the first constraint list throws --- | a catched error and the evaluation of the second list succeeds. -module Ctl.Examples.SatisfiesAnyOf - ( example - , main - , testMustSatisfyAnyOf - ) where - -import Contract.Prelude - -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Hashing (datumHash) as Hashing -import Contract.Log (logInfo') -import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData - ( Datum(Datum) - , PlutusData(Integer) - , unitDatum - ) -import Contract.ScriptLookups as Lookups -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) -import JS.BigInt as BigInt - -main :: Effect Unit -main = example testnetNamiConfig - -example :: ContractParams -> Effect Unit -example cfg = launchAff_ do - runContract cfg do - logInfo' "Running Examples.SatisfiesAnyOf" - testMustSatisfyAnyOf - -wrongDatum :: Datum -wrongDatum = Datum $ Integer $ BigInt.fromInt 42 - -testMustSatisfyAnyOf :: Contract Unit -testMustSatisfyAnyOf = do - let - wrongDatumHash = Hashing.datumHash wrongDatum - correctDatumHash = Hashing.datumHash unitDatum - - constraints :: TxConstraints - constraints = Constraints.mustSatisfyAnyOf - [ Constraints.mustHashDatum wrongDatumHash unitDatum - , Constraints.mustHashDatum correctDatumHash unitDatum - ] - - lookups :: Lookups.ScriptLookups - lookups = mempty - - void $ mkUnbalancedTx lookups constraints diff --git a/examples/Schnorr.purs b/examples/Schnorr.purs index b4aa431b4c..f0228128e8 100644 --- a/examples/Schnorr.purs +++ b/examples/Schnorr.purs @@ -2,11 +2,23 @@ module Ctl.Examples.Schnorr (contract) where import Contract.Prelude -import Contract.Address (getNetworkId, validatorHashEnterpriseAddress) +import Cardano.Transaction.Builder + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) +import Cardano.Types (Credential(ScriptHashCredential)) +import Cardano.Types.Address (Address(EnterpriseAddress)) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash)) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionOutput (TransactionOutput(TransactionOutput)) +import Cardano.Types.TransactionUnspentOutput (_input, fromUtxoMap, toUtxoMap) +import Contract.Address (getNetworkId, mkAddress) import Contract.Crypto.Secp256k1.Schnorr - ( SchnorrPublicKey - , SchnorrSignature - , deriveSchnorrSecp256k1PublicKey + ( deriveSchnorrSecp256k1PublicKey , signSchnorrSecp256k1 ) import Contract.Crypto.Secp256k1.Utils (randomSecp256k1PrivateKey) @@ -16,24 +28,29 @@ import Contract.Numeric.BigNum as BigNum import Contract.PlutusData ( class ToData , PlutusData(Constr) - , Redeemer(Redeemer) + , RedeemerDatum(RedeemerDatum) , toData - , unitDatum ) import Contract.Prim.ByteArray (ByteArray, byteArrayFromIntArrayUnsafe) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (Validator(Validator), validatorHash) -import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptV2FromEnvelope) +import Contract.Scripts (Validator, validatorHash) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash , awaitTxConfirmed - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value +import Data.Array as Array +import Data.Lens (view) import Data.Map as Map -import Data.Set as Set +import Data.Newtype (unwrap) +import Noble.Secp256k1.Schnorr + ( SchnorrPublicKey + , SchnorrSignature + , unSchnorrPublicKey + , unSchnorrSignature + ) newtype SchnorrRedeemer = SchnorrRedeemer { msg :: ByteArray @@ -46,7 +63,10 @@ derive instance Newtype SchnorrRedeemer _ instance ToData SchnorrRedeemer where toData (SchnorrRedeemer { msg, sig, pk }) = Constr BigNum.zero - [ toData msg, toData sig, toData pk ] + [ toData $ unwrap msg + , toData $ unSchnorrSignature sig + , toData $ unSchnorrPublicKey pk + ] contract :: Contract Unit contract = do @@ -58,51 +78,55 @@ prepTest = do validator <- liftContractM "Caonnot get validator" getValidator let valHash = validatorHash validator - val = Value.lovelaceValueOf one - - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - - constraints :: Constraints.TxConstraints - constraints = Constraints.mustPayToScript valHash unitDatum - Constraints.DatumInline - val - txId <- submitTxFromConstraints lookups constraints - logInfo' $ "Submitted Schnorr test preparation tx: " <> show txId + val = Value.lovelaceValueOf BigNum.one + scriptAddress <- mkAddress + (wrap $ ScriptHashCredential valHash) + Nothing + tx <- submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: val + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + let txId = Transaction.hash tx + logInfo' $ "Submitted ECDSA test preparation tx: " <> show txId awaitTxConfirmed txId logInfo' $ "Transaction confirmed: " <> show txId - pure txId -- | Attempt to unlock one utxo using an ECDSA signature testVerification :: TransactionHash -> SchnorrRedeemer -> Contract TransactionHash testVerification txId ecdsaRed = do - let red = Redeemer $ toData ecdsaRed + let redeemer = RedeemerDatum $ toData ecdsaRed validator <- liftContractM "Can't get validator" getValidator let valHash = validatorHash validator - netId <- getNetworkId - valAddr <- liftContractM "cannot get validator address" - (validatorHashEnterpriseAddress netId valHash) - - scriptUtxos <- utxosAt valAddr - txIn <- liftContractM "No UTxOs found at validator address" - $ Set.toUnfoldable - $ Set.filter (unwrap >>> _.transactionId >>> eq txId) - $ Map.keys scriptUtxos - + networkId <- getNetworkId let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs - (Map.filterKeys ((unwrap >>> _.transactionId >>> eq txId)) scriptUtxos) + valAddr = EnterpriseAddress + { networkId, paymentCredential: wrap $ ScriptHashCredential valHash } - constraints :: Constraints.TxConstraints - constraints = Constraints.mustSpendScriptOutput txIn red - txId' <- submitTxFromConstraints lookups constraints - logInfo' $ "Submitted Schnorr test verification tx: " <> show txId' + scriptUtxos <- utxosAt valAddr + utxo <- liftContractM "No UTxOs found at validator address" + $ Array.head + $ Array.filter (view _input >>> unwrap >>> _.transactionId >>> eq txId) + $ fromUtxoMap scriptUtxos + + tx <- submitTxFromBuildPlan (toUtxoMap [ utxo ]) mempty + [ SpendOutput utxo $ Just + $ PlutusScriptOutput + (ScriptValue validator) + redeemer + $ Just + $ DatumValue + $ PlutusData.unit + ] + let txId' = Transaction.hash tx + logInfo' $ "Submitted ECDSA test verification tx: " <> show txId' awaitTxConfirmed txId' logInfo' $ "Transaction confirmed: " <> show txId' pure txId' @@ -124,8 +148,7 @@ testSchnorr txId = do getValidator :: Maybe Validator getValidator = do - Validator <$> - (plutusScriptV2FromEnvelope =<< decodeTextEnvelope validateSchnorrScript) + (plutusScriptFromEnvelope =<< decodeTextEnvelope validateSchnorrScript) validateSchnorrScript :: String validateSchnorrScript = diff --git a/examples/SendsToken.purs b/examples/SendsToken.purs index 7993c4e114..6b4efcff92 100644 --- a/examples/SendsToken.purs +++ b/examples/SendsToken.purs @@ -6,30 +6,53 @@ module Ctl.Examples.SendsToken (main, example, contract) where import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, MintAsset) + ) +import Cardano.Types + ( AssetName + , Credential(PubKeyHashCredential) + , PaymentCredential(PaymentCredential) + , PlutusScript + , ScriptHash + , StakeCredential(StakeCredential) + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Int as Int +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Contract.Address (mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (MintingPolicy) import Contract.Transaction ( TransactionHash , awaitTxConfirmed - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints as Constraints import Contract.Value (Value) import Contract.Value as Value import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) import Ctl.Examples.AlwaysMints (alwaysMintsPolicy) -import Ctl.Examples.Helpers - ( mkCurrencySymbol - , mkTokenName - , mustPayToPubKeyStakeAddress - ) as Helpers +import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head) +import Data.Map as Map main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -47,32 +70,39 @@ contract = do mintToken :: Contract TransactionHash mintToken = do - mp /\ value <- tokenValue - let - constraints :: Constraints.TxConstraints - constraints = Constraints.mustMintValue value + mp /\ sh /\ an /\ amount /\ _value <- tokenValue - lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp - - submitTxFromConstraints lookups constraints + tx <- submitTxFromBuildPlan Map.empty mempty + [ MintAsset + sh + an + amount + (PlutusScriptCredential (ScriptValue mp) RedeemerDatum.unit) + ] + pure $ Transaction.hash tx sendToken :: Contract TransactionHash sendToken = do pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes skh <- join <<< head <$> ownStakePubKeyHashes - _ /\ value <- tokenValue - let - constraints :: Constraints.TxConstraints - constraints = Helpers.mustPayToPubKeyStakeAddress pkh skh value - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + _ /\ _ /\ _ /\ _ /\ value <- tokenValue + address <- mkAddress (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) + tx <- submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address + , amount: value + , datum: Nothing + , scriptRef: Nothing + } + ] + pure $ Transaction.hash tx -tokenValue :: Contract (MintingPolicy /\ Value) +tokenValue + :: Contract (PlutusScript /\ ScriptHash /\ AssetName /\ Int.Int /\ Value) tokenValue = do - mp /\ cs <- Helpers.mkCurrencySymbol alwaysMintsPolicy - tn <- Helpers.mkTokenName "TheToken" - pure $ mp /\ Value.singleton cs tn one + mp <- alwaysMintsPolicy + let cs = PlutusScript.hash mp + an <- Helpers.mkAssetName "TheToken" + pure $ mp /\ cs /\ an /\ Int.fromInt 1 /\ Value.singleton cs an + (BigNum.fromInt 1) diff --git a/test/Wallet/Cip30/SignData.js b/examples/SignData.js similarity index 57% rename from test/Wallet/Cip30/SignData.js rename to examples/SignData.js index 7d99800c52..f681dc76a9 100644 --- a/test/Wallet/Cip30/SignData.js +++ b/examples/SignData.js @@ -1,16 +1,8 @@ -/* global BROWSER_RUNTIME */ +"use strict"; -let lib, csl; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@emurgo/cardano-message-signing-browser"); - csl = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@emurgo/cardano-message-signing-nodejs"); - csl = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} -// import gcWrapper from "@mlabs-haskell/csl-gc-wrapper"; -// lib = gcWrapper(lib); -// csl = gcWrapper(csl); +// eslint-disable-next-line no-unused-vars +import * as lib from "@mlabs-haskell/cardano-message-signing"; +import * as CSL from "@mlabs-haskell/cardano-serialization-lib-gc"; function opt_chain(maybe, obj) { const isNothing = x => x === null || x === undefined; @@ -25,42 +17,10 @@ function opt_chain(maybe, obj) { return isNothing(result) ? maybe.nothing : maybe.just(result); } -const fromBytes = name => bytes => () => { - return lib[name].from_bytes(bytes); -}; - -// ----------------------------------------------------------------------------- -// PublicKey -// ----------------------------------------------------------------------------- - -// verifySignature :: COSESign1 -> PublicKey -> CborBytes -> Effect Boolean -export function verifySignature(coseSign1) { - return publicKey => sigStructBytes => () => { - const signature = csl.Ed25519Signature.from_bytes(coseSign1.signature()); - return publicKey.verify(sigStructBytes, signature); - }; -} - -// ----------------------------------------------------------------------------- -// COSESign1 -// ----------------------------------------------------------------------------- - -// _fromBytesCoseSign1 :: CborBytes -> Effect COSESign1 -export const fromBytesCoseSign1 = fromBytes("COSESign1"); - -// getSignedData :: COSESign1 -> Effect CborBytes -export function getSignedData(coseSign1) { - return () => { - return coseSign1.signed_data(null, null).to_bytes(); - }; -} - -// getCoseSign1ProtectedHeaders :: COSESign1 -> HeaderMap const getCoseSign1ProtectedHeaders = coseSign1 => { return coseSign1.headers().protected().deserialized_headers(); }; -// getCoseSign1ProtectedHeaderAlg :: MaybeFfiHelper -> COSESign1 -> Maybe Int export function _getCoseSign1ProtectedHeaderAlg(maybe) { return coseSign1 => { const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); @@ -74,8 +34,6 @@ export function _getCoseSign1ProtectedHeaderAlg(maybe) { }; } -// _getCoseSign1ProtectedHeaderAddress -// :: MaybeFfiHelper -> COSESign1 -> Maybe CborBytes export function _getCoseSign1ProtectedHeaderAddress(maybe) { return coseSign1 => { const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); @@ -84,37 +42,18 @@ export function _getCoseSign1ProtectedHeaderAddress(maybe) { }; } -// _getCoseSign1ProtectedHeaderKid -// :: MaybeFfiHelper -> COSESign1 -> Maybe RawBytes -export function _getCoseSign1ProtectedHeaderKid(maybe) { - return coseSign1 => { - const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); - return opt_chain(maybe, protectedHeaders, "key_id"); - }; -} - -// ----------------------------------------------------------------------------- -// COSEKey -// ----------------------------------------------------------------------------- - -// _fromBytesCoseKey :: CborBytes -> Effect COSEKey -export const fromBytesCoseKey = fromBytes("COSEKey"); - -// _getCoseKeyHeaderKty :: MaybeFfiHelper -> COSEKey -> Maybe Int export function _getCoseKeyHeaderKty(maybe) { return coseKey => { return opt_chain(maybe, coseKey.key_type(), "as_int", "as_i32"); }; } -// _getCoseKeyHeaderAlg :: MaybeFfiHelper -> COSEKey -> Maybe Int export function _getCoseKeyHeaderAlg(maybe) { return coseKey => { return opt_chain(maybe, coseKey, "algorithm_id", "as_int", "as_i32"); }; } -// _getCoseKeyHeaderCrv :: MaybeFfiHelper -> COSEKey -> Maybe Int export function _getCoseKeyHeaderCrv(maybe) { return coseKey => { const cborValue = coseKey.header( @@ -126,7 +65,18 @@ export function _getCoseKeyHeaderCrv(maybe) { }; } -// _getCoseKeyHeaderX :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes +export function _getCoseSign1ProtectedHeaderKid(maybe) { + return coseSign1 => { + const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); + return opt_chain(maybe, protectedHeaders, "key_id"); + }; +} + +export function _getCoseKeyHeaderKid(maybe) { + return coseKey => { + return opt_chain(maybe, coseKey, "key_id"); + }; +} export function _getCoseKeyHeaderX(maybe) { return coseKey => { const cborValue = coseKey.header( @@ -137,10 +87,19 @@ export function _getCoseKeyHeaderX(maybe) { return opt_chain(maybe, cborValue, "as_bytes"); }; } - -// _getCoseKeyHeaderKid :: MaybeFfiHelper -> COSESign1 -> Maybe RawBytes -export function _getCoseKeyHeaderKid(maybe) { - return coseKey => { - return opt_chain(maybe, coseKey, "key_id"); +export function getSignedData(coseSign1) { + return () => { + return coseSign1.signed_data(null, null).to_bytes(); }; } +export function verifySignature(coseSign1) { + return publicKey => sigStructBytes => () => { + const signature = CSL.Ed25519Signature.from_bytes(coseSign1.signature()); + return publicKey.verify(sigStructBytes, signature); + }; +} +const fromBytes = name => bytes => () => { + return lib[name].from_bytes(bytes); +}; +export const fromBytesCoseKey = fromBytes("COSEKey"); +export const fromBytesCoseSign1 = fromBytes("COSESign1"); diff --git a/examples/SignData.purs b/examples/SignData.purs index dfa44dee1f..b32747731f 100644 --- a/examples/SignData.purs +++ b/examples/SignData.purs @@ -2,19 +2,34 @@ module Ctl.Examples.SignData (main, example, contract) where import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.AsCbor (encodeCbor) +import Cardano.MessageSigning (DataSignature) +import Cardano.Types (CborBytes, PublicKey, RawBytes) +import Cardano.Types.PublicKey as PublicKey +import Contract.Address (Address) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) -import Contract.Prim.ByteArray (RawBytes, rawBytesFromAscii) import Contract.Wallet (getChangeAddress, getRewardAddresses, signData) -import Ctl.Internal.Serialization.Address (Address) import Data.Array (head) as Array +import Data.ByteArray (byteArrayFromAscii) import Data.Maybe (fromJust) +import Effect.Aff (error) +import Effect.Class (class MonadEffect) +import Effect.Exception (throw, throwException) import Partial.Unsafe (unsafePartial) -import Test.Ctl.Wallet.Cip30.SignData (checkCip30SignDataResponse) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example = launchAff_ <<< flip runContract contract @@ -33,10 +48,147 @@ contract = do testSignDataWithAddress "rewardAddress" rewardAddress where payload :: RawBytes - payload = unsafePartial fromJust $ rawBytesFromAscii "Hello world!" + payload = wrap $ unsafePartial fromJust $ byteArrayFromAscii "Hello world!" testSignDataWithAddress :: String -> Address -> Contract Unit testSignDataWithAddress addressLabel address = do dataSignature <- signData address payload logInfo' $ "signData " <> addressLabel <> ": " <> show dataSignature void $ liftAff $ checkCip30SignDataResponse address dataSignature + +type DeserializedDataSignature = + { coseKey :: COSEKey + , coseSign1 :: COSESign1 + } + +checkCip30SignDataResponse + :: Address -> DataSignature -> Aff DeserializedDataSignature +checkCip30SignDataResponse address { key, signature } = do + coseSign1 <- liftEffect $ fromBytesCoseSign1 signature + coseKey <- liftEffect $ fromBytesCoseKey key + + checkCoseSign1ProtectedHeaders coseSign1 + checkCoseKeyHeaders coseKey + checkKidHeaders coseSign1 coseKey + liftEffect $ checkVerification coseSign1 coseKey + pure { coseKey, coseSign1 } + where + checkCoseSign1ProtectedHeaders :: COSESign1 -> Aff Unit + checkCoseSign1ProtectedHeaders coseSign1 = do + assertTrue "COSE_Sign1's alg (1) header must be set to EdDSA (-8)" + (getCoseSign1ProtectedHeaderAlg coseSign1 == Just (-8)) + + assertTrue "COSE_Sign1's \"address\" header must be set to address bytes" + ( getCoseSign1ProtectedHeaderAddress coseSign1 + == Just (encodeCbor address) + ) + + checkCoseKeyHeaders :: COSEKey -> Aff Unit + checkCoseKeyHeaders coseKey = do + assertTrue "COSE_Key's kty (1) header must be set to OKP (1)" + (getCoseKeyHeaderKty coseKey == Just 1) + + assertTrue "COSE_Key's alg (3) header must be set to EdDSA (-8)" + (getCoseKeyHeaderAlg coseKey == Just (-8)) + + assertTrue "COSE_Key's crv (-1) header must be set to Ed25519 (6)" + (getCoseKeyHeaderCrv coseKey == Just (6)) + + checkKidHeaders :: COSESign1 -> COSEKey -> Aff Unit + checkKidHeaders coseSign1 coseKey = + assertTrue + "COSE_Sign1's kid (4) and COSE_Key's kid (2) headers, if present, must \ + \be set to the same value" + (getCoseSign1ProtectedHeaderKid coseSign1 == getCoseKeyHeaderKid coseKey) + + checkVerification :: COSESign1 -> COSEKey -> Effect Unit + checkVerification coseSign1 coseKey = do + publicKey <- + errMaybe "COSE_Key's x (-2) header must be set to public key bytes" + $ getCoseKeyHeaderX coseKey + >>= PublicKey.fromRawBytes + sigStructBytes <- getSignedData coseSign1 + assertTrue "Signature verification failed" + =<< verifySignature coseSign1 publicKey sigStructBytes + +getCoseSign1ProtectedHeaderAlg :: COSESign1 -> Maybe Int +getCoseSign1ProtectedHeaderAlg = _getCoseSign1ProtectedHeaderAlg maybeFfiHelper + +getCoseSign1ProtectedHeaderAddress :: COSESign1 -> Maybe CborBytes +getCoseSign1ProtectedHeaderAddress = + _getCoseSign1ProtectedHeaderAddress maybeFfiHelper + +type MaybeFfiHelper = + { nothing :: forall (x :: Type). Maybe x + , just :: forall (x :: Type). x -> Maybe x + , from :: forall (x :: Type). x -> Maybe x -> x + } + +maybeFfiHelper :: MaybeFfiHelper +maybeFfiHelper = { nothing: Nothing, just: Just, from: fromMaybe } + +getCoseKeyHeaderKty :: COSEKey -> Maybe Int +getCoseKeyHeaderKty = _getCoseKeyHeaderKty maybeFfiHelper + +getCoseKeyHeaderAlg :: COSEKey -> Maybe Int +getCoseKeyHeaderAlg = _getCoseKeyHeaderAlg maybeFfiHelper + +getCoseKeyHeaderCrv :: COSEKey -> Maybe Int +getCoseKeyHeaderCrv = _getCoseKeyHeaderCrv maybeFfiHelper + +getCoseSign1ProtectedHeaderKid :: COSESign1 -> Maybe RawBytes +getCoseSign1ProtectedHeaderKid = _getCoseSign1ProtectedHeaderKid maybeFfiHelper + +getCoseKeyHeaderKid :: COSEKey -> Maybe RawBytes +getCoseKeyHeaderKid = _getCoseKeyHeaderKid maybeFfiHelper + +assertTrue + :: forall (m :: Type -> Type) + . Applicative m + => MonadEffect m + => String + -> Boolean + -> m Unit +assertTrue msg b = unless b $ liftEffect $ throwException $ error msg + +errMaybe + :: forall (m :: Type -> Type) (a :: Type) + . MonadEffect m + => String + -> Maybe a + -> m a +errMaybe msg = maybe (liftEffect $ throw msg) pure + +getCoseKeyHeaderX :: COSEKey -> Maybe RawBytes +getCoseKeyHeaderX = _getCoseKeyHeaderX maybeFfiHelper + +-------------------------------------------------------------------------------- +-- Foreign functions +-------------------------------------------------------------------------------- + +foreign import _getCoseSign1ProtectedHeaderAlg + :: MaybeFfiHelper -> COSESign1 -> Maybe Int + +foreign import _getCoseSign1ProtectedHeaderAddress + :: MaybeFfiHelper -> COSESign1 -> Maybe CborBytes + +foreign import _getCoseKeyHeaderX :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes +foreign import _getCoseKeyHeaderKty :: MaybeFfiHelper -> COSEKey -> Maybe Int +foreign import _getCoseKeyHeaderAlg :: MaybeFfiHelper -> COSEKey -> Maybe Int +foreign import _getCoseKeyHeaderCrv :: MaybeFfiHelper -> COSEKey -> Maybe Int +foreign import _getCoseSign1ProtectedHeaderKid + :: MaybeFfiHelper -> COSESign1 -> Maybe RawBytes + +foreign import _getCoseKeyHeaderKid + :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes + +foreign import getSignedData :: COSESign1 -> Effect CborBytes + +foreign import verifySignature + :: COSESign1 -> PublicKey -> CborBytes -> Effect Boolean + +foreign import fromBytesCoseSign1 :: CborBytes -> Effect COSESign1 +foreign import fromBytesCoseKey :: CborBytes -> Effect COSEKey + +foreign import data COSEKey :: Type +foreign import data COSESign1 :: Type diff --git a/examples/SignMultiple.purs b/examples/SignMultiple.purs index c5eb936e7d..047fd12dfa 100644 --- a/examples/SignMultiple.purs +++ b/examples/SignMultiple.purs @@ -5,7 +5,26 @@ module Ctl.Examples.SignMultiple (example, contract, main) where import Contract.Prelude -import Contract.Config (ContractParams, testnetNamiConfig) +import Cardano.Transaction.Builder (TransactionBuilderStep(Pay)) +import Cardano.Types + ( Credential(PubKeyHashCredential) + , OutputDatum(OutputDatumHash) + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , Transaction + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Contract.Address (mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo', logWarn') import Contract.Monad ( Contract @@ -14,19 +33,17 @@ import Contract.Monad , runContract , throwContractError ) -import Contract.ScriptLookups as Lookups +import Contract.Numeric.BigNum as BigNum import Contract.Transaction - ( BalancedSignedTransaction - , TransactionHash + ( TransactionHash , awaitTxConfirmed , awaitTxConfirmedWithTimeout + , buildTx , signTransaction , submit - , submitTxFromConstraints + , submitTxFromBuildPlan , withBalancedTxs ) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value (leq) import Contract.Value as Value import Contract.Wallet @@ -37,10 +54,16 @@ import Contract.Wallet import Control.Monad.Reader (asks) import Data.Array (head) import Data.Map (Map, filter) +import Data.Map as Map import Data.Set (Set) import Data.UInt (UInt) import Effect.Ref as Ref -import JS.BigInt as BigInt + +main :: Effect Unit +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } getLockedInputs :: Contract (Map TransactionHash (Set UInt)) @@ -48,38 +71,47 @@ getLockedInputs = do cache <- asks _.usedTxOuts liftEffect $ Ref.read $ unwrap cache -main :: Effect Unit -main = example testnetNamiConfig - contract :: Contract Unit contract = do logInfo' "Running Examples.SignMultiple" pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes - skh <- liftedM "Failed to get own SKH" $ join <<< head <$> - ownStakePubKeyHashes + skh <- liftedM "Failed to get own SKH" $ head <$> ownStakePubKeyHashes -- Early fail if not enough utxos present for 2 transactions unlessM hasSufficientUtxos do logWarn' "Insufficient Utxos for 2 transactions" createAdditionalUtxos - + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) let - constraints :: Constraints.TxConstraints - constraints = Constraints.mustPayToPubKeyAddress pkh skh - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - unbalancedTx0 <- mkUnbalancedTx lookups constraints - unbalancedTx1 <- mkUnbalancedTx lookups constraints - - txIds <- withBalancedTxs [ unbalancedTx0, unbalancedTx1 ] $ \balancedTxs -> do - locked <- getLockedInputs - logInfo' $ "Locked inputs inside bracket (should be nonempty): " - <> show locked - traverse (submitAndLog <=< signTransaction) balancedTxs + plan = + [ Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + + unbalancedTx0 <- buildTx plan + unbalancedTx1 <- buildTx plan + + txIds <- + withBalancedTxs + [ { transaction: unbalancedTx0 + , usedUtxos: Map.empty + , balancerConstraints: mempty + } + , { transaction: unbalancedTx1 + , usedUtxos: Map.empty + , balancerConstraints: mempty + } + ] $ \balancedTxs -> do + locked <- getLockedInputs + logInfo' $ "Locked inputs inside bracket (should be nonempty): " + <> show locked + traverse (submitAndLog <=< signTransaction) balancedTxs locked <- getLockedInputs logInfo' $ "Locked inputs after bracket (should be empty): " <> show locked @@ -94,7 +126,7 @@ contract = do where submitAndLog - :: BalancedSignedTransaction + :: Transaction -> Contract TransactionHash submitAndLog bsTx = do txId <- submit bsTx @@ -105,8 +137,8 @@ contract = do hasSufficientUtxos = do let -- 4 Ada: enough to cover 2 Ada transfer and fees - isUtxoValid u = (Value.lovelaceValueOf $ BigInt.fromInt 4_000_000) `leq` - (unwrap (unwrap u).output).amount + isUtxoValid u = (Value.lovelaceValueOf $ BigNum.fromInt 4_000_000) `leq` + (unwrap u).amount walletValidUtxos <- liftedM "Failed to get wallet Utxos" $ map (filter isUtxoValid) @@ -118,27 +150,29 @@ createAdditionalUtxos :: Contract Unit createAdditionalUtxos = do logInfo' "Creating additional UTxOs for SignMultiple example" pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes - skh <- liftedM "Failed to get own SKH" $ join <<< head <$> - ownStakePubKeyHashes - + skh <- liftedM "Failed to get own SKH" $ head <$> ownStakePubKeyHashes + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) let - constraints :: Constraints.TxConstraints - constraints = - Constraints.mustPayToPubKeyAddress pkh skh - ( Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - ) <> - Constraints.mustPayToPubKeyAddress pkh skh - ( Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - ) - - lookups :: Lookups.ScriptLookups - lookups = mempty - - txId <- submitTxFromConstraints lookups constraints - - awaitTxConfirmedWithTimeout (wrap 100.0) txId + plan = + [ Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + , Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + + tx <- submitTxFromBuildPlan Map.empty mempty plan + + awaitTxConfirmedWithTimeout (wrap 100.0) $ Transaction.hash tx logInfo' $ "Tx submitted successfully!" example :: ContractParams -> Effect Unit diff --git a/examples/TxChaining.purs b/examples/TxChaining.purs index 4e82e1fa0b..bcafe5c2f2 100644 --- a/examples/TxChaining.purs +++ b/examples/TxChaining.purs @@ -10,32 +10,50 @@ module Ctl.Examples.TxChaining import Contract.Prelude +import Cardano.Transaction.Builder (TransactionBuilderStep(Pay)) +import Cardano.Types + ( Credential(PubKeyHashCredential) + , OutputDatum(OutputDatumHash) + , PaymentCredential(PaymentCredential) + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Contract.Address (mkAddress) import Contract.BalanceTxConstraints - ( BalanceTxConstraintsBuilder + ( BalancerConstraints , mustUseAdditionalUtxos - ) as BalanceTxConstraints -import Contract.Config (ContractParams, testnetNamiConfig) + ) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName + ) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) -import Contract.ScriptLookups as Lookups import Contract.Transaction ( awaitTxConfirmed - , balanceTxWithConstraints + , balanceTx + , buildTx , createAdditionalUtxos , signTransaction , submit , withBalancedTx ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value as Value import Contract.Wallet (ownPaymentPubKeyHashes) import Data.Array (head) -import JS.BigInt as BigInt +import Data.Map as Map +import Effect.Exception (throw) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example cfg = launchAff_ do @@ -44,33 +62,34 @@ example cfg = launchAff_ do contract :: Contract Unit contract = do pkh <- liftedM "Failed to get PKH" $ head <$> ownPaymentPubKeyHashes + address <- mkAddress (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + Nothing let - constraints :: TxConstraints - constraints = - Constraints.mustPayToPubKey pkh - (Value.lovelaceValueOf $ BigInt.fromInt 1_000_000) - - lookups0 :: Lookups.ScriptLookups - lookups0 = mempty + plan = + [ Pay $ TransactionOutput + { address: address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 1_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] - unbalancedTx0 <- mkUnbalancedTx lookups0 constraints + unbalancedTx0 <- buildTx plan - withBalancedTx unbalancedTx0 \balancedTx0 -> do + withBalancedTx unbalancedTx0 Map.empty mempty \balancedTx0 -> do + logInfo' $ "balanced" balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 logInfo' $ "Additional utxos: " <> show additionalUtxos - + when (Map.isEmpty additionalUtxos) do + liftEffect $ throw "empty utxos" let - lookups1 :: Lookups.ScriptLookups - lookups1 = Lookups.unspentOutputs additionalUtxos - - balanceTxConstraints :: BalanceTxConstraints.BalanceTxConstraintsBuilder + balanceTxConstraints :: BalancerConstraints balanceTxConstraints = - BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - - unbalancedTx1 <- mkUnbalancedTx lookups1 constraints - balancedTx1 <- balanceTxWithConstraints unbalancedTx1 balanceTxConstraints + mustUseAdditionalUtxos additionalUtxos + unbalancedTx1 <- buildTx plan + balancedTx1 <- balanceTx unbalancedTx1 additionalUtxos balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 txId0 <- submit balancedSignedTx0 diff --git a/examples/Utxos.purs b/examples/Utxos.purs index 8b782c7110..780f5be22d 100644 --- a/examples/Utxos.purs +++ b/examples/Utxos.purs @@ -2,11 +2,32 @@ module Ctl.Examples.Utxos (main, example, contract) where import Contract.Prelude -import Contract.Address - ( PaymentPubKeyHash - , StakePubKeyHash +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, MintAsset) + ) +import Cardano.Types + ( Credential(PubKeyHashCredential) + , OutputDatum(OutputDatum, OutputDatumHash) + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.Int as Int +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Contract.Address (mkAddress) +import Contract.Config + ( ContractParams + , KnownWallet(Nami) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName ) -import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo, logInfo') import Contract.Monad ( Contract @@ -15,16 +36,12 @@ import Contract.Monad , liftedM , runContract ) -import Contract.PlutusData (Datum(Datum), PlutusData(Integer)) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (MintingPolicy(PlutusMintingPolicy)) +import Contract.PlutusData (PlutusData(Integer)) import Contract.Transaction ( ScriptRef(NativeScriptRef, PlutusScriptRef) , awaitTxConfirmed - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints (DatumPresence(DatumInline, DatumWitness)) -import Contract.TxConstraints as Constraints import Contract.Value (Value) import Contract.Value (lovelaceValueOf, singleton) as Value import Contract.Wallet @@ -32,17 +49,21 @@ import Contract.Wallet , ownPaymentPubKeyHash , ownStakePubKeyHash ) -import Ctl.Examples.Helpers (mkCurrencySymbol, mkTokenName) as Helpers +import Ctl.Examples.Helpers (mkAssetName) as Helpers import Ctl.Examples.PlutusV2.OneShotMinting (oneShotMintingPolicyScriptV2) import Data.Array (head) as Array import Data.Log.Tag (tag) -import Data.Map (toUnfoldable) as Map +import Data.Map (empty, toUnfoldable) as Map import JS.BigInt (fromInt) as BigInt +import Partial.Unsafe (unsafePartial) import Test.QuickCheck.Arbitrary (arbitrary) import Test.QuickCheck.Gen (randomSampleOne) main :: Effect Unit -main = example testnetNamiConfig +main = example $ testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName Nami) { cip95: false } + } example :: ContractParams -> Effect Unit example = launchAff_ <<< flip runContract contract @@ -52,10 +73,12 @@ contract = do logInfo' "Running Examples.Utxos" pkh <- liftedM "Failed to get own PKH" ownPaymentPubKeyHash skh <- ownStakePubKeyHash + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) datum <- liftEffect - $ Datum - <<< Integer + $ Integer <<< BigInt.fromInt <$> randomSampleOne arbitrary @@ -66,54 +89,43 @@ contract = do oneShotMintingPolicy <- oneShotMintingPolicyScriptV2 oref - mp0 /\ cs0 <- - Helpers.mkCurrencySymbol - (pure $ PlutusMintingPolicy $ oneShotMintingPolicy) - tn0 <- Helpers.mkTokenName "CTLNFT" + let cs0 = PlutusScript.hash oneShotMintingPolicy + tn0 <- Helpers.mkAssetName "CTLNFT" let plutusScriptRef = PlutusScriptRef oneShotMintingPolicy nativeScriptRef <- liftEffect $ NativeScriptRef <$> randomSampleOne arbitrary let adaValue :: Value - adaValue = Value.lovelaceValueOf (BigInt.fromInt 2_000_000) - - mintValue :: Value - mintValue = Value.singleton cs0 tn0 one - - constraints :: Constraints.TxConstraints - constraints = mconcat - [ Constraints.mustMintValue mintValue - , mustPayWithDatumAndScriptRef pkh skh datum DatumWitness plutusScriptRef - (mintValue <> adaValue) - , mustPayWithDatumAndScriptRef pkh skh datum DatumInline nativeScriptRef - adaValue + adaValue = Value.lovelaceValueOf (BigNum.fromInt 2_000_000) + + tokenValue = Value.singleton cs0 tn0 BigNum.one + + plan = + [ MintAsset + cs0 + tn0 + (Int.fromInt one) + ( PlutusScriptCredential (ScriptValue oneShotMintingPolicy) + RedeemerDatum.unit + ) + , Pay $ TransactionOutput + { address + , amount: unsafePartial $ tokenValue <> adaValue + , datum: Just $ OutputDatumHash $ hashPlutusData datum + , scriptRef: Just plutusScriptRef + } + , Pay $ TransactionOutput + { address + , amount: adaValue + , datum: Just $ OutputDatum datum + , scriptRef: Just nativeScriptRef + } ] - lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp0 <> Lookups.unspentOutputs utxos - - txHash <- submitTxFromConstraints lookups constraints - awaitTxConfirmed txHash + tx <- submitTxFromBuildPlan Map.empty mempty plan + awaitTxConfirmed $ Transaction.hash tx logInfo' "Tx submitted successfully!" utxos' <- liftedM "Failed to get UTxOs from wallet" getWalletUtxos logInfo (tag "utxos" $ show utxos') "Utxos after transaction confirmation:" - --------------------------------------------------------------------------------- --- Helpers --------------------------------------------------------------------------------- - -mustPayWithDatumAndScriptRef - :: forall (i :: Type) (o :: Type) - . PaymentPubKeyHash - -> Maybe StakePubKeyHash - -> Datum - -> DatumPresence - -> ScriptRef - -> Value - -> Constraints.TxConstraints -mustPayWithDatumAndScriptRef pkh Nothing = - Constraints.mustPayToPubKeyWithDatumAndScriptRef pkh -mustPayWithDatumAndScriptRef pkh (Just skh) = - Constraints.mustPayToPubKeyAddressWithDatumAndScriptRef pkh skh diff --git a/fixtures/test/blockfrost/getProtocolParameters/getProtocolParameters-2d2ce3159a465c84058d7eab67b1b345.json b/fixtures/test/blockfrost/getProtocolParameters/getProtocolParameters-2d2ce3159a465c84058d7eab67b1b345.json deleted file mode 100644 index d137e184ad..0000000000 --- a/fixtures/test/blockfrost/getProtocolParameters/getProtocolParameters-2d2ce3159a465c84058d7eab67b1b345.json +++ /dev/null @@ -1 +0,0 @@ -{"epoch":374,"min_fee_a":44,"min_fee_b":155381,"max_block_size":90112,"max_tx_size":16384,"max_block_header_size":1100,"key_deposit":"2000000","pool_deposit":"500000000","e_max":18,"n_opt":500,"a0":0.3,"rho":0.003,"tau":0.2,"decentralisation_param":0,"extra_entropy":null,"protocol_major_ver":8,"protocol_minor_ver":0,"min_utxo":"4310","min_pool_cost":"170000000","nonce":"e35763cef0b1b30b21d7cf61e8572e016fe3b71c0619a80d1d4850643357d047","cost_models":{"PlutusV1":{"addInteger-cpu-arguments-intercept":205665,"addInteger-cpu-arguments-slope":812,"addInteger-memory-arguments-intercept":1,"addInteger-memory-arguments-slope":1,"appendByteString-cpu-arguments-intercept":1000,"appendByteString-cpu-arguments-slope":571,"appendByteString-memory-arguments-intercept":0,"appendByteString-memory-arguments-slope":1,"appendString-cpu-arguments-intercept":1000,"appendString-cpu-arguments-slope":24177,"appendString-memory-arguments-intercept":4,"appendString-memory-arguments-slope":1,"bData-cpu-arguments":1000,"bData-memory-arguments":32,"blake2b_256-cpu-arguments-intercept":117366,"blake2b_256-cpu-arguments-slope":10475,"blake2b_256-memory-arguments":4,"cekApplyCost-exBudgetCPU":23000,"cekApplyCost-exBudgetMemory":100,"cekBuiltinCost-exBudgetCPU":23000,"cekBuiltinCost-exBudgetMemory":100,"cekConstCost-exBudgetCPU":23000,"cekConstCost-exBudgetMemory":100,"cekDelayCost-exBudgetCPU":23000,"cekDelayCost-exBudgetMemory":100,"cekForceCost-exBudgetCPU":23000,"cekForceCost-exBudgetMemory":100,"cekLamCost-exBudgetCPU":23000,"cekLamCost-exBudgetMemory":100,"cekStartupCost-exBudgetCPU":100,"cekStartupCost-exBudgetMemory":100,"cekVarCost-exBudgetCPU":23000,"cekVarCost-exBudgetMemory":100,"chooseData-cpu-arguments":19537,"chooseData-memory-arguments":32,"chooseList-cpu-arguments":175354,"chooseList-memory-arguments":32,"chooseUnit-cpu-arguments":46417,"chooseUnit-memory-arguments":4,"consByteString-cpu-arguments-intercept":221973,"consByteString-cpu-arguments-slope":511,"consByteString-memory-arguments-intercept":0,"consByteString-memory-arguments-slope":1,"constrData-cpu-arguments":89141,"constrData-memory-arguments":32,"decodeUtf8-cpu-arguments-intercept":497525,"decodeUtf8-cpu-arguments-slope":14068,"decodeUtf8-memory-arguments-intercept":4,"decodeUtf8-memory-arguments-slope":2,"divideInteger-cpu-arguments-constant":196500,"divideInteger-cpu-arguments-model-arguments-intercept":453240,"divideInteger-cpu-arguments-model-arguments-slope":220,"divideInteger-memory-arguments-intercept":0,"divideInteger-memory-arguments-minimum":1,"divideInteger-memory-arguments-slope":1,"encodeUtf8-cpu-arguments-intercept":1000,"encodeUtf8-cpu-arguments-slope":28662,"encodeUtf8-memory-arguments-intercept":4,"encodeUtf8-memory-arguments-slope":2,"equalsByteString-cpu-arguments-constant":245000,"equalsByteString-cpu-arguments-intercept":216773,"equalsByteString-cpu-arguments-slope":62,"equalsByteString-memory-arguments":1,"equalsData-cpu-arguments-intercept":1060367,"equalsData-cpu-arguments-slope":12586,"equalsData-memory-arguments":1,"equalsInteger-cpu-arguments-intercept":208512,"equalsInteger-cpu-arguments-slope":421,"equalsInteger-memory-arguments":1,"equalsString-cpu-arguments-constant":187000,"equalsString-cpu-arguments-intercept":1000,"equalsString-cpu-arguments-slope":52998,"equalsString-memory-arguments":1,"fstPair-cpu-arguments":80436,"fstPair-memory-arguments":32,"headList-cpu-arguments":43249,"headList-memory-arguments":32,"iData-cpu-arguments":1000,"iData-memory-arguments":32,"ifThenElse-cpu-arguments":80556,"ifThenElse-memory-arguments":1,"indexByteString-cpu-arguments":57667,"indexByteString-memory-arguments":4,"lengthOfByteString-cpu-arguments":1000,"lengthOfByteString-memory-arguments":10,"lessThanByteString-cpu-arguments-intercept":197145,"lessThanByteString-cpu-arguments-slope":156,"lessThanByteString-memory-arguments":1,"lessThanEqualsByteString-cpu-arguments-intercept":197145,"lessThanEqualsByteString-cpu-arguments-slope":156,"lessThanEqualsByteString-memory-arguments":1,"lessThanEqualsInteger-cpu-arguments-intercept":204924,"lessThanEqualsInteger-cpu-arguments-slope":473,"lessThanEqualsInteger-memory-arguments":1,"lessThanInteger-cpu-arguments-intercept":208896,"lessThanInteger-cpu-arguments-slope":511,"lessThanInteger-memory-arguments":1,"listData-cpu-arguments":52467,"listData-memory-arguments":32,"mapData-cpu-arguments":64832,"mapData-memory-arguments":32,"mkCons-cpu-arguments":65493,"mkCons-memory-arguments":32,"mkNilData-cpu-arguments":22558,"mkNilData-memory-arguments":32,"mkNilPairData-cpu-arguments":16563,"mkNilPairData-memory-arguments":32,"mkPairData-cpu-arguments":76511,"mkPairData-memory-arguments":32,"modInteger-cpu-arguments-constant":196500,"modInteger-cpu-arguments-model-arguments-intercept":453240,"modInteger-cpu-arguments-model-arguments-slope":220,"modInteger-memory-arguments-intercept":0,"modInteger-memory-arguments-minimum":1,"modInteger-memory-arguments-slope":1,"multiplyInteger-cpu-arguments-intercept":69522,"multiplyInteger-cpu-arguments-slope":11687,"multiplyInteger-memory-arguments-intercept":0,"multiplyInteger-memory-arguments-slope":1,"nullList-cpu-arguments":60091,"nullList-memory-arguments":32,"quotientInteger-cpu-arguments-constant":196500,"quotientInteger-cpu-arguments-model-arguments-intercept":453240,"quotientInteger-cpu-arguments-model-arguments-slope":220,"quotientInteger-memory-arguments-intercept":0,"quotientInteger-memory-arguments-minimum":1,"quotientInteger-memory-arguments-slope":1,"remainderInteger-cpu-arguments-constant":196500,"remainderInteger-cpu-arguments-model-arguments-intercept":453240,"remainderInteger-cpu-arguments-model-arguments-slope":220,"remainderInteger-memory-arguments-intercept":0,"remainderInteger-memory-arguments-minimum":1,"remainderInteger-memory-arguments-slope":1,"sha2_256-cpu-arguments-intercept":806990,"sha2_256-cpu-arguments-slope":30482,"sha2_256-memory-arguments":4,"sha3_256-cpu-arguments-intercept":1927926,"sha3_256-cpu-arguments-slope":82523,"sha3_256-memory-arguments":4,"sliceByteString-cpu-arguments-intercept":265318,"sliceByteString-cpu-arguments-slope":0,"sliceByteString-memory-arguments-intercept":4,"sliceByteString-memory-arguments-slope":0,"sndPair-cpu-arguments":85931,"sndPair-memory-arguments":32,"subtractInteger-cpu-arguments-intercept":205665,"subtractInteger-cpu-arguments-slope":812,"subtractInteger-memory-arguments-intercept":1,"subtractInteger-memory-arguments-slope":1,"tailList-cpu-arguments":41182,"tailList-memory-arguments":32,"trace-cpu-arguments":212342,"trace-memory-arguments":32,"unBData-cpu-arguments":31220,"unBData-memory-arguments":32,"unConstrData-cpu-arguments":32696,"unConstrData-memory-arguments":32,"unIData-cpu-arguments":43357,"unIData-memory-arguments":32,"unListData-cpu-arguments":32247,"unListData-memory-arguments":32,"unMapData-cpu-arguments":38314,"unMapData-memory-arguments":32,"verifyEd25519Signature-cpu-arguments-intercept":57996947,"verifyEd25519Signature-cpu-arguments-slope":18975,"verifyEd25519Signature-memory-arguments":10},"PlutusV2":{"addInteger-cpu-arguments-intercept":205665,"addInteger-cpu-arguments-slope":812,"addInteger-memory-arguments-intercept":1,"addInteger-memory-arguments-slope":1,"appendByteString-cpu-arguments-intercept":1000,"appendByteString-cpu-arguments-slope":571,"appendByteString-memory-arguments-intercept":0,"appendByteString-memory-arguments-slope":1,"appendString-cpu-arguments-intercept":1000,"appendString-cpu-arguments-slope":24177,"appendString-memory-arguments-intercept":4,"appendString-memory-arguments-slope":1,"bData-cpu-arguments":1000,"bData-memory-arguments":32,"blake2b_256-cpu-arguments-intercept":117366,"blake2b_256-cpu-arguments-slope":10475,"blake2b_256-memory-arguments":4,"cekApplyCost-exBudgetCPU":23000,"cekApplyCost-exBudgetMemory":100,"cekBuiltinCost-exBudgetCPU":23000,"cekBuiltinCost-exBudgetMemory":100,"cekConstCost-exBudgetCPU":23000,"cekConstCost-exBudgetMemory":100,"cekDelayCost-exBudgetCPU":23000,"cekDelayCost-exBudgetMemory":100,"cekForceCost-exBudgetCPU":23000,"cekForceCost-exBudgetMemory":100,"cekLamCost-exBudgetCPU":23000,"cekLamCost-exBudgetMemory":100,"cekStartupCost-exBudgetCPU":100,"cekStartupCost-exBudgetMemory":100,"cekVarCost-exBudgetCPU":23000,"cekVarCost-exBudgetMemory":100,"chooseData-cpu-arguments":19537,"chooseData-memory-arguments":32,"chooseList-cpu-arguments":175354,"chooseList-memory-arguments":32,"chooseUnit-cpu-arguments":46417,"chooseUnit-memory-arguments":4,"consByteString-cpu-arguments-intercept":221973,"consByteString-cpu-arguments-slope":511,"consByteString-memory-arguments-intercept":0,"consByteString-memory-arguments-slope":1,"constrData-cpu-arguments":89141,"constrData-memory-arguments":32,"decodeUtf8-cpu-arguments-intercept":497525,"decodeUtf8-cpu-arguments-slope":14068,"decodeUtf8-memory-arguments-intercept":4,"decodeUtf8-memory-arguments-slope":2,"divideInteger-cpu-arguments-constant":196500,"divideInteger-cpu-arguments-model-arguments-intercept":453240,"divideInteger-cpu-arguments-model-arguments-slope":220,"divideInteger-memory-arguments-intercept":0,"divideInteger-memory-arguments-minimum":1,"divideInteger-memory-arguments-slope":1,"encodeUtf8-cpu-arguments-intercept":1000,"encodeUtf8-cpu-arguments-slope":28662,"encodeUtf8-memory-arguments-intercept":4,"encodeUtf8-memory-arguments-slope":2,"equalsByteString-cpu-arguments-constant":245000,"equalsByteString-cpu-arguments-intercept":216773,"equalsByteString-cpu-arguments-slope":62,"equalsByteString-memory-arguments":1,"equalsData-cpu-arguments-intercept":1060367,"equalsData-cpu-arguments-slope":12586,"equalsData-memory-arguments":1,"equalsInteger-cpu-arguments-intercept":208512,"equalsInteger-cpu-arguments-slope":421,"equalsInteger-memory-arguments":1,"equalsString-cpu-arguments-constant":187000,"equalsString-cpu-arguments-intercept":1000,"equalsString-cpu-arguments-slope":52998,"equalsString-memory-arguments":1,"fstPair-cpu-arguments":80436,"fstPair-memory-arguments":32,"headList-cpu-arguments":43249,"headList-memory-arguments":32,"iData-cpu-arguments":1000,"iData-memory-arguments":32,"ifThenElse-cpu-arguments":80556,"ifThenElse-memory-arguments":1,"indexByteString-cpu-arguments":57667,"indexByteString-memory-arguments":4,"lengthOfByteString-cpu-arguments":1000,"lengthOfByteString-memory-arguments":10,"lessThanByteString-cpu-arguments-intercept":197145,"lessThanByteString-cpu-arguments-slope":156,"lessThanByteString-memory-arguments":1,"lessThanEqualsByteString-cpu-arguments-intercept":197145,"lessThanEqualsByteString-cpu-arguments-slope":156,"lessThanEqualsByteString-memory-arguments":1,"lessThanEqualsInteger-cpu-arguments-intercept":204924,"lessThanEqualsInteger-cpu-arguments-slope":473,"lessThanEqualsInteger-memory-arguments":1,"lessThanInteger-cpu-arguments-intercept":208896,"lessThanInteger-cpu-arguments-slope":511,"lessThanInteger-memory-arguments":1,"listData-cpu-arguments":52467,"listData-memory-arguments":32,"mapData-cpu-arguments":64832,"mapData-memory-arguments":32,"mkCons-cpu-arguments":65493,"mkCons-memory-arguments":32,"mkNilData-cpu-arguments":22558,"mkNilData-memory-arguments":32,"mkNilPairData-cpu-arguments":16563,"mkNilPairData-memory-arguments":32,"mkPairData-cpu-arguments":76511,"mkPairData-memory-arguments":32,"modInteger-cpu-arguments-constant":196500,"modInteger-cpu-arguments-model-arguments-intercept":453240,"modInteger-cpu-arguments-model-arguments-slope":220,"modInteger-memory-arguments-intercept":0,"modInteger-memory-arguments-minimum":1,"modInteger-memory-arguments-slope":1,"multiplyInteger-cpu-arguments-intercept":69522,"multiplyInteger-cpu-arguments-slope":11687,"multiplyInteger-memory-arguments-intercept":0,"multiplyInteger-memory-arguments-slope":1,"nullList-cpu-arguments":60091,"nullList-memory-arguments":32,"quotientInteger-cpu-arguments-constant":196500,"quotientInteger-cpu-arguments-model-arguments-intercept":453240,"quotientInteger-cpu-arguments-model-arguments-slope":220,"quotientInteger-memory-arguments-intercept":0,"quotientInteger-memory-arguments-minimum":1,"quotientInteger-memory-arguments-slope":1,"remainderInteger-cpu-arguments-constant":196500,"remainderInteger-cpu-arguments-model-arguments-intercept":453240,"remainderInteger-cpu-arguments-model-arguments-slope":220,"remainderInteger-memory-arguments-intercept":0,"remainderInteger-memory-arguments-minimum":1,"remainderInteger-memory-arguments-slope":1,"serialiseData-cpu-arguments-intercept":1159724,"serialiseData-cpu-arguments-slope":392670,"serialiseData-memory-arguments-intercept":0,"serialiseData-memory-arguments-slope":2,"sha2_256-cpu-arguments-intercept":806990,"sha2_256-cpu-arguments-slope":30482,"sha2_256-memory-arguments":4,"sha3_256-cpu-arguments-intercept":1927926,"sha3_256-cpu-arguments-slope":82523,"sha3_256-memory-arguments":4,"sliceByteString-cpu-arguments-intercept":265318,"sliceByteString-cpu-arguments-slope":0,"sliceByteString-memory-arguments-intercept":4,"sliceByteString-memory-arguments-slope":0,"sndPair-cpu-arguments":85931,"sndPair-memory-arguments":32,"subtractInteger-cpu-arguments-intercept":205665,"subtractInteger-cpu-arguments-slope":812,"subtractInteger-memory-arguments-intercept":1,"subtractInteger-memory-arguments-slope":1,"tailList-cpu-arguments":41182,"tailList-memory-arguments":32,"trace-cpu-arguments":212342,"trace-memory-arguments":32,"unBData-cpu-arguments":31220,"unBData-memory-arguments":32,"unConstrData-cpu-arguments":32696,"unConstrData-memory-arguments":32,"unIData-cpu-arguments":43357,"unIData-memory-arguments":32,"unListData-cpu-arguments":32247,"unListData-memory-arguments":32,"unMapData-cpu-arguments":38314,"unMapData-memory-arguments":32,"verifyEcdsaSecp256k1Signature-cpu-arguments":35892428,"verifyEcdsaSecp256k1Signature-memory-arguments":10,"verifyEd25519Signature-cpu-arguments-intercept":57996947,"verifyEd25519Signature-cpu-arguments-slope":18975,"verifyEd25519Signature-memory-arguments":10,"verifySchnorrSecp256k1Signature-cpu-arguments-intercept":38887044,"verifySchnorrSecp256k1Signature-cpu-arguments-slope":32947,"verifySchnorrSecp256k1Signature-memory-arguments":10}},"price_mem":0.0577,"price_step":0.0000721,"max_tx_ex_mem":"14000000","max_tx_ex_steps":"10000000000","max_block_ex_mem":"62000000","max_block_ex_steps":"20000000000","max_val_size":"5000","collateral_percent":150,"max_collateral_inputs":3,"coins_per_utxo_size":"4310","coins_per_utxo_word":"4310"} \ No newline at end of file diff --git a/fixtures/test/blockfrost/getProtocolParameters/getProtocolParameters-6ac22050d53def4302608de2fa695f02.json b/fixtures/test/blockfrost/getProtocolParameters/getProtocolParameters-6ac22050d53def4302608de2fa695f02.json new file mode 100644 index 0000000000..6643a5d830 --- /dev/null +++ b/fixtures/test/blockfrost/getProtocolParameters/getProtocolParameters-6ac22050d53def4302608de2fa695f02.json @@ -0,0 +1 @@ +{"epoch":406,"min_fee_a":44,"min_fee_b":155381,"max_block_size":90112,"max_tx_size":16384,"max_block_header_size":1100,"key_deposit":"2000000","pool_deposit":"500000000","e_max":18,"n_opt":500,"a0":0.3,"rho":0.003,"tau":0.2,"decentralisation_param":0,"extra_entropy":null,"protocol_major_ver":10,"protocol_minor_ver":0,"min_utxo":"4310","min_pool_cost":"340000000","nonce":"20a149dea03f4a8ee32d30db9219ee61628ccefdf0be517f96302bef35bd4cd7","cost_models":{"PlutusV1":{"addInteger-cpu-arguments-intercept":205665,"addInteger-cpu-arguments-slope":812,"addInteger-memory-arguments-intercept":1,"addInteger-memory-arguments-slope":1,"appendByteString-cpu-arguments-intercept":1000,"appendByteString-cpu-arguments-slope":571,"appendByteString-memory-arguments-intercept":0,"appendByteString-memory-arguments-slope":1,"appendString-cpu-arguments-intercept":1000,"appendString-cpu-arguments-slope":24177,"appendString-memory-arguments-intercept":4,"appendString-memory-arguments-slope":1,"bData-cpu-arguments":1000,"bData-memory-arguments":32,"blake2b_256-cpu-arguments-intercept":117366,"blake2b_256-cpu-arguments-slope":10475,"blake2b_256-memory-arguments":4,"cekApplyCost-exBudgetCPU":23000,"cekApplyCost-exBudgetMemory":100,"cekBuiltinCost-exBudgetCPU":23000,"cekBuiltinCost-exBudgetMemory":100,"cekConstCost-exBudgetCPU":23000,"cekConstCost-exBudgetMemory":100,"cekDelayCost-exBudgetCPU":23000,"cekDelayCost-exBudgetMemory":100,"cekForceCost-exBudgetCPU":23000,"cekForceCost-exBudgetMemory":100,"cekLamCost-exBudgetCPU":23000,"cekLamCost-exBudgetMemory":100,"cekStartupCost-exBudgetCPU":100,"cekStartupCost-exBudgetMemory":100,"cekVarCost-exBudgetCPU":23000,"cekVarCost-exBudgetMemory":100,"chooseData-cpu-arguments":19537,"chooseData-memory-arguments":32,"chooseList-cpu-arguments":175354,"chooseList-memory-arguments":32,"chooseUnit-cpu-arguments":46417,"chooseUnit-memory-arguments":4,"consByteString-cpu-arguments-intercept":221973,"consByteString-cpu-arguments-slope":511,"consByteString-memory-arguments-intercept":0,"consByteString-memory-arguments-slope":1,"constrData-cpu-arguments":89141,"constrData-memory-arguments":32,"decodeUtf8-cpu-arguments-intercept":497525,"decodeUtf8-cpu-arguments-slope":14068,"decodeUtf8-memory-arguments-intercept":4,"decodeUtf8-memory-arguments-slope":2,"divideInteger-cpu-arguments-constant":196500,"divideInteger-cpu-arguments-model-arguments-intercept":453240,"divideInteger-cpu-arguments-model-arguments-slope":220,"divideInteger-memory-arguments-intercept":0,"divideInteger-memory-arguments-minimum":1,"divideInteger-memory-arguments-slope":1,"encodeUtf8-cpu-arguments-intercept":1000,"encodeUtf8-cpu-arguments-slope":28662,"encodeUtf8-memory-arguments-intercept":4,"encodeUtf8-memory-arguments-slope":2,"equalsByteString-cpu-arguments-constant":245000,"equalsByteString-cpu-arguments-intercept":216773,"equalsByteString-cpu-arguments-slope":62,"equalsByteString-memory-arguments":1,"equalsData-cpu-arguments-intercept":1060367,"equalsData-cpu-arguments-slope":12586,"equalsData-memory-arguments":1,"equalsInteger-cpu-arguments-intercept":208512,"equalsInteger-cpu-arguments-slope":421,"equalsInteger-memory-arguments":1,"equalsString-cpu-arguments-constant":187000,"equalsString-cpu-arguments-intercept":1000,"equalsString-cpu-arguments-slope":52998,"equalsString-memory-arguments":1,"fstPair-cpu-arguments":80436,"fstPair-memory-arguments":32,"headList-cpu-arguments":43249,"headList-memory-arguments":32,"iData-cpu-arguments":1000,"iData-memory-arguments":32,"ifThenElse-cpu-arguments":80556,"ifThenElse-memory-arguments":1,"indexByteString-cpu-arguments":57667,"indexByteString-memory-arguments":4,"lengthOfByteString-cpu-arguments":1000,"lengthOfByteString-memory-arguments":10,"lessThanByteString-cpu-arguments-intercept":197145,"lessThanByteString-cpu-arguments-slope":156,"lessThanByteString-memory-arguments":1,"lessThanEqualsByteString-cpu-arguments-intercept":197145,"lessThanEqualsByteString-cpu-arguments-slope":156,"lessThanEqualsByteString-memory-arguments":1,"lessThanEqualsInteger-cpu-arguments-intercept":204924,"lessThanEqualsInteger-cpu-arguments-slope":473,"lessThanEqualsInteger-memory-arguments":1,"lessThanInteger-cpu-arguments-intercept":208896,"lessThanInteger-cpu-arguments-slope":511,"lessThanInteger-memory-arguments":1,"listData-cpu-arguments":52467,"listData-memory-arguments":32,"mapData-cpu-arguments":64832,"mapData-memory-arguments":32,"mkCons-cpu-arguments":65493,"mkCons-memory-arguments":32,"mkNilData-cpu-arguments":22558,"mkNilData-memory-arguments":32,"mkNilPairData-cpu-arguments":16563,"mkNilPairData-memory-arguments":32,"mkPairData-cpu-arguments":76511,"mkPairData-memory-arguments":32,"modInteger-cpu-arguments-constant":196500,"modInteger-cpu-arguments-model-arguments-intercept":453240,"modInteger-cpu-arguments-model-arguments-slope":220,"modInteger-memory-arguments-intercept":0,"modInteger-memory-arguments-minimum":1,"modInteger-memory-arguments-slope":1,"multiplyInteger-cpu-arguments-intercept":69522,"multiplyInteger-cpu-arguments-slope":11687,"multiplyInteger-memory-arguments-intercept":0,"multiplyInteger-memory-arguments-slope":1,"nullList-cpu-arguments":60091,"nullList-memory-arguments":32,"quotientInteger-cpu-arguments-constant":196500,"quotientInteger-cpu-arguments-model-arguments-intercept":453240,"quotientInteger-cpu-arguments-model-arguments-slope":220,"quotientInteger-memory-arguments-intercept":0,"quotientInteger-memory-arguments-minimum":1,"quotientInteger-memory-arguments-slope":1,"remainderInteger-cpu-arguments-constant":196500,"remainderInteger-cpu-arguments-model-arguments-intercept":453240,"remainderInteger-cpu-arguments-model-arguments-slope":220,"remainderInteger-memory-arguments-intercept":0,"remainderInteger-memory-arguments-minimum":1,"remainderInteger-memory-arguments-slope":1,"sha2_256-cpu-arguments-intercept":806990,"sha2_256-cpu-arguments-slope":30482,"sha2_256-memory-arguments":4,"sha3_256-cpu-arguments-intercept":1927926,"sha3_256-cpu-arguments-slope":82523,"sha3_256-memory-arguments":4,"sliceByteString-cpu-arguments-intercept":265318,"sliceByteString-cpu-arguments-slope":0,"sliceByteString-memory-arguments-intercept":4,"sliceByteString-memory-arguments-slope":0,"sndPair-cpu-arguments":85931,"sndPair-memory-arguments":32,"subtractInteger-cpu-arguments-intercept":205665,"subtractInteger-cpu-arguments-slope":812,"subtractInteger-memory-arguments-intercept":1,"subtractInteger-memory-arguments-slope":1,"tailList-cpu-arguments":41182,"tailList-memory-arguments":32,"trace-cpu-arguments":212342,"trace-memory-arguments":32,"unBData-cpu-arguments":31220,"unBData-memory-arguments":32,"unConstrData-cpu-arguments":32696,"unConstrData-memory-arguments":32,"unIData-cpu-arguments":43357,"unIData-memory-arguments":32,"unListData-cpu-arguments":32247,"unListData-memory-arguments":32,"unMapData-cpu-arguments":38314,"unMapData-memory-arguments":32,"verifyEd25519Signature-cpu-arguments-intercept":57996947,"verifyEd25519Signature-cpu-arguments-slope":18975,"verifyEd25519Signature-memory-arguments":10},"PlutusV2":{"addInteger-cpu-arguments-intercept":205665,"addInteger-cpu-arguments-slope":812,"addInteger-memory-arguments-intercept":1,"addInteger-memory-arguments-slope":1,"appendByteString-cpu-arguments-intercept":1000,"appendByteString-cpu-arguments-slope":571,"appendByteString-memory-arguments-intercept":0,"appendByteString-memory-arguments-slope":1,"appendString-cpu-arguments-intercept":1000,"appendString-cpu-arguments-slope":24177,"appendString-memory-arguments-intercept":4,"appendString-memory-arguments-slope":1,"bData-cpu-arguments":1000,"bData-memory-arguments":32,"blake2b_256-cpu-arguments-intercept":117366,"blake2b_256-cpu-arguments-slope":10475,"blake2b_256-memory-arguments":4,"cekApplyCost-exBudgetCPU":23000,"cekApplyCost-exBudgetMemory":100,"cekBuiltinCost-exBudgetCPU":23000,"cekBuiltinCost-exBudgetMemory":100,"cekConstCost-exBudgetCPU":23000,"cekConstCost-exBudgetMemory":100,"cekDelayCost-exBudgetCPU":23000,"cekDelayCost-exBudgetMemory":100,"cekForceCost-exBudgetCPU":23000,"cekForceCost-exBudgetMemory":100,"cekLamCost-exBudgetCPU":23000,"cekLamCost-exBudgetMemory":100,"cekStartupCost-exBudgetCPU":100,"cekStartupCost-exBudgetMemory":100,"cekVarCost-exBudgetCPU":23000,"cekVarCost-exBudgetMemory":100,"chooseData-cpu-arguments":19537,"chooseData-memory-arguments":32,"chooseList-cpu-arguments":175354,"chooseList-memory-arguments":32,"chooseUnit-cpu-arguments":46417,"chooseUnit-memory-arguments":4,"consByteString-cpu-arguments-intercept":221973,"consByteString-cpu-arguments-slope":511,"consByteString-memory-arguments-intercept":0,"consByteString-memory-arguments-slope":1,"constrData-cpu-arguments":89141,"constrData-memory-arguments":32,"decodeUtf8-cpu-arguments-intercept":497525,"decodeUtf8-cpu-arguments-slope":14068,"decodeUtf8-memory-arguments-intercept":4,"decodeUtf8-memory-arguments-slope":2,"divideInteger-cpu-arguments-constant":196500,"divideInteger-cpu-arguments-model-arguments-intercept":453240,"divideInteger-cpu-arguments-model-arguments-slope":220,"divideInteger-memory-arguments-intercept":0,"divideInteger-memory-arguments-minimum":1,"divideInteger-memory-arguments-slope":1,"encodeUtf8-cpu-arguments-intercept":1000,"encodeUtf8-cpu-arguments-slope":28662,"encodeUtf8-memory-arguments-intercept":4,"encodeUtf8-memory-arguments-slope":2,"equalsByteString-cpu-arguments-constant":245000,"equalsByteString-cpu-arguments-intercept":216773,"equalsByteString-cpu-arguments-slope":62,"equalsByteString-memory-arguments":1,"equalsData-cpu-arguments-intercept":1060367,"equalsData-cpu-arguments-slope":12586,"equalsData-memory-arguments":1,"equalsInteger-cpu-arguments-intercept":208512,"equalsInteger-cpu-arguments-slope":421,"equalsInteger-memory-arguments":1,"equalsString-cpu-arguments-constant":187000,"equalsString-cpu-arguments-intercept":1000,"equalsString-cpu-arguments-slope":52998,"equalsString-memory-arguments":1,"fstPair-cpu-arguments":80436,"fstPair-memory-arguments":32,"headList-cpu-arguments":43249,"headList-memory-arguments":32,"iData-cpu-arguments":1000,"iData-memory-arguments":32,"ifThenElse-cpu-arguments":80556,"ifThenElse-memory-arguments":1,"indexByteString-cpu-arguments":57667,"indexByteString-memory-arguments":4,"lengthOfByteString-cpu-arguments":1000,"lengthOfByteString-memory-arguments":10,"lessThanByteString-cpu-arguments-intercept":197145,"lessThanByteString-cpu-arguments-slope":156,"lessThanByteString-memory-arguments":1,"lessThanEqualsByteString-cpu-arguments-intercept":197145,"lessThanEqualsByteString-cpu-arguments-slope":156,"lessThanEqualsByteString-memory-arguments":1,"lessThanEqualsInteger-cpu-arguments-intercept":204924,"lessThanEqualsInteger-cpu-arguments-slope":473,"lessThanEqualsInteger-memory-arguments":1,"lessThanInteger-cpu-arguments-intercept":208896,"lessThanInteger-cpu-arguments-slope":511,"lessThanInteger-memory-arguments":1,"listData-cpu-arguments":52467,"listData-memory-arguments":32,"mapData-cpu-arguments":64832,"mapData-memory-arguments":32,"mkCons-cpu-arguments":65493,"mkCons-memory-arguments":32,"mkNilData-cpu-arguments":22558,"mkNilData-memory-arguments":32,"mkNilPairData-cpu-arguments":16563,"mkNilPairData-memory-arguments":32,"mkPairData-cpu-arguments":76511,"mkPairData-memory-arguments":32,"modInteger-cpu-arguments-constant":196500,"modInteger-cpu-arguments-model-arguments-intercept":453240,"modInteger-cpu-arguments-model-arguments-slope":220,"modInteger-memory-arguments-intercept":0,"modInteger-memory-arguments-minimum":1,"modInteger-memory-arguments-slope":1,"multiplyInteger-cpu-arguments-intercept":69522,"multiplyInteger-cpu-arguments-slope":11687,"multiplyInteger-memory-arguments-intercept":0,"multiplyInteger-memory-arguments-slope":1,"nullList-cpu-arguments":60091,"nullList-memory-arguments":32,"quotientInteger-cpu-arguments-constant":196500,"quotientInteger-cpu-arguments-model-arguments-intercept":453240,"quotientInteger-cpu-arguments-model-arguments-slope":220,"quotientInteger-memory-arguments-intercept":0,"quotientInteger-memory-arguments-minimum":1,"quotientInteger-memory-arguments-slope":1,"remainderInteger-cpu-arguments-constant":196500,"remainderInteger-cpu-arguments-model-arguments-intercept":453240,"remainderInteger-cpu-arguments-model-arguments-slope":220,"remainderInteger-memory-arguments-intercept":0,"remainderInteger-memory-arguments-minimum":1,"remainderInteger-memory-arguments-slope":1,"serialiseData-cpu-arguments-intercept":1159724,"serialiseData-cpu-arguments-slope":392670,"serialiseData-memory-arguments-intercept":0,"serialiseData-memory-arguments-slope":2,"sha2_256-cpu-arguments-intercept":806990,"sha2_256-cpu-arguments-slope":30482,"sha2_256-memory-arguments":4,"sha3_256-cpu-arguments-intercept":1927926,"sha3_256-cpu-arguments-slope":82523,"sha3_256-memory-arguments":4,"sliceByteString-cpu-arguments-intercept":265318,"sliceByteString-cpu-arguments-slope":0,"sliceByteString-memory-arguments-intercept":4,"sliceByteString-memory-arguments-slope":0,"sndPair-cpu-arguments":85931,"sndPair-memory-arguments":32,"subtractInteger-cpu-arguments-intercept":205665,"subtractInteger-cpu-arguments-slope":812,"subtractInteger-memory-arguments-intercept":1,"subtractInteger-memory-arguments-slope":1,"tailList-cpu-arguments":41182,"tailList-memory-arguments":32,"trace-cpu-arguments":212342,"trace-memory-arguments":32,"unBData-cpu-arguments":31220,"unBData-memory-arguments":32,"unConstrData-cpu-arguments":32696,"unConstrData-memory-arguments":32,"unIData-cpu-arguments":43357,"unIData-memory-arguments":32,"unListData-cpu-arguments":32247,"unListData-memory-arguments":32,"unMapData-cpu-arguments":38314,"unMapData-memory-arguments":32,"verifyEcdsaSecp256k1Signature-cpu-arguments":35892428,"verifyEcdsaSecp256k1Signature-memory-arguments":10,"verifyEd25519Signature-cpu-arguments-intercept":57996947,"verifyEd25519Signature-cpu-arguments-slope":18975,"verifyEd25519Signature-memory-arguments":10,"verifySchnorrSecp256k1Signature-cpu-arguments-intercept":38887044,"verifySchnorrSecp256k1Signature-cpu-arguments-slope":32947,"verifySchnorrSecp256k1Signature-memory-arguments":10},"PlutusV3":{"0":100788,"1":420,"2":1,"3":1,"4":1000,"5":173,"6":0,"7":1,"8":1000,"9":59957,"10":4,"11":1,"12":11183,"13":32,"14":201305,"15":8356,"16":4,"17":16000,"18":100,"19":16000,"20":100,"21":16000,"22":100,"23":16000,"24":100,"25":16000,"26":100,"27":16000,"28":100,"29":100,"30":100,"31":16000,"32":100,"33":94375,"34":32,"35":132994,"36":32,"37":61462,"38":4,"39":72010,"40":178,"41":0,"42":1,"43":22151,"44":32,"45":91189,"46":769,"47":4,"48":2,"49":85848,"50":123203,"51":7305,"52":-900,"53":1716,"54":549,"55":57,"56":85848,"57":0,"58":1,"59":1,"60":1000,"61":42921,"62":4,"63":2,"64":24548,"65":29498,"66":38,"67":1,"68":898148,"69":27279,"70":1,"71":51775,"72":558,"73":1,"74":39184,"75":1000,"76":60594,"77":1,"78":141895,"79":32,"80":83150,"81":32,"82":15299,"83":32,"84":76049,"85":1,"86":13169,"87":4,"88":22100,"89":10,"90":28999,"91":74,"92":1,"93":28999,"94":74,"95":1,"96":43285,"97":552,"98":1,"99":44749,"100":541,"101":1,"102":33852,"103":32,"104":68246,"105":32,"106":72362,"107":32,"108":7243,"109":32,"110":7391,"111":32,"112":11546,"113":32,"114":85848,"115":123203,"116":7305,"117":-900,"118":1716,"119":549,"120":57,"121":85848,"122":0,"123":1,"124":90434,"125":519,"126":0,"127":1,"128":74433,"129":32,"130":85848,"131":123203,"132":7305,"133":-900,"134":1716,"135":549,"136":57,"137":85848,"138":0,"139":1,"140":1,"141":85848,"142":123203,"143":7305,"144":-900,"145":1716,"146":549,"147":57,"148":85848,"149":0,"150":1,"151":955506,"152":213312,"153":0,"154":2,"155":270652,"156":22588,"157":4,"158":1457325,"159":64566,"160":4,"161":20467,"162":1,"163":4,"164":0,"165":141992,"166":32,"167":100788,"168":420,"169":1,"170":1,"171":81663,"172":32,"173":59498,"174":32,"175":20142,"176":32,"177":24588,"178":32,"179":20744,"180":32,"181":25933,"182":32,"183":24623,"184":32,"185":43053543,"186":10,"187":53384111,"188":14333,"189":10,"190":43574283,"191":26308,"192":10,"193":16000,"194":100,"195":16000,"196":100,"197":962335,"198":18,"199":2780678,"200":6,"201":442008,"202":1,"203":52538055,"204":3756,"205":18,"206":267929,"207":18,"208":76433006,"209":8868,"210":18,"211":52948122,"212":18,"213":1995836,"214":36,"215":3227919,"216":12,"217":901022,"218":1,"219":166917843,"220":4307,"221":36,"222":284546,"223":36,"224":158221314,"225":26549,"226":36,"227":74698472,"228":36,"229":333849714,"230":1,"231":254006273,"232":72,"233":2174038,"234":72,"235":2261318,"236":64571,"237":4,"238":207616,"239":8310,"240":4,"241":1293828,"242":28716,"243":63,"244":0,"245":1,"246":1006041,"247":43623,"248":251,"249":0,"250":1}},"price_mem":0.0577,"price_step":0.0000721,"max_tx_ex_mem":"14000000","max_tx_ex_steps":"10000000000","max_block_ex_mem":"62000000","max_block_ex_steps":"20000000000","max_val_size":"5000","collateral_percent":150,"max_collateral_inputs":3,"coins_per_utxo_size":"4310","coins_per_utxo_word":"4310","pvt_motion_no_confidence":0.6,"pvt_committee_normal":0.65,"pvt_committee_no_confidence":0.65,"pvt_hard_fork_initiation":0.51,"dvt_motion_no_confidence":0.67,"dvt_committee_normal":0.67,"dvt_committee_no_confidence":0.65,"dvt_update_to_constitution":0.75,"dvt_hard_fork_initiation":0.6,"dvt_p_p_network_group":0.67,"dvt_p_p_economic_group":0.67,"dvt_p_p_technical_group":0.67,"dvt_p_p_gov_group":0.75,"dvt_treasury_withdrawal":0.67,"committee_min_size":"5","committee_max_term_length":"146","gov_action_lifetime":"14","gov_action_deposit":"100000000000","drep_deposit":"500000000","drep_activity":"20"} \ No newline at end of file diff --git a/fixtures/test/blockfrost/getProtocolParameters/getProtocolParameters-7fe834fd628aa322eedeb3d8c7c1dd61.json b/fixtures/test/blockfrost/getProtocolParameters/getProtocolParameters-7fe834fd628aa322eedeb3d8c7c1dd61.json deleted file mode 100644 index 0fed15880a..0000000000 --- a/fixtures/test/blockfrost/getProtocolParameters/getProtocolParameters-7fe834fd628aa322eedeb3d8c7c1dd61.json +++ /dev/null @@ -1 +0,0 @@ -{"epoch":71,"min_fee_a":44,"min_fee_b":155381,"max_block_size":90112,"max_tx_size":16384,"max_block_header_size":1100,"key_deposit":"2000000","pool_deposit":"500000000","e_max":18,"n_opt":500,"a0":0.3,"rho":0.003,"tau":0.2,"decentralisation_param":0,"extra_entropy":null,"protocol_major_ver":8,"protocol_minor_ver":0,"min_utxo":"4310","min_pool_cost":"340000000","nonce":"e3ba06ef0f6021007739589d435432517a86e4e22723ac11b92b12f817718c77","cost_models":{"PlutusV1":{"addInteger-cpu-arguments-intercept":205665,"addInteger-cpu-arguments-slope":812,"addInteger-memory-arguments-intercept":1,"addInteger-memory-arguments-slope":1,"appendByteString-cpu-arguments-intercept":1000,"appendByteString-cpu-arguments-slope":571,"appendByteString-memory-arguments-intercept":0,"appendByteString-memory-arguments-slope":1,"appendString-cpu-arguments-intercept":1000,"appendString-cpu-arguments-slope":24177,"appendString-memory-arguments-intercept":4,"appendString-memory-arguments-slope":1,"bData-cpu-arguments":1000,"bData-memory-arguments":32,"blake2b_256-cpu-arguments-intercept":117366,"blake2b_256-cpu-arguments-slope":10475,"blake2b_256-memory-arguments":4,"cekApplyCost-exBudgetCPU":23000,"cekApplyCost-exBudgetMemory":100,"cekBuiltinCost-exBudgetCPU":23000,"cekBuiltinCost-exBudgetMemory":100,"cekConstCost-exBudgetCPU":23000,"cekConstCost-exBudgetMemory":100,"cekDelayCost-exBudgetCPU":23000,"cekDelayCost-exBudgetMemory":100,"cekForceCost-exBudgetCPU":23000,"cekForceCost-exBudgetMemory":100,"cekLamCost-exBudgetCPU":23000,"cekLamCost-exBudgetMemory":100,"cekStartupCost-exBudgetCPU":100,"cekStartupCost-exBudgetMemory":100,"cekVarCost-exBudgetCPU":23000,"cekVarCost-exBudgetMemory":100,"chooseData-cpu-arguments":19537,"chooseData-memory-arguments":32,"chooseList-cpu-arguments":175354,"chooseList-memory-arguments":32,"chooseUnit-cpu-arguments":46417,"chooseUnit-memory-arguments":4,"consByteString-cpu-arguments-intercept":221973,"consByteString-cpu-arguments-slope":511,"consByteString-memory-arguments-intercept":0,"consByteString-memory-arguments-slope":1,"constrData-cpu-arguments":89141,"constrData-memory-arguments":32,"decodeUtf8-cpu-arguments-intercept":497525,"decodeUtf8-cpu-arguments-slope":14068,"decodeUtf8-memory-arguments-intercept":4,"decodeUtf8-memory-arguments-slope":2,"divideInteger-cpu-arguments-constant":196500,"divideInteger-cpu-arguments-model-arguments-intercept":453240,"divideInteger-cpu-arguments-model-arguments-slope":220,"divideInteger-memory-arguments-intercept":0,"divideInteger-memory-arguments-minimum":1,"divideInteger-memory-arguments-slope":1,"encodeUtf8-cpu-arguments-intercept":1000,"encodeUtf8-cpu-arguments-slope":28662,"encodeUtf8-memory-arguments-intercept":4,"encodeUtf8-memory-arguments-slope":2,"equalsByteString-cpu-arguments-constant":245000,"equalsByteString-cpu-arguments-intercept":216773,"equalsByteString-cpu-arguments-slope":62,"equalsByteString-memory-arguments":1,"equalsData-cpu-arguments-intercept":1060367,"equalsData-cpu-arguments-slope":12586,"equalsData-memory-arguments":1,"equalsInteger-cpu-arguments-intercept":208512,"equalsInteger-cpu-arguments-slope":421,"equalsInteger-memory-arguments":1,"equalsString-cpu-arguments-constant":187000,"equalsString-cpu-arguments-intercept":1000,"equalsString-cpu-arguments-slope":52998,"equalsString-memory-arguments":1,"fstPair-cpu-arguments":80436,"fstPair-memory-arguments":32,"headList-cpu-arguments":43249,"headList-memory-arguments":32,"iData-cpu-arguments":1000,"iData-memory-arguments":32,"ifThenElse-cpu-arguments":80556,"ifThenElse-memory-arguments":1,"indexByteString-cpu-arguments":57667,"indexByteString-memory-arguments":4,"lengthOfByteString-cpu-arguments":1000,"lengthOfByteString-memory-arguments":10,"lessThanByteString-cpu-arguments-intercept":197145,"lessThanByteString-cpu-arguments-slope":156,"lessThanByteString-memory-arguments":1,"lessThanEqualsByteString-cpu-arguments-intercept":197145,"lessThanEqualsByteString-cpu-arguments-slope":156,"lessThanEqualsByteString-memory-arguments":1,"lessThanEqualsInteger-cpu-arguments-intercept":204924,"lessThanEqualsInteger-cpu-arguments-slope":473,"lessThanEqualsInteger-memory-arguments":1,"lessThanInteger-cpu-arguments-intercept":208896,"lessThanInteger-cpu-arguments-slope":511,"lessThanInteger-memory-arguments":1,"listData-cpu-arguments":52467,"listData-memory-arguments":32,"mapData-cpu-arguments":64832,"mapData-memory-arguments":32,"mkCons-cpu-arguments":65493,"mkCons-memory-arguments":32,"mkNilData-cpu-arguments":22558,"mkNilData-memory-arguments":32,"mkNilPairData-cpu-arguments":16563,"mkNilPairData-memory-arguments":32,"mkPairData-cpu-arguments":76511,"mkPairData-memory-arguments":32,"modInteger-cpu-arguments-constant":196500,"modInteger-cpu-arguments-model-arguments-intercept":453240,"modInteger-cpu-arguments-model-arguments-slope":220,"modInteger-memory-arguments-intercept":0,"modInteger-memory-arguments-minimum":1,"modInteger-memory-arguments-slope":1,"multiplyInteger-cpu-arguments-intercept":69522,"multiplyInteger-cpu-arguments-slope":11687,"multiplyInteger-memory-arguments-intercept":0,"multiplyInteger-memory-arguments-slope":1,"nullList-cpu-arguments":60091,"nullList-memory-arguments":32,"quotientInteger-cpu-arguments-constant":196500,"quotientInteger-cpu-arguments-model-arguments-intercept":453240,"quotientInteger-cpu-arguments-model-arguments-slope":220,"quotientInteger-memory-arguments-intercept":0,"quotientInteger-memory-arguments-minimum":1,"quotientInteger-memory-arguments-slope":1,"remainderInteger-cpu-arguments-constant":196500,"remainderInteger-cpu-arguments-model-arguments-intercept":453240,"remainderInteger-cpu-arguments-model-arguments-slope":220,"remainderInteger-memory-arguments-intercept":0,"remainderInteger-memory-arguments-minimum":1,"remainderInteger-memory-arguments-slope":1,"sha2_256-cpu-arguments-intercept":806990,"sha2_256-cpu-arguments-slope":30482,"sha2_256-memory-arguments":4,"sha3_256-cpu-arguments-intercept":1927926,"sha3_256-cpu-arguments-slope":82523,"sha3_256-memory-arguments":4,"sliceByteString-cpu-arguments-intercept":265318,"sliceByteString-cpu-arguments-slope":0,"sliceByteString-memory-arguments-intercept":4,"sliceByteString-memory-arguments-slope":0,"sndPair-cpu-arguments":85931,"sndPair-memory-arguments":32,"subtractInteger-cpu-arguments-intercept":205665,"subtractInteger-cpu-arguments-slope":812,"subtractInteger-memory-arguments-intercept":1,"subtractInteger-memory-arguments-slope":1,"tailList-cpu-arguments":41182,"tailList-memory-arguments":32,"trace-cpu-arguments":212342,"trace-memory-arguments":32,"unBData-cpu-arguments":31220,"unBData-memory-arguments":32,"unConstrData-cpu-arguments":32696,"unConstrData-memory-arguments":32,"unIData-cpu-arguments":43357,"unIData-memory-arguments":32,"unListData-cpu-arguments":32247,"unListData-memory-arguments":32,"unMapData-cpu-arguments":38314,"unMapData-memory-arguments":32,"verifyEd25519Signature-cpu-arguments-intercept":9462713,"verifyEd25519Signature-cpu-arguments-slope":1021,"verifyEd25519Signature-memory-arguments":10},"PlutusV2":{"addInteger-cpu-arguments-intercept":205665,"addInteger-cpu-arguments-slope":812,"addInteger-memory-arguments-intercept":1,"addInteger-memory-arguments-slope":1,"appendByteString-cpu-arguments-intercept":1000,"appendByteString-cpu-arguments-slope":571,"appendByteString-memory-arguments-intercept":0,"appendByteString-memory-arguments-slope":1,"appendString-cpu-arguments-intercept":1000,"appendString-cpu-arguments-slope":24177,"appendString-memory-arguments-intercept":4,"appendString-memory-arguments-slope":1,"bData-cpu-arguments":1000,"bData-memory-arguments":32,"blake2b_256-cpu-arguments-intercept":117366,"blake2b_256-cpu-arguments-slope":10475,"blake2b_256-memory-arguments":4,"cekApplyCost-exBudgetCPU":23000,"cekApplyCost-exBudgetMemory":100,"cekBuiltinCost-exBudgetCPU":23000,"cekBuiltinCost-exBudgetMemory":100,"cekConstCost-exBudgetCPU":23000,"cekConstCost-exBudgetMemory":100,"cekDelayCost-exBudgetCPU":23000,"cekDelayCost-exBudgetMemory":100,"cekForceCost-exBudgetCPU":23000,"cekForceCost-exBudgetMemory":100,"cekLamCost-exBudgetCPU":23000,"cekLamCost-exBudgetMemory":100,"cekStartupCost-exBudgetCPU":100,"cekStartupCost-exBudgetMemory":100,"cekVarCost-exBudgetCPU":23000,"cekVarCost-exBudgetMemory":100,"chooseData-cpu-arguments":19537,"chooseData-memory-arguments":32,"chooseList-cpu-arguments":175354,"chooseList-memory-arguments":32,"chooseUnit-cpu-arguments":46417,"chooseUnit-memory-arguments":4,"consByteString-cpu-arguments-intercept":221973,"consByteString-cpu-arguments-slope":511,"consByteString-memory-arguments-intercept":0,"consByteString-memory-arguments-slope":1,"constrData-cpu-arguments":89141,"constrData-memory-arguments":32,"decodeUtf8-cpu-arguments-intercept":497525,"decodeUtf8-cpu-arguments-slope":14068,"decodeUtf8-memory-arguments-intercept":4,"decodeUtf8-memory-arguments-slope":2,"divideInteger-cpu-arguments-constant":196500,"divideInteger-cpu-arguments-model-arguments-intercept":453240,"divideInteger-cpu-arguments-model-arguments-slope":220,"divideInteger-memory-arguments-intercept":0,"divideInteger-memory-arguments-minimum":1,"divideInteger-memory-arguments-slope":1,"encodeUtf8-cpu-arguments-intercept":1000,"encodeUtf8-cpu-arguments-slope":28662,"encodeUtf8-memory-arguments-intercept":4,"encodeUtf8-memory-arguments-slope":2,"equalsByteString-cpu-arguments-constant":245000,"equalsByteString-cpu-arguments-intercept":216773,"equalsByteString-cpu-arguments-slope":62,"equalsByteString-memory-arguments":1,"equalsData-cpu-arguments-intercept":1060367,"equalsData-cpu-arguments-slope":12586,"equalsData-memory-arguments":1,"equalsInteger-cpu-arguments-intercept":208512,"equalsInteger-cpu-arguments-slope":421,"equalsInteger-memory-arguments":1,"equalsString-cpu-arguments-constant":187000,"equalsString-cpu-arguments-intercept":1000,"equalsString-cpu-arguments-slope":52998,"equalsString-memory-arguments":1,"fstPair-cpu-arguments":80436,"fstPair-memory-arguments":32,"headList-cpu-arguments":43249,"headList-memory-arguments":32,"iData-cpu-arguments":1000,"iData-memory-arguments":32,"ifThenElse-cpu-arguments":80556,"ifThenElse-memory-arguments":1,"indexByteString-cpu-arguments":57667,"indexByteString-memory-arguments":4,"lengthOfByteString-cpu-arguments":1000,"lengthOfByteString-memory-arguments":10,"lessThanByteString-cpu-arguments-intercept":197145,"lessThanByteString-cpu-arguments-slope":156,"lessThanByteString-memory-arguments":1,"lessThanEqualsByteString-cpu-arguments-intercept":197145,"lessThanEqualsByteString-cpu-arguments-slope":156,"lessThanEqualsByteString-memory-arguments":1,"lessThanEqualsInteger-cpu-arguments-intercept":204924,"lessThanEqualsInteger-cpu-arguments-slope":473,"lessThanEqualsInteger-memory-arguments":1,"lessThanInteger-cpu-arguments-intercept":208896,"lessThanInteger-cpu-arguments-slope":511,"lessThanInteger-memory-arguments":1,"listData-cpu-arguments":52467,"listData-memory-arguments":32,"mapData-cpu-arguments":64832,"mapData-memory-arguments":32,"mkCons-cpu-arguments":65493,"mkCons-memory-arguments":32,"mkNilData-cpu-arguments":22558,"mkNilData-memory-arguments":32,"mkNilPairData-cpu-arguments":16563,"mkNilPairData-memory-arguments":32,"mkPairData-cpu-arguments":76511,"mkPairData-memory-arguments":32,"modInteger-cpu-arguments-constant":196500,"modInteger-cpu-arguments-model-arguments-intercept":453240,"modInteger-cpu-arguments-model-arguments-slope":220,"modInteger-memory-arguments-intercept":0,"modInteger-memory-arguments-minimum":1,"modInteger-memory-arguments-slope":1,"multiplyInteger-cpu-arguments-intercept":69522,"multiplyInteger-cpu-arguments-slope":11687,"multiplyInteger-memory-arguments-intercept":0,"multiplyInteger-memory-arguments-slope":1,"nullList-cpu-arguments":60091,"nullList-memory-arguments":32,"quotientInteger-cpu-arguments-constant":196500,"quotientInteger-cpu-arguments-model-arguments-intercept":453240,"quotientInteger-cpu-arguments-model-arguments-slope":220,"quotientInteger-memory-arguments-intercept":0,"quotientInteger-memory-arguments-minimum":1,"quotientInteger-memory-arguments-slope":1,"remainderInteger-cpu-arguments-constant":196500,"remainderInteger-cpu-arguments-model-arguments-intercept":453240,"remainderInteger-cpu-arguments-model-arguments-slope":220,"remainderInteger-memory-arguments-intercept":0,"remainderInteger-memory-arguments-minimum":1,"remainderInteger-memory-arguments-slope":1,"serialiseData-cpu-arguments-intercept":1159724,"serialiseData-cpu-arguments-slope":392670,"serialiseData-memory-arguments-intercept":0,"serialiseData-memory-arguments-slope":2,"sha2_256-cpu-arguments-intercept":806990,"sha2_256-cpu-arguments-slope":30482,"sha2_256-memory-arguments":4,"sha3_256-cpu-arguments-intercept":1927926,"sha3_256-cpu-arguments-slope":82523,"sha3_256-memory-arguments":4,"sliceByteString-cpu-arguments-intercept":265318,"sliceByteString-cpu-arguments-slope":0,"sliceByteString-memory-arguments-intercept":4,"sliceByteString-memory-arguments-slope":0,"sndPair-cpu-arguments":85931,"sndPair-memory-arguments":32,"subtractInteger-cpu-arguments-intercept":205665,"subtractInteger-cpu-arguments-slope":812,"subtractInteger-memory-arguments-intercept":1,"subtractInteger-memory-arguments-slope":1,"tailList-cpu-arguments":41182,"tailList-memory-arguments":32,"trace-cpu-arguments":212342,"trace-memory-arguments":32,"unBData-cpu-arguments":31220,"unBData-memory-arguments":32,"unConstrData-cpu-arguments":32696,"unConstrData-memory-arguments":32,"unIData-cpu-arguments":43357,"unIData-memory-arguments":32,"unListData-cpu-arguments":32247,"unListData-memory-arguments":32,"unMapData-cpu-arguments":38314,"unMapData-memory-arguments":32,"verifyEcdsaSecp256k1Signature-cpu-arguments":35892428,"verifyEcdsaSecp256k1Signature-memory-arguments":10,"verifyEd25519Signature-cpu-arguments-intercept":9462713,"verifyEd25519Signature-cpu-arguments-slope":1021,"verifyEd25519Signature-memory-arguments":10,"verifySchnorrSecp256k1Signature-cpu-arguments-intercept":38887044,"verifySchnorrSecp256k1Signature-cpu-arguments-slope":32947,"verifySchnorrSecp256k1Signature-memory-arguments":10}},"price_mem":0.0577,"price_step":0.0000721,"max_tx_ex_mem":"14000000","max_tx_ex_steps":"10000000000","max_block_ex_mem":"62000000","max_block_ex_steps":"40000000000","max_val_size":"5000","collateral_percent":150,"max_collateral_inputs":3,"coins_per_utxo_size":"4310","coins_per_utxo_word":"4310"} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryLedgerState-epoch-549aea404aff3926f2fce0325e9cd8d4.json b/fixtures/test/ogmios/queryLedgerState-epoch-549aea404aff3926f2fce0325e9cd8d4.json new file mode 100644 index 0000000000..667523d64c --- /dev/null +++ b/fixtures/test/ogmios/queryLedgerState-epoch-549aea404aff3926f2fce0325e9cd8d4.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryLedgerState/epoch","result":369,"id":"queryLedgerState/epoch-hfkgvfollxkiih0n"} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryLedgerState-epoch-8d7a461f70d4d44d0d8cdd64c5fba15c.json b/fixtures/test/ogmios/queryLedgerState-epoch-8d7a461f70d4d44d0d8cdd64c5fba15c.json deleted file mode 100644 index 093568ebd8..0000000000 --- a/fixtures/test/ogmios/queryLedgerState-epoch-8d7a461f70d4d44d0d8cdd64c5fba15c.json +++ /dev/null @@ -1 +0,0 @@ -{"result":374,"method":"queryLedgerState/epoch","jsonrpc":"2.0","id":"queryLedgerState/epoch-3rvj1ml27d5loixoww7","error":null} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryLedgerState-epoch-f91be14635fa026f2a990508f3379064.json b/fixtures/test/ogmios/queryLedgerState-epoch-f91be14635fa026f2a990508f3379064.json new file mode 100644 index 0000000000..5ef38782b0 --- /dev/null +++ b/fixtures/test/ogmios/queryLedgerState-epoch-f91be14635fa026f2a990508f3379064.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryLedgerState/epoch","result":122,"id":"queryLedgerState/epoch-hfkg8z8vlxlxx1jb"} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryLedgerState-eraSummaries-8073a8f378e969384ec52010ec6c290c.json b/fixtures/test/ogmios/queryLedgerState-eraSummaries-8073a8f378e969384ec52010ec6c290c.json new file mode 100644 index 0000000000..d222d802c4 --- /dev/null +++ b/fixtures/test/ogmios/queryLedgerState-eraSummaries-8073a8f378e969384ec52010ec6c290c.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryLedgerState/eraSummaries","result":[{"start":{"time":{"seconds":0},"slot":0,"epoch":0},"end":{"time":{"seconds":0},"slot":0,"epoch":0},"parameters":{"epochLength":4320,"slotLength":{"milliseconds":20000},"safeZone":864}},{"start":{"time":{"seconds":0},"slot":0,"epoch":0},"end":{"time":{"seconds":0},"slot":0,"epoch":0},"parameters":{"epochLength":86400,"slotLength":{"milliseconds":1000},"safeZone":25920}},{"start":{"time":{"seconds":0},"slot":0,"epoch":0},"end":{"time":{"seconds":0},"slot":0,"epoch":0},"parameters":{"epochLength":86400,"slotLength":{"milliseconds":1000},"safeZone":25920}},{"start":{"time":{"seconds":0},"slot":0,"epoch":0},"end":{"time":{"seconds":0},"slot":0,"epoch":0},"parameters":{"epochLength":86400,"slotLength":{"milliseconds":1000},"safeZone":25920}},{"start":{"time":{"seconds":0},"slot":0,"epoch":0},"end":{"time":{"seconds":172800},"slot":172800,"epoch":2},"parameters":{"epochLength":86400,"slotLength":{"milliseconds":1000},"safeZone":25920}},{"start":{"time":{"seconds":172800},"slot":172800,"epoch":2},"end":{"time":{"seconds":28944000},"slot":28944000,"epoch":335},"parameters":{"epochLength":86400,"slotLength":{"milliseconds":1000},"safeZone":25920}},{"start":{"time":{"seconds":28944000},"slot":28944000,"epoch":335},"end":{"time":{"seconds":31968000},"slot":31968000,"epoch":370},"parameters":{"epochLength":86400,"slotLength":{"milliseconds":1000},"safeZone":25920}}],"id":"queryLedgerState/eraSummaries-hfkgvfollxkiih0o"} diff --git a/fixtures/test/ogmios/queryLedgerState-eraSummaries-d8b19110b9580cddfa3895eea34c2139.json b/fixtures/test/ogmios/queryLedgerState-eraSummaries-d8b19110b9580cddfa3895eea34c2139.json deleted file mode 100644 index 6a2ce74782..0000000000 --- a/fixtures/test/ogmios/queryLedgerState-eraSummaries-d8b19110b9580cddfa3895eea34c2139.json +++ /dev/null @@ -1 +0,0 @@ -{"result":[{"start":{"time":0,"slot":0,"epoch":0},"end":{"time":0,"slot":0,"epoch":0},"parameters":{"epochLength":4320,"slotLength":{"seconds":20},"safeZone":864}},{"start":{"time":0,"slot":0,"epoch":0},"end":{"time":0,"slot":0,"epoch":0},"parameters":{"epochLength":86400,"slotLength":{"seconds":1},"safeZone":25920}},{"start":{"time":0,"slot":0,"epoch":0},"end":{"time":0,"slot":0,"epoch":0},"parameters":{"epochLength":86400,"slotLength":{"seconds":1},"safeZone":25920}},{"start":{"time":0,"slot":0,"epoch":0},"end":{"time":0,"slot":0,"epoch":0},"parameters":{"epochLength":86400,"slotLength":{"seconds":1},"safeZone":25920}},{"start":{"time":0,"slot":0,"epoch":0},"end":{"time":259200,"slot":259200,"epoch":3},"parameters":{"epochLength":86400,"slotLength":{"seconds":1},"safeZone":25920}},{"start":{"time":259200,"slot":259200,"epoch":3},"end":{"time":32486400,"slot":32486400,"epoch":376},"parameters":{"epochLength":86400,"slotLength":{"seconds":1},"safeZone":25920}}],"method":"queryLedgerState/eraSummaries","jsonrpc":"2.0","id":"queryLedgerState/eraSummaries-3rvj1ml27d5loixoww8","error":null} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryLedgerState-protocolParameters-1d8c6233b8bfb7c028f1dd60eb113d40.json b/fixtures/test/ogmios/queryLedgerState-protocolParameters-1d8c6233b8bfb7c028f1dd60eb113d40.json new file mode 100644 index 0000000000..f80e8373fc --- /dev/null +++ b/fixtures/test/ogmios/queryLedgerState-protocolParameters-1d8c6233b8bfb7c028f1dd60eb113d40.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryLedgerState/protocolParameters","result":{"minFeeCoefficient":44,"minFeeConstant":{"ada":{"lovelace":155381}},"minFeeReferenceScripts":{"base":15,"range":25600,"multiplier":1.2},"maxBlockBodySize":{"bytes":90112},"maxBlockHeaderSize":{"bytes":1100},"maxTransactionSize":{"bytes":16384},"maxReferenceScriptsSize":{"bytes":204800},"stakeCredentialDeposit":{"ada":{"lovelace":2000000}},"stakePoolDeposit":{"ada":{"lovelace":500000000}},"stakePoolRetirementEpochBound":18,"desiredNumberOfStakePools":500,"stakePoolPledgeInfluence":"3/10","monetaryExpansion":"3/1000","treasuryExpansion":"1/5","minStakePoolCost":{"ada":{"lovelace":340000000}},"minUtxoDepositConstant":{"ada":{"lovelace":0}},"minUtxoDepositCoefficient":4310,"plutusCostModels":{"plutus:v1":[205665,812,1,1,1000,571,0,1,1000,24177,4,1,1000,32,117366,10475,4,23000,100,23000,100,23000,100,23000,100,23000,100,23000,100,100,100,23000,100,19537,32,175354,32,46417,4,221973,511,0,1,89141,32,497525,14068,4,2,196500,453240,220,0,1,1,1000,28662,4,2,245000,216773,62,1,1060367,12586,1,208512,421,1,187000,1000,52998,1,80436,32,43249,32,1000,32,80556,1,57667,4,1000,10,197145,156,1,197145,156,1,204924,473,1,208896,511,1,52467,32,64832,32,65493,32,22558,32,16563,32,76511,32,196500,453240,220,0,1,1,69522,11687,0,1,60091,32,196500,453240,220,0,1,1,196500,453240,220,0,1,1,806990,30482,4,1927926,82523,4,265318,0,4,0,85931,32,205665,812,1,1,41182,32,212342,32,31220,32,32696,32,43357,32,32247,32,38314,32,57996947,18975,10],"plutus:v2":[205665,812,1,1,1000,571,0,1,1000,24177,4,1,1000,32,117366,10475,4,23000,100,23000,100,23000,100,23000,100,23000,100,23000,100,100,100,23000,100,19537,32,175354,32,46417,4,221973,511,0,1,89141,32,497525,14068,4,2,196500,453240,220,0,1,1,1000,28662,4,2,245000,216773,62,1,1060367,12586,1,208512,421,1,187000,1000,52998,1,80436,32,43249,32,1000,32,80556,1,57667,4,1000,10,197145,156,1,197145,156,1,204924,473,1,208896,511,1,52467,32,64832,32,65493,32,22558,32,16563,32,76511,32,196500,453240,220,0,1,1,69522,11687,0,1,60091,32,196500,453240,220,0,1,1,196500,453240,220,0,1,1,1159724,392670,0,2,806990,30482,4,1927926,82523,4,265318,0,4,0,85931,32,205665,812,1,1,41182,32,212342,32,31220,32,32696,32,43357,32,32247,32,38314,32,35892428,10,57996947,18975,10,38887044,32947,10],"plutus:v3":[100788,420,1,1,1000,173,0,1,1000,59957,4,1,11183,32,201305,8356,4,16000,100,16000,100,16000,100,16000,100,16000,100,16000,100,100,100,16000,100,94375,32,132994,32,61462,4,72010,178,0,1,22151,32,91189,769,4,2,85848,123203,7305,-900,1716,549,57,85848,0,1,1,1000,42921,4,2,24548,29498,38,1,898148,27279,1,51775,558,1,39184,1000,60594,1,141895,32,83150,32,15299,32,76049,1,13169,4,22100,10,28999,74,1,28999,74,1,43285,552,1,44749,541,1,33852,32,68246,32,72362,32,7243,32,7391,32,11546,32,85848,123203,7305,-900,1716,549,57,85848,0,1,90434,519,0,1,74433,32,85848,123203,7305,-900,1716,549,57,85848,0,1,1,85848,123203,7305,-900,1716,549,57,85848,0,1,955506,213312,0,2,270652,22588,4,1457325,64566,4,20467,1,4,0,141992,32,100788,420,1,1,81663,32,59498,32,20142,32,24588,32,20744,32,25933,32,24623,32,43053543,10,53384111,14333,10,43574283,26308,10,16000,100,16000,100,962335,18,2780678,6,442008,1,52538055,3756,18,267929,18,76433006,8868,18,52948122,18,1995836,36,3227919,12,901022,1,166917843,4307,36,284546,36,158221314,26549,36,74698472,36,333849714,1,254006273,72,2174038,72,2261318,64571,4,207616,8310,4,1293828,28716,63,0,1,1006041,43623,251,0,1]},"scriptExecutionPrices":{"memory":"577/10000","cpu":"721/10000000"},"maxExecutionUnitsPerTransaction":{"memory":14000000,"cpu":10000000000},"maxExecutionUnitsPerBlock":{"memory":62000000,"cpu":20000000000},"maxValueSize":{"bytes":5000},"collateralPercentage":150,"maxCollateralInputs":3,"version":{"major":10,"minor":0},"stakePoolVotingThresholds":{"noConfidence":"3/5","constitutionalCommittee":{"default":"13/20","stateOfNoConfidence":"13/20"},"hardForkInitiation":"51/100"},"delegateRepresentativeVotingThresholds":{"noConfidence":"67/100","constitutionalCommittee":{"default":"67/100","stateOfNoConfidence":"13/20"},"constitution":"3/4","hardForkInitiation":"3/5","protocolParametersUpdate":{"network":"67/100","economic":"67/100","technical":"67/100","governance":"3/4"},"treasuryWithdrawals":"67/100"},"constitutionalCommitteeMinSize":5,"constitutionalCommitteeMaxTermLength":146,"governanceActionLifetime":14,"governanceActionDeposit":{"ada":{"lovelace":100000000000}},"delegateRepresentativeDeposit":{"ada":{"lovelace":500000000}},"delegateRepresentativeMaxIdleTime":20},"id":"queryLedgerState/protocolParameters-hfkg3r9slz15sesn"} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryLedgerState-protocolParameters-68ba1141d17af9326cad70407ea3d7fb.json b/fixtures/test/ogmios/queryLedgerState-protocolParameters-68ba1141d17af9326cad70407ea3d7fb.json deleted file mode 100644 index 154c4a4962..0000000000 --- a/fixtures/test/ogmios/queryLedgerState-protocolParameters-68ba1141d17af9326cad70407ea3d7fb.json +++ /dev/null @@ -1 +0,0 @@ -{"result":{"minFeeCoefficient":44,"minFeeConstant":{"lovelace":155381},"maxBlockBodySize":{"bytes":90112},"maxBlockHeaderSize":{"bytes":1100},"maxTransactionSize":{"bytes":16384},"stakeCredentialDeposit":{"lovelace":2000000},"stakePoolDeposit":{"lovelace":500000000},"stakePoolRetirementEpochBound":18,"desiredNumberOfStakePools":500,"stakePoolPledgeInfluence":"3/10","monetaryExpansion":"3/1000","treasuryExpansion":"1/5","minStakePoolCost":{"lovelace":170000000},"minUtxoDepositConstant":0,"minUtxoDepositCoefficient":4310,"plutusCostModels":{"plutus:v1":[205665,812,1,1,1000,571,0,1,1000,24177,4,1,1000,32,117366,10475,4,23000,100,23000,100,23000,100,23000,100,23000,100,23000,100,100,100,23000,100,19537,32,175354,32,46417,4,221973,511,0,1,89141,32,497525,14068,4,2,196500,453240,220,0,1,1,1000,28662,4,2,245000,216773,62,1,1060367,12586,1,208512,421,1,187000,1000,52998,1,80436,32,43249,32,1000,32,80556,1,57667,4,1000,10,197145,156,1,197145,156,1,204924,473,1,208896,511,1,52467,32,64832,32,65493,32,22558,32,16563,32,76511,32,196500,453240,220,0,1,1,69522,11687,0,1,60091,32,196500,453240,220,0,1,1,196500,453240,220,0,1,1,806990,30482,4,1927926,82523,4,265318,0,4,0,85931,32,205665,812,1,1,41182,32,212342,32,31220,32,32696,32,43357,32,32247,32,38314,32,57996947,18975,10],"plutus:v2":[205665,812,1,1,1000,571,0,1,1000,24177,4,1,1000,32,117366,10475,4,23000,100,23000,100,23000,100,23000,100,23000,100,23000,100,100,100,23000,100,19537,32,175354,32,46417,4,221973,511,0,1,89141,32,497525,14068,4,2,196500,453240,220,0,1,1,1000,28662,4,2,245000,216773,62,1,1060367,12586,1,208512,421,1,187000,1000,52998,1,80436,32,43249,32,1000,32,80556,1,57667,4,1000,10,197145,156,1,197145,156,1,204924,473,1,208896,511,1,52467,32,64832,32,65493,32,22558,32,16563,32,76511,32,196500,453240,220,0,1,1,69522,11687,0,1,60091,32,196500,453240,220,0,1,1,196500,453240,220,0,1,1,1159724,392670,0,2,806990,30482,4,1927926,82523,4,265318,0,4,0,85931,32,205665,812,1,1,41182,32,212342,32,31220,32,32696,32,43357,32,32247,32,38314,32,35892428,10,57996947,18975,10,38887044,32947,10]},"scriptExecutionPrices":{"memory":"577/10000","cpu":"721/10000000"},"maxExecutionUnitsPerTransaction":{"memory":14000000,"cpu":10000000000},"maxExecutionUnitsPerBlock":{"memory":62000000,"cpu":20000000000},"maxValueSize":{"bytes":5000},"collateralPercentage":150,"maxCollateralInputs":3,"version":{"major":8,"minor":0}},"method":"queryLedgerState/protocolParameters","jsonrpc":"2.0","id":"queryLedgerState/protocolParameters-3rvj1ml27d5loixoww9","error":null} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryLedgerState-protocolParameters-f39db65d5d9dc11e511f061b37349173.json b/fixtures/test/ogmios/queryLedgerState-protocolParameters-f39db65d5d9dc11e511f061b37349173.json new file mode 100644 index 0000000000..dba57f04f4 --- /dev/null +++ b/fixtures/test/ogmios/queryLedgerState-protocolParameters-f39db65d5d9dc11e511f061b37349173.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryLedgerState/protocolParameters","result":{"minFeeCoefficient":44,"minFeeConstant":{"ada":{"lovelace":155381}},"maxBlockBodySize":{"bytes":90112},"maxBlockHeaderSize":{"bytes":1100},"maxTransactionSize":{"bytes":16384},"stakeCredentialDeposit":{"ada":{"lovelace":2000000}},"stakePoolDeposit":{"ada":{"lovelace":500000000}},"stakePoolRetirementEpochBound":18,"desiredNumberOfStakePools":500,"stakePoolPledgeInfluence":"3/10","monetaryExpansion":"3/1000","treasuryExpansion":"1/5","minStakePoolCost":{"ada":{"lovelace":170000000}},"minUtxoDepositConstant":{"ada":{"lovelace":0}},"minUtxoDepositCoefficient":4310,"plutusCostModels":{"plutus:v1":[205665,812,1,1,1000,571,0,1,1000,24177,4,1,1000,32,117366,10475,4,23000,100,23000,100,23000,100,23000,100,23000,100,23000,100,100,100,23000,100,19537,32,175354,32,46417,4,221973,511,0,1,89141,32,497525,14068,4,2,196500,453240,220,0,1,1,1000,28662,4,2,245000,216773,62,1,1060367,12586,1,208512,421,1,187000,1000,52998,1,80436,32,43249,32,1000,32,80556,1,57667,4,1000,10,197145,156,1,197145,156,1,204924,473,1,208896,511,1,52467,32,64832,32,65493,32,22558,32,16563,32,76511,32,196500,453240,220,0,1,1,69522,11687,0,1,60091,32,196500,453240,220,0,1,1,196500,453240,220,0,1,1,806990,30482,4,1927926,82523,4,265318,0,4,0,85931,32,205665,812,1,1,41182,32,212342,32,31220,32,32696,32,43357,32,32247,32,38314,32,57996947,18975,10],"plutus:v2":[205665,812,1,1,1000,571,0,1,1000,24177,4,1,1000,32,117366,10475,4,23000,100,23000,100,23000,100,23000,100,23000,100,23000,100,100,100,23000,100,19537,32,175354,32,46417,4,221973,511,0,1,89141,32,497525,14068,4,2,196500,453240,220,0,1,1,1000,28662,4,2,245000,216773,62,1,1060367,12586,1,208512,421,1,187000,1000,52998,1,80436,32,43249,32,1000,32,80556,1,57667,4,1000,10,197145,156,1,197145,156,1,204924,473,1,208896,511,1,52467,32,64832,32,65493,32,22558,32,16563,32,76511,32,196500,453240,220,0,1,1,69522,11687,0,1,60091,32,196500,453240,220,0,1,1,196500,453240,220,0,1,1,1159724,392670,0,2,806990,30482,4,1927926,82523,4,265318,0,4,0,85931,32,205665,812,1,1,41182,32,212342,32,31220,32,32696,32,43357,32,32247,32,38314,32,35892428,10,57996947,18975,10,38887044,32947,10]},"scriptExecutionPrices":{"memory":"577/10000","cpu":"721/10000000"},"maxExecutionUnitsPerTransaction":{"memory":14000000,"cpu":10000000000},"maxExecutionUnitsPerBlock":{"memory":62000000,"cpu":20000000000},"maxValueSize":{"bytes":5000},"collateralPercentage":150,"maxCollateralInputs":3,"version":{"major":8,"minor":0}},"id":"queryLedgerState/protocolParameters-hfkg1hk4lxm0pfyy"} diff --git a/fixtures/test/ogmios/queryLedgerState-stakePools-0147fed3c201c7769462ebd9f2e0aa8d.json b/fixtures/test/ogmios/queryLedgerState-stakePools-0147fed3c201c7769462ebd9f2e0aa8d.json new file mode 100644 index 0000000000..fe3504a59c --- /dev/null +++ b/fixtures/test/ogmios/queryLedgerState-stakePools-0147fed3c201c7769462ebd9f2e0aa8d.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryLedgerState/stakePools","result":{"pool1qfjpgpy83v9hal8z3hjnt3namnc8xcrqstgp504sr2p2krfu7dd":{"id":"pool1qfjpgpy83v9hal8z3hjnt3namnc8xcrqstgp504sr2p2krfu7dd","vrfVerificationKeyHash":"39af5d6fcd342985e6c3bd7159b8f74eb8a2181a9eae524fecf02b58fa3ef95d","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"21/500","rewardAccount":"stake_test1uqzah3n6wfgxw78kmha95vnpnq35yqlnqq8e0q9vf79pfjq30m0al","owners":["05dbc67a72506778f6ddfa5a326198234203f3000f9780ac4f8a14c8"],"relays":[{"type":"hostname","hostname":"test.smaug.pool.pm","port":3004}],"metadata":{"url":"https://smaug.pool.pm/meta-b4391f2c.json","hash":"b4391f2c278c8b34fd73a1b33ea20da50383e1a906d11ba27c644975cba97412"}},"pool1rdaxrw3722f0x3nx4uam9u9c6dh9qqd2g83r2uyllf53qmmj5uu":{"id":"pool1rdaxrw3722f0x3nx4uam9u9c6dh9qqd2g83r2uyllf53qmmj5uu","vrfVerificationKeyHash":"fdb9ec5d3e9774458dbdb7b337190fc9a2fbc585f28060fd0158ee8f9a96b8a2","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":10000000000}},"margin":"1/10","rewardAccount":"stake_test1urqntq4wexjylnrdnp97qq79qkxxvrsa9lcnwr7ckjd6w0cr04y4p","owners":["c13582aec9a44fcc6d984be003c5058c660e1d2ff1370fd8b49ba73f"],"relays":[{"type":"hostname","hostname":"test.stakepool.at","port":3001}],"metadata":{"url":"https://my-ip.at/test/sanchopool.metadata.json","hash":"69059846a028ab1161218d3b683502abcc0513a88567de78cc18b43d506e3f3c"}},"pool1xrr9pc5wrh6p30mgsx5f87lcwgzrk53dylt6mr4dgs7gyy7vrl8":{"id":"pool1xrr9pc5wrh6p30mgsx5f87lcwgzrk53dylt6mr4dgs7gyy7vrl8","vrfVerificationKeyHash":"006bf4607575e637cc001309fb9ee1a7d298c1854ee680004586989080affd6f","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":420000000}},"margin":"1/10","rewardAccount":"stake_test1uqucy2kt9hvqatv66um3n9k250txwk75fdk5nderred0v0q8tc0ex","owners":["39822acb2dd80ead9ad7371996caa3d6675bd44b6d49b7231e5af63c"],"relays":[{"type":"hostname","hostname":"sn-relay1.apexpool.info","port":3001}],"metadata":{"url":"https://apexpool.info/testnet/poolmetadata.json","hash":"a207f23a6255eeb0b508945e5170b169eb5c3220109d7fa17a7d88d462c8a199"}},"pool1xxym8esp42n98d5xa9mg96hp8x3lflfzdde3k9jvwgqsqmpc7k0":{"id":"pool1xxym8esp42n98d5xa9mg96hp8x3lflfzdde3k9jvwgqsqmpc7k0","vrfVerificationKeyHash":"2cf4c32db8b90524046b2970e9839d9ff50234a0b701514531b629ad4064d64f","pledge":{"ada":{"lovelace":90000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1uqgpckl60xvctfhfdtdmtpv7jr97fg8yah977sy2xc39tzcqq85ws","owners":["101c5bfa799985a6e96adbb5859e90cbe4a0e4edcbef408a3622558b"],"relays":[{"type":"hostname","hostname":"node1.cardano.gratis","port":6401},{"type":"hostname","hostname":"node2.cardano.gratis","port":6402}],"metadata":{"url":"https://cardano.gratis/poolmetadatasanchonet.json","hash":"42bccfe66e06bdfaac74c361c5f8d9f6fa899c82f1f72815fd6e48deead38ccc"}},"pool1x2zyeurdn6p0vfus5hye5hcjdu2pk9lp43wkpp7g0hasxjxu0r6":{"id":"pool1x2zyeurdn6p0vfus5hye5hcjdu2pk9lp43wkpp7g0hasxjxu0r6","vrfVerificationKeyHash":"5889f906dd051543f7bfbc8d0c95110260ccdfa26a905d247a8f7499bb87d283","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1uzkfmfgarpr7ghgz7w7cunv06r8tqncrh6xsynee2gxj5ks3r8g2w","owners":["ac9da51d1847e45d02f3bd8e4d8fd0ceb04f03be8d024f39520d2a5a"],"relays":[{"type":"hostname","hostname":"c-sn-rn01.liv.io","port":30004},{"type":"hostname","hostname":"c-sn-rn02.liv.io","port":30004}],"metadata":{"url":"https://liv.io/metadata.json","hash":"78409be753a669ae5eb8c81ee7f3f1a48e8a265ebc6814e6247af4440d50b515"}},"pool180jwa8p7zyjke2g8q8gccfl0fhqm5e3guqeh03vjlmfx2jdn6h6":{"id":"pool180jwa8p7zyjke2g8q8gccfl0fhqm5e3guqeh03vjlmfx2jdn6h6","vrfVerificationKeyHash":"e8b0fb834d5574273d44979b1a4a44a8f829cce2b32aa09d34827ac06995236a","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1urceznh2v6kel2rxlyqmay9caqff0fgtettjwnkhz59fnlghle5jn","owners":["f1914eea66ad9fa866f901be90b8e81297a50bcad7274ed7150a99fd"],"relays":[{"type":"hostname","hostname":"sanchorelay.junglestakepool.com","port":3003}],"metadata":{"url":"https://junglestakepool.com/jp-sanchonet.json","hash":"ed8428ea6ab07e94f8af44a0ddec8df1ccf63401b5592f88831fed0da9dda860"}},"pool1fhr6s9xqqu7cenr662paxcyyhcxvdwga0355v22h9z50zrcxljs":{"id":"pool1fhr6s9xqqu7cenr662paxcyyhcxvdwga0355v22h9z50zrcxljs","vrfVerificationKeyHash":"5c047db583e2d79ed308bde394664b3675465b2ec350388f957ba96dfecb8d9d","pledge":{"ada":{"lovelace":50000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1uqj3zvljhu695w0yzqvtp3w5lra6vzgxd0lz50rh4s38yssxfmvqf","owners":["251133f2bf345a39e41018b0c5d4f8fba609066bfe2a3c77ac227242"],"relays":[{"type":"ipAddress","ipv4":"73.23.36.140","port":5000}],"metadata":{"url":"https://petloverstake.com/PET_Sancho.json","hash":"bf6ee843301bdabbddc4e18f920b1da6e91a5a7a3057381a04c6cfe9b165dcf3"}},"pool1v7ek9g8xnm9gud47x209vzsypcaxmcsqrth7zwcs4c6k506ffnq":{"id":"pool1v7ek9g8xnm9gud47x209vzsypcaxmcsqrth7zwcs4c6k506ffnq","vrfVerificationKeyHash":"b41ffe1f1b752cdb7fddad90137e07a655c2673007af5daac18d7827fc4394ae","pledge":{"ada":{"lovelace":90000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1upxen45d9t467l76pvxlue99635hleqcmvtrcnghmf6v7lgjengrp","owners":["4d99d68d2aebaf7fda0b0dfe64a5d4697fe418db163c4d17da74cf7d"],"relays":[{"type":"hostname","hostname":"sancho.junostakepool.com","port":18441}],"metadata":{"url":"https://junostakepool.com/juno-sancho.metadata.json","hash":"098b2ced4cf44471bb7737e07f600bab426fe485ef71343b7f4b2a4b067e325f"}},"pool104flte3y29dprxcntacsuyznhduvlaza38gvp8yyhy2vvmfenxa":{"id":"pool104flte3y29dprxcntacsuyznhduvlaza38gvp8yyhy2vvmfenxa","vrfVerificationKeyHash":"47bc02cc376e3a44d4c77b821e13993d30d02bdb97933a061fbda74f15132f09","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1urw2jna5t23pj24jdmlcgz02qy8694rkrmafysm7p4dkkcqx6m2u0","owners":["dca94fb45aa2192ab26eff8409ea010fa2d4761efa92437e0d5b6b60"],"relays":[{"type":"hostname","hostname":"firewall.adamantium.online","port":3002}],"metadata":{"url":"https://testforge.adamantium.online/otg-sancho.metadata.json","hash":"cbe49b4a77211ce5641a8958914b33f239d65787b67165958e94f12f1c64022b"}},"pool1spv6ts5262ze925mhdasxdcrc50n0eq5ktp7764h6kc97r7dd7z":{"id":"pool1spv6ts5262ze925mhdasxdcrc50n0eq5ktp7764h6kc97r7dd7z","vrfVerificationKeyHash":"719f4a7b25aeded42e3729a1bd29b47c8389fe664f1f8c90039d644361c3d991","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1up7e0lctmgctqjksm0s3sqzqa0pu2ndmg704j0lmuz4q47gr57fwr","owners":["7d97ff0bda30b04ad0dbe1180040ebc3c54dbb479f593ffbe0aa0af9"],"relays":[{"type":"ipAddress","ipv4":"192.168.1.158","port":7001}]},"pool1s49txezsz73m09jvdv5deu7fwa9atln0dg60ze6xqjx5sj4l3fn":{"id":"pool1s49txezsz73m09jvdv5deu7fwa9atln0dg60ze6xqjx5sj4l3fn","vrfVerificationKeyHash":"eb9938878f68c63f0c0d2b9a96e7679ec5ab3c37bb9746bf8b6ae9cb206bc8d3","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"7/100","rewardAccount":"stake_test1up22k6t7wlmlwc4888nr8r020te8ezhthpatpv56006j03s7f38nn","owners":["54ab697e77f7f762a739e6338dea7af27c8aebb87ab0b29a7bf527c6"],"relays":[{"type":"hostname","hostname":"adar-monitor.freeddns.org","port":3012}],"metadata":{"url":"http://tinyurl.com/snet-adar","hash":"12174285d72804e73c883b01d2f645ba37467c2a5fbb133a355da88b067a2474"}},"pool13lr6wv9m55el9ahscn8qmutc80gq9m5ajgawjstj3v5rqm7fpd9":{"id":"pool13lr6wv9m55el9ahscn8qmutc80gq9m5ajgawjstj3v5rqm7fpd9","vrfVerificationKeyHash":"48f8762dd20e68830b05aa9320ee9f0f5dd0173a8a3c73b0a7ad725e039ea4ca","pledge":{"ada":{"lovelace":1000000000000}},"cost":{"ada":{"lovelace":500000000}},"margin":"1/1","rewardAccount":"stake_test1uzpaylcrkxth2rhyrd7u5qkgqeccze9exjc0h7n5wdy73usd0pxpl","owners":["b2f1e813fb3108fe6926717ec6409bc369ae81b485aa2120dc1fa1d7"],"relays":[{"type":"hostname","hostname":"sanchonet3-node.play.dev.cardano.org","port":3001}]},"pool14hwlqytt0kcxz57edu78k5qhqvd0v9m0ae4h9annux2eg8ayq5p":{"id":"pool14hwlqytt0kcxz57edu78k5qhqvd0v9m0ae4h9annux2eg8ayq5p","vrfVerificationKeyHash":"11c83eee77c51c9a60d2ea01ee70611910c2ad4a89e16cee6eaa783adc5b15b4","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uzt80vhpew2f5qkaa5pga5x7r7eps0kpkc758s0ay68aursp0hk4r","owners":["9677b2e1cb949a02dded028ed0de1fb2183ec1b63d43c1fd268fde0e"],"relays":[]},"pool1k3nuy86a7g077j7njdtsr54rxv3355ca3fnx239675nju4898er":{"id":"pool1k3nuy86a7g077j7njdtsr54rxv3355ca3fnx239675nju4898er","vrfVerificationKeyHash":"749e83b1d436209ab75d583ed8773f1afdebdf35f1152fda43545e1c5ef551c4","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/25","rewardAccount":"stake_test1up42qf6yrz0jkgfn0dhvev7ap4ulygt92t36wsvp7km983s30hke6","owners":["6aa02744189f2b21337b6eccb3dd0d79f2216552e3a74181f5b653c6"],"relays":[{"type":"hostname","hostname":"relay1.sanchonet.pool.cardanofoundation.org","port":30004},{"type":"hostname","hostname":"relay2.sanchonet.pool.cardanofoundation.org","port":30004}],"metadata":{"url":"https://sanchonet.pool.cardanofoundation.org/metadata.json","hash":"32930af3be03dea4488f66718fb2f62cddda26c914b9940b94fb9f585a61598f"}},"pool1h722gdd6kx782me0v9zresnds4ajugneq0vl9a0ju7mgvemezdf":{"id":"pool1h722gdd6kx782me0v9zresnds4ajugneq0vl9a0ju7mgvemezdf","vrfVerificationKeyHash":"24e3099f2fdf533c6148c33737c54e908795e13979573bf999df8bc74727fbbe","pledge":{"ada":{"lovelace":1000000000000}},"cost":{"ada":{"lovelace":500000000}},"margin":"1/1","rewardAccount":"stake_test1uzpaylcrkxth2rhyrd7u5qkgqeccze9exjc0h7n5wdy73usd0pxpl","owners":["2f5fde105530993a262d744e534847794d477d2cc5a457312b2014b1"],"relays":[{"type":"hostname","hostname":"sanchonet2-node.play.dev.cardano.org","port":3001}]},"pool1cpxhrrewpu0ltk8fulczrqsj0mgaj8mx8yujzqmmkwp05393ln2":{"id":"pool1cpxhrrewpu0ltk8fulczrqsj0mgaj8mx8yujzqmmkwp05393ln2","vrfVerificationKeyHash":"a612a9fbbf33a50bf64719444423564a567b8cf8da530a6fd53e4469cdc892dc","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1ur0qtgl8rj9jwsmtjvs90dstpprdzvscuxd7z04y57g548gy7q30j","owners":["de05a3e71c8b27436b932057b60b0846d13218e19be13ea4a7914a9d"],"relays":[{"type":"hostname","hostname":"sanchonet.happystaking.io","port":3004}],"metadata":{"url":"https://happystaking.io/poolMetadataSanchonet.json","hash":"88f21480bcd6a5709c1fcd3c8604a18d1e0c40b17966043bf4339184bbcd24de"}},"pool1c6xrqt8nq6zasfmvpk0067je69r2eljh5xa08hsvf0lgzgaw4lr":{"id":"pool1c6xrqt8nq6zasfmvpk0067je69r2eljh5xa08hsvf0lgzgaw4lr","vrfVerificationKeyHash":"e82231789278477533459b806e845ffc7719abfc11a29f486604c65f7ff3668f","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1uq3qf285n6qg8wqu34etec69g0al0y60a7gckntjsyp6mhgawzd20","owners":["2204a8f49e8083b81c8d72bce34543fbf7934fef918b4d728103addd"],"relays":[{"type":"hostname","hostname":"relay.hephy.io","port":9000}],"metadata":{"url":"https://raw.githubusercontent.com/hephy-io/sancho/main/snet.json","hash":"1cffc29ea55b7864fca5854e0ce4d3bae8456de0a6458b2cf6be2d9b22581a78"}},"pool1e8ud28v893mq2nmre2x09ex07ek3seljh4w7a2zphcy5z4sek9v":{"id":"pool1e8ud28v893mq2nmre2x09ex07ek3seljh4w7a2zphcy5z4sek9v","vrfVerificationKeyHash":"36af8b2a8521adf754f98042817887d691066bc40eba545527e8d7a773766143","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1ur94h9va6rmc9lg9gye8686sv6cfyvqaka2w8drf8qlekxqgzxnd2","owners":["cb5b959dd0f782fd0541327d1f5066b092301db754e3b469383f9b18"],"relays":[{"type":"hostname","hostname":"sancho.adanorthpool.com","port":8013}],"metadata":{"url":"https://adanorthpool.com/anpsanchopool.metadata.json","hash":"dbb6db6197a9c9512e65f18b533a91a0db495ea157fcb3e34b480205572d803b"}},"pool1m8glad404zhwsa6k2lalm6qu95ptfffj9uk5drphmu0rsj3mnaz":{"id":"pool1m8glad404zhwsa6k2lalm6qu95ptfffj9uk5drphmu0rsj3mnaz","vrfVerificationKeyHash":"0faf9e2d07c9909291d51e5776fd2715cc1b5e3cf0aa79866cd41f305171d135","pledge":{"ada":{"lovelace":100000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1urqntq4wexjylnrdnp97qq79qkxxvrsa9lcnwr7ckjd6w0cr04y4p","owners":["c13582aec9a44fcc6d984be003c5058c660e1d2ff1370fd8b49ba73f"],"relays":[{"type":"ipAddress","ipv4":"127.0.0.1","port":3001}],"metadata":{"url":"https://my-ip.at/test/testpool.metadata.json","hash":"93a6d4a028620f31b4315cf96a53eb05fa5f1364c4fad75bec43a9cf95b9ee96"}},"pool1m840r7thpj9mxhw33hud3g9jkvjvm00wkw89ul8t06nngjewl6m":{"id":"pool1m840r7thpj9mxhw33hud3g9jkvjvm00wkw89ul8t06nngjewl6m","vrfVerificationKeyHash":"668902c613a1875f7b1b3323fc995cc2c94dace33203d6c7cb042c6da0a9d103","pledge":{"ada":{"lovelace":1000000000000}},"cost":{"ada":{"lovelace":500000000}},"margin":"1/1","rewardAccount":"stake_test1uzpaylcrkxth2rhyrd7u5qkgqeccze9exjc0h7n5wdy73usd0pxpl","owners":["f535d2bfc700116bb07ad9f9a1159d45577e85fc3c472d692780d996"],"relays":[{"type":"hostname","hostname":"sanchonet1-node.play.dev.cardano.org","port":3001}]},"pool1m6prw8mg3ttu45s45e6dyqfsxjzkfk7ln07pktksujsr29ghtxm":{"id":"pool1m6prw8mg3ttu45s45e6dyqfsxjzkfk7ln07pktksujsr29ghtxm","vrfVerificationKeyHash":"452f30d0f5141104287bd3c3a0e2c1b82f8a1be2593c9e1e41b4e94925b928e4","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1urvdtlnh4axqa8heuwtnm699zp4lk3hjqcjh5xrjm68wqdsvfcqzv","owners":["d8d5fe77af4c0e9ef9e3973de8a5106bfb46f206257a1872de8ee036"],"relays":[{"type":"hostname","hostname":"mithril-signer-1.testing-sanchonet.api.mithril.network","port":9091}],"metadata":{"url":"https://tinyurl.com/2xrncehj","hash":"12225f1ea91b643eae68730e5a01e97bd229228b0f52f8374d15b3ef3e050105"}},"pool1as9wfr5422grct7cxnctjvwja0urauwazapjw7y9xl66vz78ae4":{"id":"pool1as9wfr5422grct7cxnctjvwja0urauwazapjw7y9xl66vz78ae4","vrfVerificationKeyHash":"2bfb08731a0945d5c68498a8959deb3b7052ca0d2d3ccfebe9ac3be95eab0389","pledge":{"ada":{"lovelace":500000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1up254pxpxzmrqn7mmsrxyrk2ga3qlsargrhm98c0qyh3zccs58zch","owners":["554a84c130b6304fdbdc06620eca47620fc3a340efb29f0f012f1163"],"relays":[{"type":"ipAddress","ipv4":"64.176.50.202","port":4002}]},"pool17ckkqnsxhvj467ey03jqxjrtgq8reuq6zz7gpnrdv4p52ds25sa":{"id":"pool17ckkqnsxhvj467ey03jqxjrtgq8reuq6zz7gpnrdv4p52ds25sa","vrfVerificationKeyHash":"f2144066d9c5545aec573b6cac041742f7bceed2a9ea23085db2d00d290e6d3f","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"99/100","rewardAccount":"stake_test1ur0407lhwpgq0cdje5ldpmrwgxfxehgz0ztq5efdy9nej6g4dxxdy","owners":["df57fbf7705007e1b2cd3ed0ec6e41926cdd0278960a652d21679969"],"relays":[{"type":"hostname","hostname":"sancho-testnet.able-pool.io","port":6002}],"metadata":{"url":"https://hornan7.github.io/sanchometadata.json","hash":"4e544cca134322ef1fbf5dce57524cc06be1cfe07c545bd49e240b3df536c7d7"}},"pool1lj20psmnkjau2ywmuzlhp44jnfku3w3l0pdyqkn0p08k7e32cx3":{"id":"pool1lj20psmnkjau2ywmuzlhp44jnfku3w3l0pdyqkn0p08k7e32cx3","vrfVerificationKeyHash":"5062b97786383eace8f8364274b531e50dc4cc5d7e5afc8e6ad563da112f4071","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"9999/10000","rewardAccount":"stake_test1uzywv7fwzvaaurpkct7yqg9ayxvdr06rlkldaerw7jmd9rchpy3ut","owners":["e94c611b70b247e748b07f8553e5cce2193f8bdf86f80d0b0b8f5221"],"relays":[{"type":"hostname","hostname":"relay.sancho.cardanostakehouse.com","port":8000}],"metadata":{"url":"https://cardanostakehouse.com/523bc64b-d2ad-42c3-81e7-eb0.json","hash":"b65998c78972998aa13b0e2ae8f032b58583f2d6df9b42ea6272f16bfff23b0b"}}},"id":"queryLedgerState/stakePools-hfkgvfollxkiih0q"} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryLedgerState-stakePools-b83473f5b74f365f842c3ba6968d4e3e.json b/fixtures/test/ogmios/queryLedgerState-stakePools-b83473f5b74f365f842c3ba6968d4e3e.json new file mode 100644 index 0000000000..8a1e2286fd --- /dev/null +++ b/fixtures/test/ogmios/queryLedgerState-stakePools-b83473f5b74f365f842c3ba6968d4e3e.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryLedgerState/stakePools","result":{"pool1q95luz38nhsw6h7mxud8tptc6mxvnsczhanw4j5htk8h2ltlf3k":{"id":"pool1q95luz38nhsw6h7mxud8tptc6mxvnsczhanw4j5htk8h2ltlf3k","vrfVerificationKeyHash":"00e024fbc63daf0af69eebc5741e7ff183b890ef2628e9bfd4e2bc4d6d1b16b8","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":345000000}},"margin":"3/20","rewardAccount":"stake_test1uztsmrxurfw7v3gjz04n8m45kngf4fwhfzxez9wa24rmdxclut9y5","owners":["970d8cdc1a5de6451213eb33eeb4b4d09aa5d7488d9115dd5547b69b"],"relays":[{"type":"ipAddress","ipv4":"83.58.170.227","port":6000}],"metadata":{"url":"https://not.me","hash":"e3568b0190e59d344e0a9803d31ac9fe4ca11c5861b6e3b06527343adbdefae9"}},"pool1qncwwllw9nwtu7sl7zqw3fpyh4t3q6nhludryfwv0jyqjygd46d":{"id":"pool1qncwwllw9nwtu7sl7zqw3fpyh4t3q6nhludryfwv0jyqjygd46d","vrfVerificationKeyHash":"9b960c725b707c79a4aade62a362be9f35b5b0d7615b8bdd3bfd72a77b0a32a4","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":345000000}},"margin":"1/20","rewardAccount":"stake_test1ur4n0pv3cagnah7atw58qr8an8vm8f75tq5u2q9h925nwasuxt25m","owners":["eb378591c7513edfdd5ba8700cfd99d9b3a7d45829c500b72aa93776"],"relays":[{"type":"hostname","hostname":"beadapool.ddns.net","port":6001}],"metadata":{"url":"https://beadapool.com/media/poolMetaDatapreview.json","hash":"c760f6e23539c052bff72bbc0d921a0663a0fea445b401871d5f65eb3debfc55"}},"pool1qal80uhlj949mgv0ecvdkmgqjdn5q27wmpaj4crnr5e9v6qmsv7":{"id":"pool1qal80uhlj949mgv0ecvdkmgqjdn5q27wmpaj4crnr5e9v6qmsv7","vrfVerificationKeyHash":"d498ef12879315f2b3b9bf3d944a42ae4062203db8ebc78236d63f3697f1804c","pledge":{"ada":{"lovelace":420000000}},"cost":{"ada":{"lovelace":420000000}},"margin":"69/1000","rewardAccount":"stake_test1uzpafaxd4q5p7adccdefpnv69dkwlpm7dpkpm3yefxzeluc4z24ec","owners":["83d4f4cda8281f75b8c37290cd9a2b6cef877e686c1dc49949859ff3"],"relays":[{"type":"hostname","hostname":"preview.world.bbhmm.net","port":6200}],"metadata":{"url":"https://pool.bbhmm.net/poolmeta-preview.json","hash":"885cbb02d004f75fad5716c878a6074a9c1bd62b3003d1896b1d27831d67239a"}},"pool1p9xu88dzmpp5l8wmjd6f5xfs9z89mky6up86ty2wz4aavmm8f3m":{"id":"pool1p9xu88dzmpp5l8wmjd6f5xfs9z89mky6up86ty2wz4aavmm8f3m","vrfVerificationKeyHash":"2dd02fc85a8ded714d3d56a684f85d741cef553756d760c8c4d5ae325ab6a1a1","pledge":{"ada":{"lovelace":1111000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1uzsf4dc8l9r2uxgwk7vpladqf09vvduw43z6cd0p96ru0gcpg49cx","owners":["a09ab707f946ae190eb7981ff5a04bcac6378eac45ac35e12e87c7a3"],"relays":[{"type":"hostname","hostname":"relay-m.fluxpool.cc","port":5001}],"metadata":{"url":"https://cylonyx.github.io/testnet.json","hash":"99e451a46f89b17502196457698bde37d604fe74ef19a8c0cb8518da72b1ecf1"}},"pool1p90428kec03mjdya3k4gv5d20w7lmed7ca0snknef5j977l3y8l":{"id":"pool1p90428kec03mjdya3k4gv5d20w7lmed7ca0snknef5j977l3y8l","vrfVerificationKeyHash":"af790879fc1dc4a8c00147aebc13e95585d641b76986d9a449a1ba4652ba77ad","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/2","rewardAccount":"stake_test1uruf9dc3kf35aqnng5wz38kt03h9jk6y5gdszy69nppkylqdk8agr","owners":["f892b711b2634e8273451c289ecb7c6e595b44a21b0113459843627c"],"relays":[{"type":"hostname","hostname":"water.lbcrypt.com","port":9600}],"metadata":{"url":"https://www.lbcrypt.com/json/LBCPP.json","hash":"6074e009fcb59f6ef28337412168e1b5391b42e6cec8dc01f7291babf6d2771d"}},"pool1p835jxsj8py5n34lrgk6fvpgpxxvh585qm8dzvp7ups37vdet5a":{"id":"pool1p835jxsj8py5n34lrgk6fvpgpxxvh585qm8dzvp7ups37vdet5a","vrfVerificationKeyHash":"e67d6ccc4b3b0ca3e61ad09ccf2094b4fbf4eee929e8995c52fa0f32a43a707c","pledge":{"ada":{"lovelace":100000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1upn7ehn9g6e9cqp7jcmuv5a79avzxavxe6g6fmfwttsm6lqa9kp7c","owners":["67ecde6546b25c003e9637c653be2f58237586ce91a4ed2e5ae1bd7c"],"relays":[{"type":"hostname","hostname":"firewall.adamantium.online","port":3000}],"metadata":{"url":"https://testforge.adamantium.online/otg-preview.metadata.json","hash":"0b15c664cf2883a8d68140f852963f8c7f8adac538ddf1f6cfab60444465ee5e"}},"pool1pt39c4va0aljcgn4jqru0jhtws9q5wj8u0xnajtkgk9g7lxlk2t":{"id":"pool1pt39c4va0aljcgn4jqru0jhtws9q5wj8u0xnajtkgk9g7lxlk2t","vrfVerificationKeyHash":"d9f1792aeb20bf814c367e6b3dd5e2c3f4c7f91f45247da2d0de451a2a2c1f85","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1uzftx5dwygs4k88svkh4gp6hz4l628ydvskx5yzff55wlmskas3cr","owners":["92b351ae22215b1cf065af540757157fa51c8d642c6a10494d28efee"],"relays":[{"type":"hostname","hostname":"preview.bladepool.com","port":3001}],"metadata":{"url":"https://public.bladepool.com/metadata.json","hash":"2738e2233800ab7f82bd2212a9a55f52d4851f9147f161684c63e6655bedb562"}},"pool1pn9sffcqqzkx70m0gujks4h3wf8p4y706t2f0cjcyreekg83wtf":{"id":"pool1pn9sffcqqzkx70m0gujks4h3wf8p4y706t2f0cjcyreekg83wtf","vrfVerificationKeyHash":"3cfeffec7d5b5dbbc4f0494271fad41952fdb82937189fb3f2581d9de3fad81b","pledge":{"ada":{"lovelace":250000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1up8dnh6ywzs96upw6ycmeafzmkvrv096njjkphgqzuts0wgnxsaqg","owners":["4ed9df4470a05d702ed131bcf522dd98363cba9ca560dd00171707b9"],"relays":[{"type":"hostname","hostname":"preview-r1.panl.org","port":3015}],"metadata":{"url":"https://preview-metadata.panl.org","hash":"a2d8a47fc4d3a6e707487b65b3ab790e6fff71c2afd72f0fe17bc5e523024019"}},"pool1phj3kpraf3vgn0zzlugpts8k6eps8d3fgp9ddceu4s43cq00nzr":{"id":"pool1phj3kpraf3vgn0zzlugpts8k6eps8d3fgp9ddceu4s43cq00nzr","vrfVerificationKeyHash":"d4d04f919daf4e89a556f5555a2a68ba89ccf03f022ee77954b1bf1c37a7c8ff","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1up046thgsc2fg0wcwfzvmpmy6r6c0psanu9wyxg8vcknt9sumrgc7","owners":["5f5d2ee88614943dd87244cd8764d0f587861d9f0ae21907662d3596"],"relays":[{"type":"hostname","hostname":"https://aggregator.dev-preview.api.mithril.network/"}],"metadata":{"url":"https://mithril.network/tbd.json","hash":"5e96bfc37d05582545c91727d73e11a26fa0ebcd4e482a9714d02ab96e83ed19"}},"pool1p73yrd7vzwkkjd2rff4g683smhlm3jkg45f2hwm79cke6uxxwq9":{"id":"pool1p73yrd7vzwkkjd2rff4g683smhlm3jkg45f2hwm79cke6uxxwq9","vrfVerificationKeyHash":"da1d45782040dd4862a9f97ac9fa706ca14f8f2f2823a0e2a466932cf530da6e","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1urnuwkjxcf0erfm53fx9tnkvs6ye0shcwk3lt0wzzy500tcu0xf8f","owners":["e7c75a46c25f91a7748a4c55cecc868997c2f875a3f5bdc21128f7af"],"relays":[{"type":"hostname","hostname":"api.monrma.ml","port":6020}],"metadata":{"url":"https://api.monrma.ml/meta/JOSEP.json","hash":"6c133a6ba49006eee1fdd1525662d64de10f4a54566e715246525b3b386f0c02"}},"pool1zyvx690fps6a9m3m89q6fwcfgd8jyupzgv8wrfpvd0fm5cyzxd0":{"id":"pool1zyvx690fps6a9m3m89q6fwcfgd8jyupzgv8wrfpvd0fm5cyzxd0","vrfVerificationKeyHash":"e0c09cfd7e6b1766efe46f4297d5ada1a5f8b006c1ed72535e16c6fd2f384174","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/100","rewardAccount":"stake_test1uzzx65ylw8yrkeusmfwa6exesgpzlw74630cxusgq3jn9jqrgsrjc","owners":["846d509f71c83b6790da5ddd64d982022fbbd5d45f837208046532c8"],"relays":[{"type":"ipAddress","ipv4":"129.152.11.126","port":3002}],"metadata":{"url":"https://raw.githubusercontent.com/stefanosu-code/stpz/a/s2.j","hash":"0bf71440af0a351555045ae2a59e65c8661748a2781476f9bd560871afb2069f"}},"pool1z9nsz7wyyxc5r8zf8pf774p9gry09yxtrlqlg5tsnjndv5xupu3":{"id":"pool1z9nsz7wyyxc5r8zf8pf774p9gry09yxtrlqlg5tsnjndv5xupu3","vrfVerificationKeyHash":"b5971d1f29a9938574aa98cf5a8437a8245239644fe6dcaa8b22b92ed2b00e90","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/9a065d69-ef59-4aff-983d-e34.json","hash":"92bab22abc33ea5fa2be2f515639bec213e782b5f417b3cc0441fd115172d171"}},"pool1rzgvf9rytug9p3hz6a9q8zeu3mp6trl70qdyw0g9c7ywzy984yr":{"id":"pool1rzgvf9rytug9p3hz6a9q8zeu3mp6trl70qdyw0g9c7ywzy984yr","vrfVerificationKeyHash":"0e0c0f257842b44b19dda1a20d8e406401f7696725f1c00a5b2768a4c684a089","pledge":{"ada":{"lovelace":70000000000}},"cost":{"ada":{"lovelace":345000000}},"margin":"3/25","rewardAccount":"stake_test1upxxj9un9j6xyaxkxnw0n2hajye3ux6qxn53ex7g4xwdh2cq3xsrd","owners":["4c6917932cb46274d634dcf9aafd91331e1b4034e91c9bc8a99cdbab"],"relays":[{"type":"hostname","hostname":"adarelay-t2-1.nanyka.com","port":1856}],"metadata":{"url":"https://nanyka.com/cardanospo/poolmeta_preview.json","hash":"a14630b7010397fc9bf309f59618b613698851bc1ac5772fd43717405b426bf5"}},"pool1rwwmnhgsnyzhzpg89lgq4k6uc38qadsdnet9l2xgv34hsjxzj2d":{"id":"pool1rwwmnhgsnyzhzpg89lgq4k6uc38qadsdnet9l2xgv34hsjxzj2d","vrfVerificationKeyHash":"a4057bb1feefee1f968888a3596a6ff463b443ef9d9919398c1b4dbe9a493597","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"99/100","rewardAccount":"stake_test1urarrlsypaptr9lrx8c65qr5qjfd4a6j893caw33mwpxsjgqfxdem","owners":["fa31fe040f42b197e331f1aa00740492daf75239638eba31db826849"],"relays":[{"type":"hostname","hostname":"spec1-staging.spirestaking2.com","port":3005}],"metadata":{"url":"https://data.spireblockchain.com/ADA-PREVIEW/SPF/pool_0.json","hash":"e11362ceaa7817a979a1f703268a0d63a9e65d48e35e5879e4a7e693f47253ed"}},"pool1r0tln8nct3mpyvehgy6uu3cdlmjnmtr2fxjcqnfl6v0qg0we42e":{"id":"pool1r0tln8nct3mpyvehgy6uu3cdlmjnmtr2fxjcqnfl6v0qg0we42e","vrfVerificationKeyHash":"0bf04a518f6e9a49fbc3ca8b98bec244874fa9939427156ec2af28fa2bfdab11","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1uraat6a6egphv996jz7ncmzncp8689fzum4up72c8xfaf4s04shmw","owners":["fbd5ebbaca037614ba90bd3c6c53c04fa39522e6ebc0f9583993d4d6"],"relays":[{"type":"hostname","hostname":"mithril-signer-2.testing-preview.api.mithril.network","port":9092}],"metadata":{"url":"https://tinyurl.com/2nx2ty2d","hash":"8cc5e635ed38182d9c4680129dc8815f7c2af1d0d7c34e36781139a26a47d650"}},"pool1rk2y9gx6vll8lawzdqlky5p2a3ypzsxg07arg8gmhkjj2905035":{"id":"pool1rk2y9gx6vll8lawzdqlky5p2a3ypzsxg07arg8gmhkjj2905035","vrfVerificationKeyHash":"a86606621866917a797374a33b0dbb73afdb27b82abfe1facdf99f527cc7b434","pledge":{"ada":{"lovelace":100000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/20","rewardAccount":"stake_test1uz6yw4xj9lfkv8dweq3m64vwnmm8c3hpleufjzqf866ar8qjxc6cs","owners":["b44754d22fd3661daec823bd558e9ef67c46e1fe789908093eb5d19c"],"relays":[{"type":"hostname","hostname":"sully.crabdance.com","port":6004}],"metadata":{"url":"tinyurl.com/4uszu5zt","hash":"62710fed07d182806c647d4a2034eccb14035e57f9bb4899aff9ec1c461ee4ae"}},"pool1yq5q3unkyr764243l4v3gca6m42jlg04df9k7f5hv00lsjhyj4d":{"id":"pool1yq5q3unkyr764243l4v3gca6m42jlg04df9k7f5hv00lsjhyj4d","vrfVerificationKeyHash":"d6d05e32b4c2eb2e62cb5659d118061473360c2db23a213c377edb2ead2cf591","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/40","rewardAccount":"stake_test1urty9s8ufz8kydh8wfz6k9cqsj4v2q2k5wdu8wtetvlz4fs7adk6p","owners":["d642c0fc488f6236e77245ab170084aac50156a39bc3b9795b3e2aa6"],"relays":[{"type":"hostname","hostname":"pool.sudosu.cyou","port":30443},{"type":"hostname","hostname":"pool.sudosu.cyou","port":30444}],"metadata":{"url":"https://ado-pool.web.app/poolMetadata.json","hash":"aeaaf5c46c1466f65ff731fc3cc82f006acfd0aaedb4d4f6ff665f04224a1bd1"}},"pool1yphncqvpc4n49c4ya3mys7uwpwa25892r70gzkpqglenv093qge":{"id":"pool1yphncqvpc4n49c4ya3mys7uwpwa25892r70gzkpqglenv093qge","vrfVerificationKeyHash":"83602a44cf3b951a3ef83a4d868852ccfa50cc841e93212b302a67c8d1cd9144","pledge":{"ada":{"lovelace":8000000000}},"cost":{"ada":{"lovelace":345000000}},"margin":"1/10","rewardAccount":"stake_test1urt0mxys755epyacjdacm4e0wyyr7kd603tzxrqzstj7auc5l9456","owners":["d6fd9890f5299093b8937b8dd72f71083f59ba7c56230c0282e5eef3"],"relays":[{"type":"hostname","hostname":"129.213.55.211","port":6000}],"metadata":{"url":"https://cardano-blockhouse.de/preview/poolMetaData.json","hash":"5561fb2b9a8b234a4ae4aee30b87916d5b4dd8b028dcda21a70dfee465d3de8f"}},"pool1ynfnjspgckgxjf2zeye8s33jz3e3ndk9pcwp0qzaupzvvd8ukwt":{"id":"pool1ynfnjspgckgxjf2zeye8s33jz3e3ndk9pcwp0qzaupzvvd8ukwt","vrfVerificationKeyHash":"dbdd412069ed405b8efe1f30d4e7a8ea551a8cbfc949b1a462936e0b55ec632a","pledge":{"ada":{"lovelace":400000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1urn5vcltkemnl8nnx3xt4ucsej3v45y0r5s4xgkl9v24jpsxs8v3h","owners":["e74663ebb6773f9e73344cbaf310cca2cad08f1d215322df2b155906"],"relays":[{"type":"hostname","hostname":"node1.cardano.gratis","port":6501},{"type":"hostname","hostname":"node2.cardano.gratis","port":6502}],"metadata":{"url":"https://cardano.gratis/poolMetaDataPreView.json","hash":"8bcb8efe6973b8b6bd0918cd356735ff3ce0ca41276fac6fb4b50b900fbcebce"}},"pool1yu60zjc6ykj22ns69e8w5me469r4k4805706vz2mvrnz5qvvfz7":{"id":"pool1yu60zjc6ykj22ns69e8w5me469r4k4805706vz2mvrnz5qvvfz7","vrfVerificationKeyHash":"e84a8a24359b57aec037671ec8597f73ca6d231f06174e7b58c1536ad0f28c9e","pledge":{"ada":{"lovelace":1000}},"cost":{"ada":{"lovelace":500000000}},"margin":"1/1000","rewardAccount":"stake_test1uzp3y24gpe5zjw0nzsc04tteyuhr6yxqpcvl4cg9x6227gcr4s4cs","owners":["83122aa80e682939f31430faad79272e3d10c00e19fae1053694af23"],"relays":[]},"pool19p0rndwuhsyzwjt3v3s946yrq3je8usgcqwn32xjfkd52f3znjf":{"id":"pool19p0rndwuhsyzwjt3v3s946yrq3je8usgcqwn32xjfkd52f3znjf","vrfVerificationKeyHash":"18a7b9fa81478d76b1797a5935f1ba4564c06390ecffb208a02283993f179ceb","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1up829zqr979f4svv7daykuk000nwmvtkas8qpy8rld4t7wqyu059y","owners":["4ea288032f8a9ac18cf37a4b72cf7be6edb176ec0e0090e3fb6abf38"],"relays":[{"type":"hostname","hostname":"mithril-signer-1.dev-preview.api.mithril.network","port":9091}],"metadata":{"url":"https://tinyurl.com/2xn8c23m","hash":"d907a12c9750aa8536fe24bf2e904cef6acc9801d952e851b76530e743244491"}},"pool190ce9qhpzwzveasvngas7kmwqrn54mfvhk9unqmuesykvtadu8l":{"id":"pool190ce9qhpzwzveasvngas7kmwqrn54mfvhk9unqmuesykvtadu8l","vrfVerificationKeyHash":"ecaaf8a89ead238b71ae9054487c229c1c6bc327062c5211dea2ae78c7cb0280","pledge":{"ada":{"lovelace":1000000}},"cost":{"ada":{"lovelace":1130000000}},"margin":"1/100","rewardAccount":"stake_test1uz5qfpx4786s0n847grlqcfrg5ja2g980jtnkfal2jxnaccg69qk0","owners":["a80484d5f1f507ccf5f207f061234525d520a77c973b27bf548d3ee3","c9dc49a676087ba0fb1ab1f28b209e647b4139626d732455bb7d5582","f4cceaa5fff7b592e39519942ea8c3b823f3fee622bb3c81a5f5150f"],"relays":[{"type":"hostname","hostname":"us.netspectrum.com","port":13001}],"metadata":{"url":"http://us.netspectrum.com:13002/pool-meta-data.json","hash":"6e31d534b0d8bdde4ce9bd04ac8d7a6906b680304a3150400304c46f0f393af5"}},"pool1xe7ey753aw0v79tysaumamkgcugpw9txahxwrrltqjpx25adrkr":{"id":"pool1xe7ey753aw0v79tysaumamkgcugpw9txahxwrrltqjpx25adrkr","vrfVerificationKeyHash":"5837fb2c83c6c2808deb5269be449a4c16cd337a7a27d379e77587f5fce73ce9","pledge":{"ada":{"lovelace":65000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/200","rewardAccount":"stake_test1ur7a6w4l2tkz3p7krp8y6807lnqd6e03awrstq644wfaksczmnpth","owners":["fddd3abf52ec2887d6184e4d1dfefcc0dd65f1eb87058355ab93db43"],"relays":[{"type":"ipAddress","ipv4":"45.32.18.201","ipv6":"2001:19f0:7001:24a6:5400:4ff:fe31:9996","port":4002}],"metadata":{"url":"https://git.io/JI2Zk","hash":"d50f5e2e137f291889af50e054025af04bdc487e747c6cfa2521810157a5dfe6"}},"pool18pn6p9ef58u4ga3wagp44qhzm8f6zncl57g6qgh0pk3yytwz54h":{"id":"pool18pn6p9ef58u4ga3wagp44qhzm8f6zncl57g6qgh0pk3yytwz54h","vrfVerificationKeyHash":"82419eaa78194ea40711dea37ab068e6ee101dd7785fe9e41e9acd4b98290d49","pledge":{"ada":{"lovelace":1659000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1urpl4kvj3jfn3zxzxud9px6she3suks5fdyygyke7nnpkcslky9um","owners":["c3fad9928c933888c2371a509b50be630e5a144b484412d9f4e61b62"],"relays":[{"type":"ipAddress","ipv4":"51.104.251.142","port":3001}],"metadata":{"url":"https://adacapital.io/adact_preview.json","hash":"e345a478726731a08900d2cbad4b8455815d41b562fe2b862a3d8fd2c3e36d78"}},"pool18r62tz408lkgfu6pq5svwzkh2vslkeg6mf72qf3h8njgvzhx9ce":{"id":"pool18r62tz408lkgfu6pq5svwzkh2vslkeg6mf72qf3h8njgvzhx9ce","vrfVerificationKeyHash":"a1b272e77f8d5cebc04ba482dacba825e8f7f59251d95746e8ff23864e0c89ee","pledge":{"ada":{"lovelace":100000000000000}},"cost":{"ada":{"lovelace":500000000}},"margin":"1/1","rewardAccount":"stake_test1uzuklnhnhy634a5rf0v9pcaf0pva002mw2wjf0ekg6h2encat3ykr","owners":["788cf0519348fefaf3c721c5f5bd60b195b444fa0d8fb4512dc259be"],"relays":[{"type":"hostname","hostname":"preview-node.world.dev.cardano.org","port":30002}]},"pool18xr0tmqrqffd7yu5jh4pq7hs4eezkremxmgzkq8ua4y82dmmrxp":{"id":"pool18xr0tmqrqffd7yu5jh4pq7hs4eezkremxmgzkq8ua4y82dmmrxp","vrfVerificationKeyHash":"d9df3f4eee37db91a204ef07d8240e4822d8a1d0c0009d2384e7057dcd9cd7c8","pledge":{"ada":{"lovelace":210000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"69/10000","rewardAccount":"stake_test1ur9pv4652sv524d5qdy9q5h354er45jc3s562jp6vjykwwqyz0kzj","owners":["ca16575454194555b403485052f1a5723ad2588c29a5483a64896738"],"relays":[{"type":"ipAddress","ipv4":"130.162.231.122","port":6001}],"metadata":{"url":"https://tinyurl.com/2ku8unuf","hash":"f5d13701d87a7a6d2642c194c7517a411ac662bfe63fa1d1c63f7558ed83e7ea"}},"pool18x5zg95n59xvysu3rq7ygqn6f842ud29dlcc5jmw97xkv2renhy":{"id":"pool18x5zg95n59xvysu3rq7ygqn6f842ud29dlcc5jmw97xkv2renhy","vrfVerificationKeyHash":"eb7084adcbbe7c2f29e4ad162969dfc80ec4d53a1598d2b4277340c29fd99b35","pledge":{"ada":{"lovelace":9400000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"99/100","rewardAccount":"stake_test1upa7k9ag7zpst5h63lpxa9syq5l4wqk2p2qjvfc04j4ncygq73sxl","owners":["7beb17a8f08305d2fa8fc26e9604053f5702ca0a8126270facab3c11"],"relays":[{"type":"ipAddress","ipv4":"139.218.11.14","port":6005},{"type":"ipAddress","ipv4":"14.201.4.90","port":6005},{"type":"ipAddress","ipv4":"14.201.4.90","port":6006}],"metadata":{"url":"https://dpadapools.com/preview1meta.json","hash":"fafe0366055360d905a2f12da33af561518ae141151fadc9a8a61de850c45664"}},"pool18cq0sr4ryw4t63hvgmdp00z7f8h3hgxef0gjldsgk6j75ajza6y":{"id":"pool18cq0sr4ryw4t63hvgmdp00z7f8h3hgxef0gjldsgk6j75ajza6y","vrfVerificationKeyHash":"18c331fcf6535b1d597c8c661c54eedc36029982c3a3b9779e1525ce73b8d884","pledge":{"ada":{"lovelace":10000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"9999/10000","rewardAccount":"stake_test1uza6lr2dqs8skq7wut7rp77xvn42w67gsqslpca3r6v6kwqxmcuup","owners":["9ca82a28ceafb9b3bbd77faf6ac500519e6fcbd54f49ef387ca507ab"],"relays":[{"type":"hostname","hostname":"relay.preview.cardanostakehouse.com","port":11000}],"metadata":{"url":"https://cardanostakehouse.com/459b8a9e-b96a-43cc-9981-970.json","hash":"e5e31422e1e2bc34d9ddc87aa974ffc841079a0773dc6972b6efbdb17c8d0ffe"}},"pool18u47gq2ps4hqawl2sfr8uu8rn4yvkue7c68mw45v2ra4wj7pdx0":{"id":"pool18u47gq2ps4hqawl2sfr8uu8rn4yvkue7c68mw45v2ra4wj7pdx0","vrfVerificationKeyHash":"63de13cac6902f7b63a6530ab41297734554bc7932a68496dce10aa187da8bfc","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uzmxaaxxnrk7qcmx7mr3dtshc6e4xgfh5t5w8e690msqtyqgnzx08","owners":["b0348c669fe3cb7446b5084a669e304dd1cff63762352e8355e14482","b66ef4c698ede06366f6c716ae17c6b3532137a2e8e3e7457ee00590"],"relays":[{"type":"hostname","hostname":"4728f95d.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://4728f95d.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool1grvqd4eu354qervmr62uew0nsrjqedx5kglldeqr4c29vv59rku":{"id":"pool1grvqd4eu354qervmr62uew0nsrjqedx5kglldeqr4c29vv59rku","vrfVerificationKeyHash":"5ad90f4be69faac1c7e216cd50631240db41842b5a43f2ce344670fa7219a6c6","pledge":{"ada":{"lovelace":100000000000000}},"cost":{"ada":{"lovelace":500000000}},"margin":"1/1","rewardAccount":"stake_test1uzuklnhnhy634a5rf0v9pcaf0pva002mw2wjf0ekg6h2encat3ykr","owners":["f631370cc87882bf5e14ab72534caf2655d0a2a50a9a8a3820bb6f4a"],"relays":[{"type":"hostname","hostname":"preview-node.world.dev.cardano.org","port":30002}]},"pool1gslhruyd8pk4f6am9zjjzgwuvetge6tztswwfrjqpnvdsex3455":{"id":"pool1gslhruyd8pk4f6am9zjjzgwuvetge6tztswwfrjqpnvdsex3455","vrfVerificationKeyHash":"4173aad927f4be2a67adf068fcb45871ecac8614864d7af2e079502109e81644","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/2","rewardAccount":"stake_test1ur5p8rcnye82hu4ukkt8xru2hqxa3f9z58pe53qkl9wzz0sn83hhf","owners":["e8138f13264eabf2bcb596730f8ab80dd8a4a2a1c39a4416f95c213e"],"relays":[{"type":"hostname","hostname":"spec2-staging.spirestaking2.com","port":3006}],"metadata":{"url":"https://data.spireblockchain.com/ADA-PREVIEW/SPF/pool_1.json","hash":"9f4e03dd87a814ef9407212ca61355edd9ff266d29a14eb43ad8ad312851b2bc"}},"pool1fr8hdmcl5vadqdxrtdks6vzc44ddqmxpzfuxeuezjt965z8hr04":{"id":"pool1fr8hdmcl5vadqdxrtdks6vzc44ddqmxpzfuxeuezjt965z8hr04","vrfVerificationKeyHash":"4b4e8c37e61a53313028a84eef9bcd1d0ddc77c5da6570be8d23ab77e0088318","pledge":{"ada":{"lovelace":100}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/10","rewardAccount":"stake_test1uzp3y24gpe5zjw0nzsc04tteyuhr6yxqpcvl4cg9x6227gcr4s4cs","owners":["83122aa80e682939f31430faad79272e3d10c00e19fae1053694af23"],"relays":[]},"pool1fv5dyzcaydlj3gvkxqdjsxvey29cvk5zz8jjxncqhch4xxj3lgr":{"id":"pool1fv5dyzcaydlj3gvkxqdjsxvey29cvk5zz8jjxncqhch4xxj3lgr","vrfVerificationKeyHash":"4ab5835f2302ea9d183e1d56143ee82e224657f46403ffc2bc0c4a557f1afeb6","pledge":{"ada":{"lovelace":1104000000}},"cost":{"ada":{"lovelace":411000000}},"margin":"1/100","rewardAccount":"stake_test1ur9h9qtr739mhuypqmhfxvzux3g9h0tksew8w6ravaj3t8qacq6d9","owners":["c9dc49a676087ba0fb1ab1f28b209e647b4139626d732455bb7d5582","cb728163f44bbbf08106ee93305c34505bbd76865c77687d6765159c","f4cceaa5fff7b592e39519942ea8c3b823f3fee622bb3c81a5f5150f"],"relays":[{"type":"hostname","hostname":"us.netspectrum.com","port":13001}],"metadata":{"url":"http://us.netspectrum.com:13002/pool-meta-data.json","hash":"41bbeb6b2f37c5c9195c4c816fb9b641723b92ba14ecf5f4adf210155b08d0e3"}},"pool1fw9mq9eyrp5yydl3njau2568jal62rx5f8anp2llt0e5s3pl3py":{"id":"pool1fw9mq9eyrp5yydl3njau2568jal62rx5f8anp2llt0e5s3pl3py","vrfVerificationKeyHash":"171fdc0c6430bddfdc725553a2d84d01042cfb586f1e4b546853da5d96a604db","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uq27femrn9wj07uad23waxfnc29f7wk86s9mddtp7qhlepcnk0r4r","owners":["15e4e763995d27fb9d6aa2ee9933c28a9f3ac7d40bb6b561f02ffc87"],"relays":[{"type":"hostname","hostname":"d8bdbfbe.cardano-relay.bison.run","port":1338}],"metadata":{"url":"https://d8bdbfbe.cardano-metadata.bison.run/metadata.json","hash":"64c1813d814e5c2abb5f65864ec26f0b060d49f3d206a31f34aa6428d7b682e3"}},"pool1fw7yf4mehfuszpdf2g0u72gu8d948qamwut5c6jm3d3lkj3e4an":{"id":"pool1fw7yf4mehfuszpdf2g0u72gu8d948qamwut5c6jm3d3lkj3e4an","vrfVerificationKeyHash":"838ca6096cff572b788d840445bf2167345f3d87485133ebcbfc729af016ee14","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uzulxfzccykl6xl659glxnfrvkr9jr3dled8g50m4gfe2lg6a5wde","owners":["b9f32458c12dfd1bfaa151f34d236586590e2dfe5a7451fbaa13957d","fcdeb3cb17a93f01b50d1265438fdd18de6b8d6066aebaa8e40d48ea"],"relays":[{"type":"ipAddress","ipv4":"162.55.3.29","port":3003}],"metadata":{"url":"https://foo.bat/poolmeta.json","hash":"cd1585d8931ff5f3b9397ee7e1b7fe4747209c5cd1a3afbd22600b167eef0b0c"}},"pool1fsxwamyfh5aqwg707m69zpfvwyrj5fz5ep7a8yk92wnavck4pdf":{"id":"pool1fsxwamyfh5aqwg707m69zpfvwyrj5fz5ep7a8yk92wnavck4pdf","vrfVerificationKeyHash":"e091185050f16c36c140ff83df893a6ee90abc4e4b6c9e6f61feec71fb2af439","pledge":{"ada":{"lovelace":1000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/50","rewardAccount":"stake_test1up50rxfvpmvh2k0e9ku7vypfk5w8280j3w6nm4nkk76qkfcqpc9wn","owners":["68f1992c0ed97559f92db9e61029b51c751df28bb53dd676b7b40b27"],"relays":[{"type":"ipAddress","ipv4":"154.12.248.114","port":6001}],"metadata":{"url":"https://raw.githubusercontent.com/hodlonaut/a/master/t1.json","hash":"81986b8f246cb39979af55fc01215f193df2dc07107989b886e131633e880e43"}},"pool12q7fskmv767qv8yn7mvcxj5azam9cdg0lpm3cajjqr2rqxc7y6a":{"id":"pool12q7fskmv767qv8yn7mvcxj5azam9cdg0lpm3cajjqr2rqxc7y6a","vrfVerificationKeyHash":"d1dc9125cf57397889b155799e3e6e89ce70c41b6b3b94d3e6e08a48bc4ea5e3","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"19/1000","rewardAccount":"stake_test1urfrzvw6yyunusyx4creuzysuyly3tqkj353v7fv58jl6hcfyzy5d","owners":["d23131da21393e4086ae079e0890e13e48ac16946916792ca1e5fd5f"],"relays":[{"type":"hostname","hostname":"pv.blockchainlens.org","port":6306}],"metadata":{"url":"https://raw.githubusercontent.com/bclens/cardano/main/pv.json","hash":"82dc82447da80029382fb904948c09431e0848260a504bcf4a75c575a040b05e"}},"pool12645cty3fsa7a79vx2nsd8yupl3quyhr6h3vqk6duqn0yy7vkv0":{"id":"pool12645cty3fsa7a79vx2nsd8yupl3quyhr6h3vqk6duqn0yy7vkv0","vrfVerificationKeyHash":"c1b125e070bea224be6663ebf5cf748194a70cf6aa8c16885b56e684d12450d5","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/bf2f257f-2776-4c14-aae4-1c1.json","hash":"98db945cdff93d149a30e0d9010927f1417fb1b9796c63a2bcbb85cd551b2fb6"}},"pool1tycl9a9cqgffccgsh0867u65qpk0qlm43kjqggepmflajsmcds6":{"id":"pool1tycl9a9cqgffccgsh0867u65qpk0qlm43kjqggepmflajsmcds6","vrfVerificationKeyHash":"e89c87e0d1527f047cdb4254d8139987124e9a06d07538bfb4ceda29f43ee098","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uzd5msh6y083l597yacq5pcgs82pzfrm50j3nemmynmqfcsg2m4r0","owners":["9b4dc2fa23cf1fd0be27700a070881d411247ba3e519e77b24f604e2"],"relays":[{"type":"hostname","hostname":"e566964e.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://e566964e.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool1t9uuagsat8hlr0n0ga4wzge0jxlyjuhl6mugrm8atc285vzkf2e":{"id":"pool1t9uuagsat8hlr0n0ga4wzge0jxlyjuhl6mugrm8atc285vzkf2e","vrfVerificationKeyHash":"957d1696507a9f88c641db39cc2e34274456efeee9538a2bb4f332f44fb1d25c","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1uq9yp8wqvgpnucpe6s6yavnrvqnuykadx8y40sv0c5ur93gapzeka","owners":["0a409dc062033e6039d4344eb2636027c25bad31c957c18fc53832c5"],"relays":[{"type":"hostname","hostname":"mithril-signer-3.testing-preview.api.mithril.network","port":9092}],"metadata":{"url":"https://tinyurl.com/2qvmy5xy","hash":"adaff9f5327ad0a3b9a47ba88a14100235915c80da2806f9bf8d271dbc0a6e13"}},"pool1t3pl903zsy3wqgl4392hmuwx8a3f259f3yzhl2ns4xlhskxkr43":{"id":"pool1t3pl903zsy3wqgl4392hmuwx8a3f259f3yzhl2ns4xlhskxkr43","vrfVerificationKeyHash":"dd6686e356e2bec35ee51b17356d801e69917e3b472e2e59d3371e48207fd990","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1urp9rkuj73fqcuc47u3r92huffdmfgnxszkk8nl3dpdmwvqjwpjgz","owners":["c251db92f4520c7315f72232aafc4a5bb4a26680ad63cff1685bb730"],"relays":[{"type":"hostname","hostname":"sator89.ddns.net","port":25369}],"metadata":{"url":"https://capitalstakepool.info/CSP.json","hash":"04028c72c74f04d605fc0d1a04c99357c8563bcf5cc408a6b6e8c7e72176c9d9"}},"pool1vzqtn3mtfvvuy8ghksy34gs9g97tszj5f8mr3sn7asy5vk577ec":{"id":"pool1vzqtn3mtfvvuy8ghksy34gs9g97tszj5f8mr3sn7asy5vk577ec","vrfVerificationKeyHash":"cc688f3f4c8152bbc71cd7b2e8da059856ea06e1520cda4a0724c4cd2632acd3","pledge":{"ada":{"lovelace":250000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uzyzlml7sqd9kpdq5xv6y6dzme78xtgllpt3yv62mjmj9cg082gaa","owners":["882feffe801a5b05a0a199a269a2de7c732d1ff85712334adcb722e1"],"relays":[{"type":"hostname","hostname":"tn-preview.psilobyte.io","port":4201},{"type":"hostname","hostname":"tn-preview2.psilobyte.io","port":4202}],"metadata":{"url":"https://psilobyte.io/adatest/psb-meta.json","hash":"18c2dcb8d69024dbe95beebcef4a49a2bdc3f0b1c60e5e669007e5e39edd4a7f"}},"pool1vc577hmjzpgz6mlccdv8ddwplfgvjtp639ykqd05anu6jcja69a":{"id":"pool1vc577hmjzpgz6mlccdv8ddwplfgvjtp639ykqd05anu6jcja69a","vrfVerificationKeyHash":"42d1ab64b06293ddcbf63dcf8466939bbfc470cf858b87be468abf46dca407ce","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":345000000}},"margin":"3/20","rewardAccount":"stake_test1uq2ktannndxkd639acvkf3hnllh04ddvmh8ctu9e6u2mstsu6fv2l","owners":["1565f6739b4d66ea25ee1964c6f3ffeefab5acddcf85f0b9d715b82e"],"relays":[{"type":"hostname","hostname":"0.0.0.0","port":6000}],"metadata":{"url":"shorturl.at/itHOW","hash":"d37a27a9a28ece2c898936eaf431287b5cd7b4cd09247a941289273ca70a06a4"}},"pool1vevw38yxlyaxke29d40ace7jzz7d38qtcmd5kk36chf3shh02ek":{"id":"pool1vevw38yxlyaxke29d40ace7jzz7d38qtcmd5kk36chf3shh02ek","vrfVerificationKeyHash":"9b49ae80c094db2bb49ae40e21deb1d7921fde3c8b469e90667c58859836d16c","pledge":{"ada":{"lovelace":30000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1ur5jhdf8a7lput2qhsa2hndls4h5yh5ukxr7yc7qkdm96jgnrtjmj","owners":["e92bb527efbe1e2d40bc3aabcdbf856f425e9cb187e263c0b3765d49"],"relays":[{"type":"ipAddress","ipv4":"153.127.67.171","port":3001},{"type":"hostname","hostname":"3rd.vps.deroris.net","port":3001}],"metadata":{"url":"https://git.io/Jo7m7","hash":"a40c9206f1ccb3e6ccfe71a7eaf7f6d4a0d15770d7b097829089468ed9be21ac"}},"pool1ve7vhcyde2d342wmqcwcudd906jk749t37y7fmz5e6mvgghrwh3":{"id":"pool1ve7vhcyde2d342wmqcwcudd906jk749t37y7fmz5e6mvgghrwh3","vrfVerificationKeyHash":"612e0b5b84ff4e48a924b51e511485a4884a31e9f8094d7ff9f1e190bc1af30d","pledge":{"ada":{"lovelace":9147456725}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/25","rewardAccount":"stake_test1urwy6fkeyl4e38mws7f8k34pyltq6qy5gpn86ws3l67cthccls3hd","owners":["dc4d26d927eb989f6e87927b46a127d60d009440667d3a11febd85df"],"relays":[{"type":"ipAddress","ipv4":"192.168.200.132","port":3001}],"metadata":{"url":"https://raw.githubusercontent.com/mj83263/test/main/tPl.json","hash":"dc4bd67f3b9b6138fcd11b6222a1550d402d367e303cce3e07a683e9c6af8f41"}},"pool1vapqexnsx6hvc588yyysxpjecf3k43hcr5mvhmstutuvy085xpa":{"id":"pool1vapqexnsx6hvc588yyysxpjecf3k43hcr5mvhmstutuvy085xpa","vrfVerificationKeyHash":"9f6e5d16ea05c1905907e8aee60b426c7680c32870c2ebe0be50281d889d5cf0","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1uzkxke5d0tjj0utd8tf2v75vytt6wjkx0tp4lr0885slcnqtq2ryf","owners":["ac6b668d7ae527f16d3ad2a67a8c22d7a74ac67ac35f8de73d21fc4c"],"relays":[{"type":"hostname","hostname":"mithril-signer-1.testing-preview.api.mithril.network","port":9091}],"metadata":{"url":"https://tinyurl.com/263p356z","hash":"276f035319f342a84f7e8abf8ec0befde2434bcb29f20f41afd09132fb083fd1"}},"pool1drrylt73ln8jcv0sthcenlkhuan2lfyhthkrrv3vhs9vv4eywdy":{"id":"pool1drrylt73ln8jcv0sthcenlkhuan2lfyhthkrrv3vhs9vv4eywdy","vrfVerificationKeyHash":"c2d3aa0b9ddf84ad6680c8d4dac3375664290b95a290ab7f27c2ebd52bd537cd","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1up2ldekqxmad8gu89l4dw9r9nde58xvfsh00uhs98x33w4qxeeugs","owners":["55f6e6c036fad3a3872fead714659b7343998985defe5e0539a31754"],"relays":[{"type":"hostname","hostname":"api.monrma.ml","port":6006}],"metadata":{"url":"https://api.monrma.ml/meta/GATOR.json","hash":"66bcc65cac5cb109e0bd4c89696d2dc010902cef15d29f0b73250fc8855af5d3"}},"pool1d4nsv4wa0h3cvdkzuj7trx9d3gz93cj4hkslhekhq0wmcdpwmps":{"id":"pool1d4nsv4wa0h3cvdkzuj7trx9d3gz93cj4hkslhekhq0wmcdpwmps","vrfVerificationKeyHash":"ca839c83356effe8d232fa8dd1335afcf923bf8d151cda561a6e94e0b9f38ac7","pledge":{"ada":{"lovelace":1000000}},"cost":{"ada":{"lovelace":429000000}},"margin":"2/25","rewardAccount":"stake_test1ur8csttjsny8t783dnfeylwangqh94zrahnps3qaw6rphcsswzsft","owners":["cf882d7284c875f8f16cd3927ddd9a0172d443ede618441d76861be2"],"relays":[{"type":"hostname","hostname":"relay.preview.crimsonpool.com","port":3000}],"metadata":{"url":"https://crimsonpool.com/red.metadata.json","hash":"e3db302e127a7929cd741de7df7744448906110f76fb6d7d793716937b7a49a6"}},"pool1w83ux7vrwafrsuz044knxl9xxtr38q5jj2l3p28fl3g26faqqwg":{"id":"pool1w83ux7vrwafrsuz044knxl9xxtr38q5jj2l3p28fl3g26faqqwg","vrfVerificationKeyHash":"5c44de7dcbbf485040edf760fe91855693ea7e2290a6a9f4b25efdc42a37b025","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":10000000000}},"margin":"1/2","rewardAccount":"stake_test1urqntq4wexjylnrdnp97qq79qkxxvrsa9lcnwr7ckjd6w0cr04y4p","owners":["c13582aec9a44fcc6d984be003c5058c660e1d2ff1370fd8b49ba73f"],"relays":[{"type":"ipAddress","ipv4":"185.164.6.221","port":54326}],"metadata":{"url":"https://my-ip.at/test/previewpool.metadata.json","hash":"069457ca9fdc1bbeac1f7b4602b9d8fe8ee4255f8af724de2f79702c464402fc"}},"pool1wwh3k3ldzujdvgxllfwlnnkxyheafkacqlufnvpr77n5q72f9hw":{"id":"pool1wwh3k3ldzujdvgxllfwlnnkxyheafkacqlufnvpr77n5q72f9hw","vrfVerificationKeyHash":"81fd203455043724337724f64e67ebbb208d3885ac0063c8b14c4b2bea0bec5e","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1uz3s7gd3rhe9ptechqj7z2r7l6l2gr42rv3lvu4grsdnapg88utxm","owners":["a30f21b11df250af38b825e1287efebea40eaa1b23f672a81c1b3e85"],"relays":[{"type":"ipAddress","ipv4":"51.77.24.220","port":4003}],"metadata":{"url":"https://www.stakecool.io/pools/pvcool-001.metadata.json","hash":"aade4d000f39df2f9ebfc4e23c9a3c49850236fcb924edc1f4da9be844d9691f"}},"pool1wjz475nwhq3fnhfvrjesf4pw70k27fnc5mzvsrzqlxfhy60rmu3":{"id":"pool1wjz475nwhq3fnhfvrjesf4pw70k27fnc5mzvsrzqlxfhy60rmu3","vrfVerificationKeyHash":"663f0b5d8bebb6622de18c0121d3d5bbcb1824b749fe4cbd41a0b232ff4b982e","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1uq3n393q95qu7nswzvnx688ukq69e4p3r78euf2kfwsxg2sygp0rv","owners":["233896202d01cf4e0e13266d1cfcb0345cd4311f8f9e25564ba0642a"],"relays":[{"type":"hostname","hostname":"preview-relays.onyxstakepool.com","port":3001}],"metadata":{"url":"https://onyxstakepool.com/PV-ONYX1.json","hash":"c9e5e56c46dd015c183978583e6f9bc71f7abfc4dc4f949ca12a6f5aff8778fa"}},"pool1w75ukvh77hhz8c2u6rhfjvqlxyptwg37yrkddzatu99qxwwlqhd":{"id":"pool1w75ukvh77hhz8c2u6rhfjvqlxyptwg37yrkddzatu99qxwwlqhd","vrfVerificationKeyHash":"dedb7862c992b2fddfc5fe012e573aead78a0b844ca73748c9feb45a0d68666a","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1urelmc7gcf4ukdf0lakusaunerkm8h6hqzvfgx8z4sflpjc4xeg7h","owners":["f3fde3c8c26bcb352fff6dc87793c8edb3df5700989418e2ac13f0cb"],"relays":[],"metadata":{"url":"https://your_pool_website.com","hash":"6bf124f217d0e5a0a8adb1dbd8540e1334280d49ab861127868339f43b3948bf"}},"pool1w757a30j8cd6nlf5dn9q52lm5ee0fn5permvtlr7mycucpkn6c5":{"id":"pool1w757a30j8cd6nlf5dn9q52lm5ee0fn5permvtlr7mycucpkn6c5","vrfVerificationKeyHash":"6ee546ad0102c3576526fc600b4ab806d5ae3f2cd037110d4cd2505c31c05a18","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"9/500","rewardAccount":"stake_test1uzu2wh3mwjg0pua454hskmehvvte4ut9nn22tqxzuycdclq5kuf7g","owners":["b8a75e3b7490f0f3b5a56f0b6f3763179af1659cd4a580c2e130dc7c"],"relays":[{"type":"ipAddress","ipv4":"139.180.205.134","port":6000}],"metadata":{"url":"https://stakinghouse.com/poolMetaData.json","hash":"021ca91a9f24147bd20c4b7f9a4a1a329998e5fa2ac2a362b40850749ff54b1d"}},"pool10gqm62xy7caj6jhhefsl7h59kse3rv2esuh9rvx55eze2n8dlrj":{"id":"pool10gqm62xy7caj6jhhefsl7h59kse3rv2esuh9rvx55eze2n8dlrj","vrfVerificationKeyHash":"8a9f2e79f70743bdc43b20da993c90b9512849f939fb5b6c3bdad80b5ff3261e","pledge":{"ada":{"lovelace":25000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1uqj0hyhn72p495gntxzt4g9au76ycpcvku693mpexqxdk5s7cwqed","owners":["24fb92f3f28352d1135984baa0bde7b44c070cb73458ec39300cdb52"],"relays":[{"type":"hostname","hostname":"preview.relay.beerpool.io","port":6000}],"metadata":{"url":"https://beerpool.io/poolmeta.json","hash":"3f2d006aa149ac16689d6dd5d0dbbe46d87b41d4b8a282e7621996b6a64cd819"}},"pool105wx68zqse6v4wyx09nkqhxhmf7e0zj349pclyqsjqch7953j0x":{"id":"pool105wx68zqse6v4wyx09nkqhxhmf7e0zj349pclyqsjqch7953j0x","vrfVerificationKeyHash":"7b0cb25a2a5abf1a97523355002a173cd9ff4b2108b7ace2b4693ee406b06eef","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1uz575pc99c8tr8n09u9ek3vhuys7202naetcj83l6fuzrxqpd3ml9","owners":["a9ea07052e0eb19e6f2f0b9b4597e121e53d53ee57891e3fd2782198"],"relays":[{"type":"hostname","hostname":"relay1.doctorstake.network","port":6061}],"metadata":{"url":"https://doctorstake.network/pvpoolmetadata.json","hash":"8ad1a438122bcbab46ab21bb077e818948b2d53d8c9798d0598cad713214663b"}},"pool10c40pnzz3e00kuej05xfcs2ptkekhys48q7qc4jjcsysypj46qv":{"id":"pool10c40pnzz3e00kuej05xfcs2ptkekhys48q7qc4jjcsysypj46qv","vrfVerificationKeyHash":"904c35106259f1c80add13381d730f8bf6291499b9df48dd19a930d0ab865093","pledge":{"ada":{"lovelace":8000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/20","rewardAccount":"stake_test1uqk6t7lajwssrzer6xjarc0n78y26d7p3lswnzrnnegng5ggr5lhm","owners":["2da5fbfd93a1018b23d1a5d1e1f3f1c8ad37c18fe0e988739e513451"],"relays":[{"type":"hostname","hostname":"preview.seaside-staking.best","port":18000}],"metadata":{"url":"https://raw.githubusercontent.com/Seaside-Staking/m/main/m.json","hash":"d843ac7c8ab3a17fe28d5a68c975dc846fe87479364bcff7dd3b30e5c442ca07"}},"pool1s337lucxxrhl8tz8c3r6c4crk784xtga225w3uh2tm0w2kqf0l9":{"id":"pool1s337lucxxrhl8tz8c3r6c4crk784xtga225w3uh2tm0w2kqf0l9","vrfVerificationKeyHash":"a34e2815232397c8680656eda7bb0a7f47531715a083e68432fd18c9a03049e8","pledge":{"ada":{"lovelace":50000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/40","rewardAccount":"stake_test1urp5muju83v5853rwpe7g7yt7u8la35uqpa08ym07ht7jqqymvhfn","owners":["c34df25c3c5943d2237073e4788bf70ffec69c007af3936ff5d7e900"],"relays":[{"type":"ipAddress","ipv4":"69.244.216.147","port":6000}],"metadata":{"url":"https://arcadiastakepool.com/INDGO.metadata.json","hash":"874b5cffdb3cb0720d82802bfc9b68446d858d852dd7694be43a291000fdadbe"}},"pool1s5c2wws3s0trn7agdrwfgz3knq37pule65knyxh0s0dhkdvhn3h":{"id":"pool1s5c2wws3s0trn7agdrwfgz3knq37pule65knyxh0s0dhkdvhn3h","vrfVerificationKeyHash":"e57ecb6a02223c6e8ee503c94929947462fdd2acdad2190360478274a95d6bb1","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/25","rewardAccount":"stake_test1urj7dmqqqfd6qsl8638ezh3zu7lh0cjsfc92q2uf2d2calg458h8e","owners":["e5e6ec00025ba043e7d44f915e22e7bf77e2504e0aa02b8953558efd"],"relays":[{"type":"hostname","hostname":"0c563fdf.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://0c563fdf.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool1sk8n2v844jgpwzvpd4eze374pfvygzcrqlld2mfzx484yrtq74l":{"id":"pool1sk8n2v844jgpwzvpd4eze374pfvygzcrqlld2mfzx484yrtq74l","vrfVerificationKeyHash":"1cbfd07a6145d0d2859c4d114f7e71cb5b9fc7e29cbfa37a393db2637241ce92","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":400000000}},"margin":"0/1","rewardAccount":"stake_test1uqza4tpx4698h0w793fjhtnqh4amhyfcftyx78h54q2wh0qgq074z","owners":["05daac26ae8a7bbdde2c532bae60bd7bbb91384ac86f1ef4a814ebbc"],"relays":[{"type":"hostname","hostname":"relay1.dynip.org","port":28000}],"metadata":{"url":"http://panyvino.com","hash":"9ac046260b09e2befc7addb05b469f90279338821285da90f5cc6e8cb4c5ab15"}},"pool13zafxlpfgymf474uv52qt557z5k5frn9p83yr55zp267wj5mpu4":{"id":"pool13zafxlpfgymf474uv52qt557z5k5frn9p83yr55zp267wj5mpu4","vrfVerificationKeyHash":"628980b886a274e43a09810a91f8a1e1d8241a8c67ddf51e78c8efff1236698a","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1ur0vznanca5kzcwmjyscudf6f38wal8qxcr4nkefdh089mg2kg7lh","owners":["dec14fb3c7696161db91218e353a4c4eeefce0360759db296dde72ed"],"relays":[{"type":"hostname","hostname":"mithril-signer-2.pre-release-preview.api.mithril.network","port":9092}],"metadata":{"url":"https://tinyurl.com/2fej7w5a","hash":"85212d92b197fa7402e0047ed2f2411cabfab4ad1ee54201f5043c0a0fcbaeca"}},"pool1397kpa7ylzg4lqrmj3xr28xzq2548c8lafw90qyxvucsslap03v":{"id":"pool1397kpa7ylzg4lqrmj3xr28xzq2548c8lafw90qyxvucsslap03v","vrfVerificationKeyHash":"9381a0f5511d5f033eb8b707ae620e038e6c8abca7f6d0200331cbe2c7b3cb7e","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/50","rewardAccount":"stake_test1ur2wt3rv5sty3eh6ge9fcxapn0v4ytne06tvdvg8vlv7y8cqvs5eh","owners":["d4e5c46ca41648e6fa464a9c1ba19bd9522e797e96c6b10767d9e21f"],"relays":[{"type":"ipAddress","ipv4":"144.217.73.208","port":8000}],"metadata":{"url":"https://qcpol.stakepool.quebec/poolMetaData.json","hash":"ab249c551e01ea72a5483a45c9f31b2b60bd30c15c865fedf03332ede23439fc"}},"pool13vuxg9gw3fftvfg56xwl5rq82nqtjhhkeacxtg0jgqlfup9qz66":{"id":"pool13vuxg9gw3fftvfg56xwl5rq82nqtjhhkeacxtg0jgqlfup9qz66","vrfVerificationKeyHash":"96fd4b5bbeedf7fb46010d970875c434fc59ceecf566d240dd88489421ae3161","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/1","rewardAccount":"stake_test1up6hq4rnpfmykas4p3f6kytpuqzn0s2p3xwcegng9ysn0egzcqrr9","owners":["757054730a764b76150c53ab1161e00537c141899d8ca268292137e5"],"relays":[{"type":"hostname","hostname":"cardano-relay.int.t-dx.com","port":3000}],"metadata":{"url":"https://adastakepool.t-dx.com/test.json","hash":"20c5dfe0fc1aa2190ec6e344523adbbce96a03edd47f0009a40dca1fe4f260cd"}},"pool1jx2uun9v45gtnlkq83xj6w4chy8rl5g78qqd026e0w89wt4vq9s":{"id":"pool1jx2uun9v45gtnlkq83xj6w4chy8rl5g78qqd026e0w89wt4vq9s","vrfVerificationKeyHash":"d9d2fae43a1c6b3efa0ee48142292e4b2a864150e8030f1fedf2115a60bd0442","pledge":{"ada":{"lovelace":15000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/40","rewardAccount":"stake_test1up4l9hjwtqjwgx3n25q76tw757lagm20f6zk3dc9wmmrjeq0c0s3k","owners":["6bf2de4e5824e41a335501ed2ddea7bfd46d4f4e8568b70576f63964"],"relays":[{"type":"hostname","hostname":"koios-preview.themorphium.io","port":6969}],"metadata":{"url":"https://bit.ly/310ytob","hash":"1f71674f2483c9cdc3c65c77a910dd432d0ae9026157584e34380fdad3a6f44b"}},"pool1jsa3rv0dqtkv2dv2rcx349yfx6rxqyvrnvdye4ps3wxyws6q95m":{"id":"pool1jsa3rv0dqtkv2dv2rcx349yfx6rxqyvrnvdye4ps3wxyws6q95m","vrfVerificationKeyHash":"4c75e85016f939ff51b56b9e676ac7b164f36bc09f68782991c000ad54ef55e5","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1upq49hkcwpayt9dfwe3sfz94t32zqypytdp4lux7fh0uhwclxwzmm","owners":["4152ded8707a4595a976630488b55c542010245b435ff0de4ddfcbbb"],"relays":[{"type":"hostname","hostname":"cardano-preview-relay-1.syn.pizza","port":30800},{"type":"hostname","hostname":"cardano-preview-relay-2.syn.pizza","port":30800},{"type":"hostname","hostname":"cardano-preview-relay-3.syn.pizza","port":30800}],"metadata":{"url":"shorturl.at/acKO0","hash":"acba1a147fbce589cf1d556097b19e441fd2506f86417db03e5cdc06395c06ab"}},"pool1j3x329u0uxh9s9vjvsad9kx37tzal8gndz6ttxumcz4nw947djw":{"id":"pool1j3x329u0uxh9s9vjvsad9kx37tzal8gndz6ttxumcz4nw947djw","vrfVerificationKeyHash":"dccaf70188440911259f798f29caec271cb561d250fcdbe56b9eb0e3a73a12f9","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/40","rewardAccount":"stake_test1upvzzxmzr02kw529cna76e9aga4udj7x45crxx83z2zgvqgu754de","owners":["58211b621bd5675145c4fbed64bd476bc6cbc6ad303318f112848601"],"relays":[{"type":"hostname","hostname":"relay01.preview.junglestakepool.com","port":3001}],"metadata":{"url":"https://csouza.me/jp-p.json","hash":"7fdeea9ed970f2e5eb06a7a8c272c84ce2ca2f6a48ab5912b75f25346a0acbf6"}},"pool1n5aacu3chuvxkm7p2mwcpdvnmkkkvpsje6mclnwj59c6x3wpghh":{"id":"pool1n5aacu3chuvxkm7p2mwcpdvnmkkkvpsje6mclnwj59c6x3wpghh","vrfVerificationKeyHash":"bad28ede267da0d5dc61af65cfa17285257d81ac106b74bd77f507a5b161498f","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/1","rewardAccount":"stake_test1upx0n32j5cne3p0n4pervdjy43j7222h656vgl2uksrxe6gxujj3l","owners":["4cf9c552a6279885f3a872363644ac65e52957d534c47d5cb4066ce9"],"relays":[{"type":"hostname","hostname":"cardano-relay.int.t-dx.com","port":3000}],"metadata":{"url":"https://bit.ly/3O7yle2","hash":"2ad5e7a64a28105e386ec12ad29c3bb6b8a28d07d69da93f11a0c99cc2f737e2"}},"pool1nk3uj4fdd6d42tx26y537xaejd76u6xyrn0ql8sr4r9tullk84y":{"id":"pool1nk3uj4fdd6d42tx26y537xaejd76u6xyrn0ql8sr4r9tullk84y","vrfVerificationKeyHash":"590be0c42cae1fa7e93ab166343a29c83237f297f6c10ea35e5c5e6cd2eb32fa","pledge":{"ada":{"lovelace":1112000000}},"cost":{"ada":{"lovelace":413000000}},"margin":"1/50","rewardAccount":"stake_test1ur9h9qtr739mhuypqmhfxvzux3g9h0tksew8w6ravaj3t8qacq6d9","owners":["c9dc49a676087ba0fb1ab1f28b209e647b4139626d732455bb7d5582","cb728163f44bbbf08106ee93305c34505bbd76865c77687d6765159c","f4cceaa5fff7b592e39519942ea8c3b823f3fee622bb3c81a5f5150f"],"relays":[{"type":"hostname","hostname":"us.netspectrum.com","port":13001}],"metadata":{"url":"http://us.netspectrum.com:13002/pool-meta-data.json","hash":"6e31d534b0d8bdde4ce9bd04ac8d7a6906b680304a3150400304c46f0f393af5"}},"pool1n6tcrkjjn7dr70e4vjmtayswl2rne947fue7w2htthaq6men4yp":{"id":"pool1n6tcrkjjn7dr70e4vjmtayswl2rne947fue7w2htthaq6men4yp","vrfVerificationKeyHash":"9792680b674d04b392cb637a223d327d7af568ef358080cea4d2e10790040f08","pledge":{"ada":{"lovelace":14000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1uq9f3jgmfywhgcmhtd0mv7m3qwp22ah08sd3x8s4ljylpxghkf2yx","owners":["0a98c91b491d7463775b5fb67b710382a576ef3c1b131e15fc89f099"],"relays":[{"type":"hostname","hostname":"preview.blockchainbill.lol","port":3003}],"metadata":{"url":"https://preview.blockchainbill.lol/SNSOB.metadata.json","hash":"4792d9a653baab097047724e97896697c4d1f04accd9e9d126f1786102f1e2d4"}},"pool15qlyejqxu99n2p3980wtwmne4ykzd9vn4mz7ldtncepnuh6rqeh":{"id":"pool15qlyejqxu99n2p3980wtwmne4ykzd9vn4mz7ldtncepnuh6rqeh","vrfVerificationKeyHash":"94ac627b9db9da8d083bd83a6e1e902788566b4db5ba691f5c7f12ef717ed1bf","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/be39feb0-5cba-4552-a044-68f.json","hash":"54920331d130d8949bff1fd6b3f01bc693de7d36de32fc9a29ea2ef60a65da71"}},"pool15zu40d05gy43gyyxy7svumkxyac9qy6shlpdrgyz5gh8g48qaaj":{"id":"pool15zu40d05gy43gyyxy7svumkxyac9qy6shlpdrgyz5gh8g48qaaj","vrfVerificationKeyHash":"3b18c66658a5d9dd1a2bd876f1e0b076451641c41017017ccc6b448bcf38c529","pledge":{"ada":{"lovelace":70000000000}},"cost":{"ada":{"lovelace":4321000000}},"margin":"1/25","rewardAccount":"stake_test1uqz0vs8vnxqpdcuey0qcvufn95gydj6x5g37wgy975wlfwgdhyuk4","owners":["04f640ec998016e39923c18671332d1046cb46a223e72085f51df4b9"],"relays":[{"type":"ipAddress","ipv4":"184.73.135.122","port":3002}],"metadata":{"url":"bit.ly/3Eh3p7A","hash":"9b9d00fcec79d306e3dffcc6865d4088f35b13c268e32c7a2fabb1845947f9c7"}},"pool15rneqfpzde87huszzstymzxu6f5u2jqelsaczr99e3z62dywau7":{"id":"pool15rneqfpzde87huszzstymzxu6f5u2jqelsaczr99e3z62dywau7","vrfVerificationKeyHash":"74838ee89acb2caf072cd50705f0dd0a958af9cb20ec70500ee3c2c2e800b316","pledge":{"ada":{"lovelace":500000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/40","rewardAccount":"stake_test1urx0fs8j3lqfkjtmuzd64futqtucqkmlj32ufgza2xhhutgmx79n2","owners":["ccf4c0f28fc09b497be09baaa78b02f9805b7f9455c4a05d51af7e2d"],"relays":[{"type":"hostname","hostname":"gateway.adavault.com","port":4061}],"metadata":{"url":"https://adavault.com/advpreview.json","hash":"336a78f742447c0af780583059167eff24a4268dad3947373397f5ccfe6a883e"}},"pool1580a362kwnqt7v2lgun5t02u0r7dyl70x9nsy37zj46xkq8mp22":{"id":"pool1580a362kwnqt7v2lgun5t02u0r7dyl70x9nsy37zj46xkq8mp22","vrfVerificationKeyHash":"69f0a026835764345061abdd6d566ae509c1cdfa630999cdc57b5e43a6d6c6f7","pledge":{"ada":{"lovelace":2000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1uqnxa67e6jc4dr89kdkr0e6ucvvzucd772p9vnalrr7h0xskjsgeg","owners":["266eebd9d4b1568ce5b36c37e75cc3182e61bef282564fbf18fd779a"],"relays":[{"type":"hostname","hostname":"s2.lost-in.tech","port":3001}],"metadata":{"url":"https://cardano.lost-in.tech/LIT-Pool.metadata.json","hash":"5e30e12a869cf6f5b8c8fd2d74cccd7e0825b37719a978914877b56e50e82bf9"}},"pool152x6q0ly050yr7cnatwq0087jzwyxxlkyuch6s4xex8ljaeu0ng":{"id":"pool152x6q0ly050yr7cnatwq0087jzwyxxlkyuch6s4xex8ljaeu0ng","vrfVerificationKeyHash":"c4b14fc6e1e4a632f51e245990b0d9a75096f26ad22930df52ac06ad2dc06149","pledge":{"ada":{"lovelace":3000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1urc970azyxew8lf0s0wdw8z5pckjxcdn63v7575v4upprks6h5yys","owners":["f05f3fa221b2e3fd2f83dcd71c540e2d2361b3d459ea7a8caf0211da"],"relays":[{"type":"hostname","hostname":"testnet-relay.xstakepool.com","port":3001},{"type":"hostname","hostname":"testnet-relay2.xstakepool.com","port":3001}],"metadata":{"url":"https://xstakepool.com/testnet-xstakepool.json","hash":"25d14c92cd852bbe666858ba040db7d5dd0767838e604e16c12b8fb842cf89ec"}},"pool14rn9dq87dgj2z8g3lp4n0a78fewxff3gkgjkmz72ew44ym79xpp":{"id":"pool14rn9dq87dgj2z8g3lp4n0a78fewxff3gkgjkmz72ew44ym79xpp","vrfVerificationKeyHash":"3e583b72203f1659bb73653baf0e2d7850d238d4c96435eff4331060bf926801","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uz7xx6hy2xnnrmz0av0xl7qn9vdkhage7myf0nd49e7mvcg6z0smn","owners":["bc636ae451a731ec4feb1e6ff8132b1b6bf519f6c897cdb52e7db661"],"relays":[{"type":"hostname","hostname":"f7ca89d1.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://f7ca89d1.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool14gzp9699juxeku56qc5dsk00vv9kngrz4art5v04fh77wmd37hq":{"id":"pool14gzp9699juxeku56qc5dsk00vv9kngrz4art5v04fh77wmd37hq","vrfVerificationKeyHash":"bb0670c4efe93e9bafc85323da00fef702997d64a0894b6398d8fb72d97eb7c1","pledge":{"ada":{"lovelace":678000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1up6ckzx75pw6h5wdx5gx384anmak5jf3dt9npm4dw58za8sxw5223","owners":["758b08dea05dabd1cd3510689ebd9efb6a49316acb30eead750e2e9e"],"relays":[{"type":"hostname","hostname":"test.everestada.com","port":7002}],"metadata":{"url":"https://raw.githubusercontent.com/everestada/esp/main/Meta.json","hash":"fe93bf08749b0aabb73d7a22c4af69ae15e89a52105df2ebd9a28b03a89a2353"}},"pool14fdr8cpz0qpgzkrucu2q7hst2pa3u5ssfej7kuepdq4v7lkyxg3":{"id":"pool14fdr8cpz0qpgzkrucu2q7hst2pa3u5ssfej7kuepdq4v7lkyxg3","vrfVerificationKeyHash":"896bac573601caf048566f3562e99be9c742832ad7e4527b5b1cdc330e9384c1","pledge":{"ada":{"lovelace":20000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1uqr9uznkqeuv6e7ez79yf8us678xus3y6ac0su9d253r0eg5l4clt","owners":["065e0a760678cd67d9178a449f90d78e6e4224d770f870ad552237e5"],"relays":[{"type":"ipAddress","ipv4":"81.169.140.47","port":6000}],"metadata":{"url":"https://hamster-stake-pool.de/preview_poolmeta.json","hash":"81813b6eb7904fb8533aa51f9aebc16f14e6ade80576078b83a8b307ace6b987"}},"pool14u22dyym8k2g2twvgct86njg3m9cc7j2fc74yamy6672s6up7a0":{"id":"pool14u22dyym8k2g2twvgct86njg3m9cc7j2fc74yamy6672s6up7a0","vrfVerificationKeyHash":"600f54b88675a354a87bea473ac776fb2684254d55431585904b89b71ef74620","pledge":{"ada":{"lovelace":50000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"99/100","rewardAccount":"stake_test1uruen30w3mydukztulc8z5xqp2zpezctum9x4j6kctp3csclazf3y","owners":["f999c5ee8ec8de584be7f07150c00a841c8b0be6ca6acb56c2c31c43"],"relays":[{"type":"hostname","hostname":"preview.leadstakepool.com","port":3001},{"type":"hostname","hostname":"preview.leadstakepool.com","port":3002}],"metadata":{"url":"https://raw.githubusercontent.com/lead-pool/l/master/p.json","hash":"91a080cf2aa797c24efe5b26330a634209ec152a0f079ffc0b31157a6f4a6993"}},"pool1krjtqew2jg203nvnec39vt77leqyfsc8e42u4ywx534t62h9fth":{"id":"pool1krjtqew2jg203nvnec39vt77leqyfsc8e42u4ywx534t62h9fth","vrfVerificationKeyHash":"3a238800d748179b955445d9c2488125785f1e271e8d43449e292d5a7c4b7b71","pledge":{"ada":{"lovelace":100}},"cost":{"ada":{"lovelace":500000000}},"margin":"1/2","rewardAccount":"stake_test1upxs40dqlfrh4gkd7djhwr5qlq225c3etv66f8m0mgsahxgk45c6j","owners":["4d0abda0fa477aa2cdf365770e80f814aa62395b35a49f6fda21db99"],"relays":[{"type":"ipAddress","ipv4":"212.24.98.109","port":5002}],"metadata":{"url":"https://adawallet.io/public_files/MDS_ST_meta_v2.json","hash":"ef3aca5a37d0bc4d81c4f85da513e3565be372e9bc3ecdf6fe5cb1a5bb55bff2"}},"pool1k4rdvvuhy7h927psyew9syupwddy77t4j8lc74hpgzpvv7yklwg":{"id":"pool1k4rdvvuhy7h927psyew9syupwddy77t4j8lc74hpgzpvv7yklwg","vrfVerificationKeyHash":"ff8d88fd6b39985c9ddbef0363f87ec0ae32016c62a305e2497e4b54cb161d52","pledge":{"ada":{"lovelace":6000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/40","rewardAccount":"stake_test1uqw2h3092ka5mctav6d07cwumxagvcm9zs2aj9g2m4n74cgcf5r9x","owners":["1cabc5e555bb4de17d669aff61dcd9ba8663651415d9150add67eae1"],"relays":[{"type":"hostname","hostname":"preview-test.ahlnet.nu","port":2102}],"metadata":{"url":"https://ahlnet.nu/pool/preview-meta.json","hash":"8f52b4840726c157c50c1b972fadb21b2f0c852e99004a48e649319218960c55"}},"pool1kkhr6m0syfgqamr3klzhj2trjd3q4vyg8trzdjxdp64nqzshwea":{"id":"pool1kkhr6m0syfgqamr3klzhj2trjd3q4vyg8trzdjxdp64nqzshwea","vrfVerificationKeyHash":"b4ea03eb58cbfa9059e0b8478f09762f002e4cebc9aae7bf6de04b9ccebb9d94","pledge":{"ada":{"lovelace":100000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1uzx366cdgqv9lg69y7ufw59af3y7yh9jxflnym8z8qz3pfgmef2r8","owners":["8d1d6b0d40185fa34527b89750bd4c49e25cb2327f326ce2380510a5"],"relays":[{"type":"hostname","hostname":"preview.adanorthpool.com","port":9613}],"metadata":{"url":"https://www.adanorthpool.com/ANPPREVIEW.metadata.json","hash":"e4f9a2cf26e72b93955893bbcae4a37c27c061b04ab2a8d79856350e6dc3fb26"}},"pool1kewhspt8fsxk9kx6pw2nukcrs940dkwcwh89llj233ahghexeum":{"id":"pool1kewhspt8fsxk9kx6pw2nukcrs940dkwcwh89llj233ahghexeum","vrfVerificationKeyHash":"9d009cac22c72b8200e473c71330cc5907832880a2098c1fea0affb68df5f52f","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uptdhvz442mcem2lqd3y23nlypudpdm7d32aeyn3y72d8tcs7scmy","owners":["56dbb055aab78ced5f036245467f2078d0b77e6c55dc92712794d3af","b0348c669fe3cb7446b5084a669e304dd1cff63762352e8355e14482"],"relays":[{"type":"hostname","hostname":"605691fa.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://605691fa.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool1hykgd0kw0n6vx08j8vcyu7q0q6rqkwxr7cql03vf2at9kdmlxpy":{"id":"pool1hykgd0kw0n6vx08j8vcyu7q0q6rqkwxr7cql03vf2at9kdmlxpy","vrfVerificationKeyHash":"c636a7c8aa43ee105919d24a62f0d80bdc3981de0951672e7a316cc9a0f57b74","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1uz5sce2cv9kkykjqhakrvma65xhlyzt3p7n4aamexkg0jtcf54jnu","owners":["a90c6558616d625a40bf6c366fbaa1aff209710fa75ef7793590f92f"],"relays":[{"type":"hostname","hostname":"node.armadacardano.io","port":6000},{"type":"hostname","hostname":"node2.armadacardano.io","port":6000}],"metadata":{"url":"https://armadacardano.io/metadata.json","hash":"45ce75ec2304fce3afb1a8c11316cedc5a20aea417b58ca59f6ad97ea4518112"}},"pool1h2wx7wnf079jfz6vyzs9jnjczme2nlufryyw68e2fhe2x0swk3e":{"id":"pool1h2wx7wnf079jfz6vyzs9jnjczme2nlufryyw68e2fhe2x0swk3e","vrfVerificationKeyHash":"d9a1ba9598e9613974ce89526c30d70bc9763af61b86d5e28638ecfc88e837ce","pledge":{"ada":{"lovelace":45000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/500","rewardAccount":"stake_test1upam5e8xunaktc2qwwq3aa6wumkya75x68ce32a0dkfh60qyxhst8","owners":["7bba64e6e4fb65e14073811ef74ee6ec4efa86d1f198abaf6d937d3c"],"relays":[{"type":"ipAddress","ipv4":"159.138.55.134","port":3001},{"type":"ipAddress","ipv4":"192.168.0.105","port":3001}],"metadata":{"url":"https://raw.githubusercontent.com/mj83263/test/main/tp2.json","hash":"5ff4cd6df6afda00a70f9480b72acaa0e2271371c2e6daf89e7c53ef6192ec90"}},"pool1htdmnme5s6d824trqq33czlm82f473w04h4xghprzaj3cff53mp":{"id":"pool1htdmnme5s6d824trqq33czlm82f473w04h4xghprzaj3cff53mp","vrfVerificationKeyHash":"98a662ae890d7c2d48b8bf5fb55602c20a04d59e499d0446586189680d039a9f","pledge":{"ada":{"lovelace":8000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/200","rewardAccount":"stake_test1uzsapk9c9x5frdk99wqktd6udusxhe6u0qnaryxmg4cqe9clhncf4","owners":["a1d0d8b829a891b6c52b8165b75c6f206be75c7827d190db45700c97"],"relays":[{"type":"hostname","hostname":"relaynode25t.irfada.co","port":6000},{"type":"hostname","hostname":"relaynode26t.irfada.co","port":6000}],"metadata":{"url":"https://tinyurl.com/munhhxv9","hash":"dfe61ced98cfa2fd81658686ea824910f3e6a5306c89bf1bc362f54e2000927c"}},"pool1h7c2jq3pmvn3f8jht4ulhgha3h60k6syu3rw6pmkfrhqs9j7m0l":{"id":"pool1h7c2jq3pmvn3f8jht4ulhgha3h60k6syu3rw6pmkfrhqs9j7m0l","vrfVerificationKeyHash":"941c6ac6afb53de451e95ec203d6093ce6c8ef0fd58e8a78e406ac3bb668c796","pledge":{"ada":{"lovelace":1000000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/25","rewardAccount":"stake_test1uqkn6dhxl7mg542afm858jxudl7cwd9f0gys3qkuh3al5eq5zzhss","owners":["2d3d36e6ffb68a555d4ecf43c8dc6ffd8734a97a090882dcbc7bfa64"],"relays":[{"type":"hostname","hostname":"relay.test.lidonation.com","port":3010}],"metadata":{"url":"https://test.lidonation.com/metadata.json","hash":"edc82ecfb1cabeb15cb122bd6a65b6de6006e2201617e3c8dfdf8cc652baacfe"}},"pool1hlgaznlja8jau6wg3u4curvs7ng6yhxaxa2urp7qylxkc2e4pjk":{"id":"pool1hlgaznlja8jau6wg3u4curvs7ng6yhxaxa2urp7qylxkc2e4pjk","vrfVerificationKeyHash":"f727fdc0e656c1faea14c812b9cf7648795f5b606f6428f6e8dd68d0f729514d","pledge":{"ada":{"lovelace":4000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/200","rewardAccount":"stake_test1uzpp6e09x70k4wu4ccwujgwfdjwluf4nzyekkaa2l0dlgjq07ax2w","owners":["821d65e5379f6abb95c61dc921c96c9dfe26b311336b77aafbdbf448"],"relays":[{"type":"ipAddress","ipv4":"51.255.82.47","port":6000}],"metadata":{"url":"http://config.ada-staking.fr/metadatas_preview.json","hash":"86fd4e3118fe835008a699f339ec111ac35682de1d449b15255544b1570b601f"}},"pool1cv9fr477zeznqrk8uxa5hh72tsjukkuqtnet7wgyxx3rq700kl5":{"id":"pool1cv9fr477zeznqrk8uxa5hh72tsjukkuqtnet7wgyxx3rq700kl5","vrfVerificationKeyHash":"b1ab6692d0af93c5e61e99f4ba39a5a10352b729fe370145e35e5eb39bc53b13","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/50","rewardAccount":"stake_test1upv2favfz6vqs782yg9kc8sxdely9g3dqd4w4v492jw6hvcypj9hu","owners":["58a4f58916980878ea220b6c1e066e7e42a22d036aeab2a5549dabb3"],"relays":[{"type":"hostname","hostname":"previewrelay.stakepoolcentral.com","port":15654}],"metadata":{"url":"https://bi-preview.stakepoolcentral.com/CENT.preview.json","hash":"fb6a7bdf6c6827d16c33b1173cb436897cdad7a3fe399c01813797180fe97db3"}},"pool1ceact5c2pt4ynn5nwv2rqm04krzsm4jd26r468mdqannv5crxd6":{"id":"pool1ceact5c2pt4ynn5nwv2rqm04krzsm4jd26r468mdqannv5crxd6","vrfVerificationKeyHash":"c2075042ece1ad9b41000c53598349ec2735c649f456f3836901ade5b31eca10","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uq0r8cvtjnz8y0kw4x09rv3fk8gev98gp5fg28u0zk0kaqgwxl5eq","owners":["1e33e18b94c4723ecea99e51b229b1d19614e80d12851f8f159f6e81"],"relays":[{"type":"hostname","hostname":"9caee114.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://9caee114.cardano-metadata.stagebison.net/metadata.json","hash":"985e4efc3b6a10c375968c1de0a138fc75bd357d3e1ffa581aafbd96a43d37a5"}},"pool1epeq86e8vuuar86kk9hgtn6ty3yzcjun5nrm2xyysfl07fsrwc4":{"id":"pool1epeq86e8vuuar86kk9hgtn6ty3yzcjun5nrm2xyysfl07fsrwc4","vrfVerificationKeyHash":"09f8f0bcd8dba98f8d0d5cf76624610eda099fcfd813df66b43ce23a3be7e35f","pledge":{"ada":{"lovelace":9000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"9/100","rewardAccount":"stake_test1uza6wgdaec5kulpd5ft2xtchcfhgry6te8az8h5r2xzp7kgxc3hvp","owners":["bba721bdce296e7c2da256a32f17c26e81934bc9fa23de8351841f59"],"relays":[{"type":"ipAddress","ipv4":"127.0.0.1","port":80}],"metadata":{"url":"https://foo.bat/poolmeta.json","hash":"47fa1c955765325622a3d1bcff79d78ce719a8823ee3169998348cf585edc469"}},"pool1ez9khv2gx82mqrnj0qenr47dy8grecm8qkkrtnn69wzzwkvc9l6":{"id":"pool1ez9khv2gx82mqrnj0qenr47dy8grecm8qkkrtnn69wzzwkvc9l6","vrfVerificationKeyHash":"30ff40541e2c155acfcdfa844069e705dee1ae8eef9bdcde22de465de6fa8fdd","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/20","rewardAccount":"stake_test1up3pxcv3etz7d8h5e6csly3yggnmnwrgqrvhhjsqak7828ck4ytys","owners":["62136191cac5e69ef4ceb10f92244227b9b86800d97bca00edbc751f"],"relays":[{"type":"hostname","hostname":"c-pv-rn01.liv.io","port":30002},{"type":"hostname","hostname":"c-pv-rn02.liv.io","port":30002}],"metadata":{"url":"https://liv.io/poolMetaData.json","hash":"66309fa9a6726eaf1ede2bd73b1ffe02dcbc0f966730221b0cbc71702bb1742a"}},"pool1erufgazt3scqvjvsqv7ehayfscj93llzu3e6lknh2m6d5xcfjdr":{"id":"pool1erufgazt3scqvjvsqv7ehayfscj93llzu3e6lknh2m6d5xcfjdr","vrfVerificationKeyHash":"ee04d2c090ad7cfb572b32776eb694f336b2e26048a0423de1d66241deadeac8","pledge":{"ada":{"lovelace":19000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1uqevz4f8d5z9pv7jx8rtlvxascwqx7v6ygrmf4kj2vta43q7kjpzk","owners":["32c155276d0450b3d231c6bfb0dd861c03799a2207b4d6d25317dac4"],"relays":[{"type":"hostname","hostname":"preview-testnet-relay.cardanistas.io","port":3001}],"metadata":{"url":"https://stakepool.page.link/cards-preview-testnet-metadata","hash":"ce0eb65620e544b8614517f495fd0bd371a6a5ee70c3ddc6b210c3dff0a3f8b3"}},"pool1erajsxw8ejry8flz6gwsd885dmx9uv6k9wd8dl5vme7cxrzv9hl":{"id":"pool1erajsxw8ejry8flz6gwsd885dmx9uv6k9wd8dl5vme7cxrzv9hl","vrfVerificationKeyHash":"b327686ee38df980c15a5c9f9eeefeb5a03f5079531805cfead05a33739d23b4","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/20","rewardAccount":"stake_test1upnsszyt4g7wtl4s729kqysjph9mpv9f8hy5tk2srxr5swqnl38cl","owners":["6708088baa3ce5feb0f28b6012120dcbb0b0a93dc945d95019874838"],"relays":[{"type":"hostname","hostname":"g5.datadyne.earth","port":3005}],"metadata":{"url":"http://datadyne.earth/cardano/dataDyneCardanoPool.json","hash":"23f3b6da129943598cc39d57de2569810e5564558f1db8ab0bb80bd85194b3c4"}},"pool1ewxvkzqnvfzaf48092n4t2crdventhxhtmpvydxnsnj322qc47c":{"id":"pool1ewxvkzqnvfzaf48092n4t2crdventhxhtmpvydxnsnj322qc47c","vrfVerificationKeyHash":"9842080c08dfce55e9d6758b9c57c51a83003c29920cbb94a828399f2472bc64","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":500000000}},"margin":"392699/12500000","rewardAccount":"stake_test1upp6fr9evvqcprgr57vq0u9mdwxck2whdlyjhve750xl29gu5zexv","owners":["43a48cb96301808d03a79807f0bb6b8d8b29d76fc92bb33ea3cdf515"],"relays":[{"type":"hostname","hostname":"preview.canadastakes.ca","port":5002}],"metadata":{"url":"https://www.canadastakes.ca/metadata/can1-preview-metadata.json","hash":"756e0c7c2640e526c055d0fe4eb453c0c2e2c3af85138a99a8e0d74ef9c0eeb3"}},"pool1ewed82f7tdluggkj2qsrajyjakzqewj3e37p25cddurtwejl6tz":{"id":"pool1ewed82f7tdluggkj2qsrajyjakzqewj3e37p25cddurtwejl6tz","vrfVerificationKeyHash":"dca941225e309e0aa7a4ca3a2f49280fa860098a17ab231a5e9b4347a0f2d241","pledge":{"ada":{"lovelace":9369000000}},"cost":{"ada":{"lovelace":369000000}},"margin":"9369/10000","rewardAccount":"stake_test1uzn99jy8eud3f4jp7pg6natdt3mn76mn33fx5na0a9utk7q03ttkv","owners":["a652c887cf1b14d641f051a9f56d5c773f6b738c526a4fafe978bb78"],"relays":[{"type":"hostname","hostname":"testicles.kiwipool.org","port":9720}],"metadata":{"url":"https://bit.ly/3R870ZK","hash":"19dcf5a17af5475da21aae1046a1bdae92ebac5e06e93e8c9a41b7a844fc6af8"}},"pool1ecc3gej4jsaskjfq6phxkcklx8l0qtvalyzeefp9shmvj86hchr":{"id":"pool1ecc3gej4jsaskjfq6phxkcklx8l0qtvalyzeefp9shmvj86hchr","vrfVerificationKeyHash":"dc0c2cf51a1033db6cdae7a856d78989ea373d41567b4bd30e850021d84b8843","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1uq6pyvmjrxem8gftst2v23adw5trzvxanhz9vv3p4ng9qkqgwyflc","owners":["3412337219b3b3a12b82d4c547ad75163130dd9dc4563221acd05058"],"relays":[{"type":"hostname","hostname":"relay1.cardano.teamplay.studio","port":6000}],"metadata":{"url":"https://tinyurl.com/2p93ec5b","hash":"6bfbe784117723dbd72811f1ac85acfe49d5ca913102320ae012f39533a97a96"}},"pool16y556gh885fw5nky8f8qmfwjeer7l8d2wjr8cl7f5vd8x7zgh0d":{"id":"pool16y556gh885fw5nky8f8qmfwjeer7l8d2wjr8cl7f5vd8x7zgh0d","vrfVerificationKeyHash":"968a613baf8ec8e434b663e0a1fdf1c710a7b760a67dfb15e8ede88b818236e9","pledge":{"ada":{"lovelace":5000000000}},"cost":{"ada":{"lovelace":4321000000}},"margin":"1/25","rewardAccount":"stake_test1uppyxzrrhyfh5ja2tgfm87u8h36xgr3a6d6p2ljztpfew8snugder","owners":["42430863b9137a4baa5a13b3fb87bc74640e3dd374157e425853971e"],"relays":[{"type":"ipAddress","ipv4":"123.121.123.121","port":3000}],"metadata":{"url":"https://git.io/JJWdJ","hash":"c5c38833176e2d575bd8693e206e3af2e1088e556def86cae9f6c2fc45579f36"}},"pool16dy6cwrdthfmhn85h56se7dmhp2m8vhg928lvg073r7dwkjvtpg":{"id":"pool16dy6cwrdthfmhn85h56se7dmhp2m8vhg928lvg073r7dwkjvtpg","vrfVerificationKeyHash":"a377abb415ee8e8ae9a15a2a68aa9800261c7ffc77ac9380d416703e7fed9ac8","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/b44bf76a-f93d-491d-bffe-ebf.json","hash":"e0f5672cbb37d0564f5ba3f68fad2ea15484b65ece509500b27213a597a7df03"}},"pool16hphjcfga9jhk5j3rsgmys83kza983utn3zv9jwhjgpe2ah4j8x":{"id":"pool16hphjcfga9jhk5j3rsgmys83kza983utn3zv9jwhjgpe2ah4j8x","vrfVerificationKeyHash":"42b2725232523538f75c49436958209eeec9b0bd081b847816996c3faf1a3ed1","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/20","rewardAccount":"stake_test1uzxp3ahlzepch6r7vk43cwjsmyjvp7zvqy6973nw2ejktksa5yrqu","owners":["8c18f6ff16438be87e65ab1c3a50d924c0f84c01345f466e566565da"],"relays":[{"type":"ipAddress","ipv4":"168.138.37.117","port":6000}],"metadata":{"url":"https://tinyurl.com/yc3brjd5","hash":"13538c6980dd25aef3cad66fe9534145168e94e88bdb2db73f469b7b3e2faaeb"}},"pool16h8ugt8k0a4kxa5g6x062zjrgfjc7cehpw0ze8374axlul76932":{"id":"pool16h8ugt8k0a4kxa5g6x062zjrgfjc7cehpw0ze8374axlul76932","vrfVerificationKeyHash":"4331f2905796fd9a028c17896ce5305dc1daf710ad448a3872df75722f2cc41d","pledge":{"ada":{"lovelace":100000000000000}},"cost":{"ada":{"lovelace":500000000}},"margin":"1/1","rewardAccount":"stake_test1uzuklnhnhy634a5rf0v9pcaf0pva002mw2wjf0ekg6h2encat3ykr","owners":["ba149e2e2379097e65f0c03f2733d3103151e7f100d36dfdb01a0b22"],"relays":[{"type":"hostname","hostname":"preview-node.world.dev.cardano.org","port":30002}]},"pool1mfc42za8tj74zc66ez3slwtq4mumdl7yrylaxajd5xugujmhd0c":{"id":"pool1mfc42za8tj74zc66ez3slwtq4mumdl7yrylaxajd5xugujmhd0c","vrfVerificationKeyHash":"5261e39dc3a6a2c1107bded7a5cce9f9e5ba273d92b3832d028c24a23b83db48","pledge":{"ada":{"lovelace":4567000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"117/5000","rewardAccount":"stake_test1uzckcmv9m39sx0jdvjn5snd8pkhtzwjed50tr9ayjcjdvfctmyegm","owners":["b16c6d85dc4b033e4d64a7484da70daeb13a596d1eb197a49624d627"],"relays":[{"type":"ipAddress","ipv4":"95.216.173.194","port":16000}],"metadata":{"url":"https://raw.githubusercontent.com/hodlonaut/a/master/t1.json","hash":"81986b8f246cb39979af55fc01215f193df2dc07107989b886e131633e880e43"}},"pool1m3d2flwq8kt6ys0e973xwawd042dnn6vfu82p8efyqsvu4wttaq":{"id":"pool1m3d2flwq8kt6ys0e973xwawd042dnn6vfu82p8efyqsvu4wttaq","vrfVerificationKeyHash":"e40dfd70145e63f2eb76398181f9e2f9b9f24aff6800228aa7ff1beef2a3c30c","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":345000000}},"margin":"3/20","rewardAccount":"stake_test1ups3a2wv5lnrwusv06zxqrjpga4gwzuuw86y8vh23t9uhgsxarnft","owners":["611ea9cca7e637720c7e84600e41476a870b9c71f443b2ea8acbcba2"],"relays":[{"type":"hostname","hostname":"ada01.liv.io","port":30002}],"metadata":{"url":"liv.io/poolMetaData.json","hash":"78409be753a669ae5eb8c81ee7f3f1a48e8a265ebc6814e6247af4440d50b515"}},"pool1uqthfy3jsrd82q067vu8ml8g0w3xr20qp8kv7z0yzrdhqrawkm2":{"id":"pool1uqthfy3jsrd82q067vu8ml8g0w3xr20qp8kv7z0yzrdhqrawkm2","vrfVerificationKeyHash":"7104302efc01232ce74b1c5c5fd8519e0ac84f07a62d0deb7fb8ebd05454b5ea","pledge":{"ada":{"lovelace":9400000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"99/100","rewardAccount":"stake_test1upltzjkedla8ukdnj3k58xwy3pgjqwckmnx5s4a07lr0gds7yvh0x","owners":["7eb14ad96ffa7e59b3946d4399c48851203b16dccd4857aff7c6f436"],"relays":[{"type":"ipAddress","ipv4":"14.201.4.90","port":6006},{"type":"ipAddress","ipv4":"14.201.4.90","port":6005},{"type":"ipAddress","ipv4":"139.218.11.14","port":6005}],"metadata":{"url":"https://dpadapools.com/preview3meta.json","hash":"e075ccee5c7172d62b0da89fbe1ee02a2569de5ceb438a6dd22be079c63670c5"}},"pool1uh5sc3v77el8egy6rgz59mdgv0097j7nx3usrrkagvmsy6074k0":{"id":"pool1uh5sc3v77el8egy6rgz59mdgv0097j7nx3usrrkagvmsy6074k0","vrfVerificationKeyHash":"ae3c85580444e5a30cfad07b6a70e004c1875faf87851a06ce756e5ed42ee8f4","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1uzds77htp7kk5txdk5e2zntrejgmv5gum445n26ygawv40ghak4zs","owners":["9b0f7aeb0fad6a2ccdb532a14d63cc91b6511cdd6b49ab44475ccabd"],"relays":[{"type":"hostname","hostname":"sp.altzpool.com","port":5001}],"metadata":{"url":"https://altzpool.com/WALTZ/poolmeta.json","hash":"5c8ab40789c4fdc8aeb4684deda3c85aa0202078e0f2d575977f76351da9e771"}},"pool1ayc7a29ray6yv4hn7ge72hpjafg9vvpmtscnq9v8r0zh7azas9c":{"id":"pool1ayc7a29ray6yv4hn7ge72hpjafg9vvpmtscnq9v8r0zh7azas9c","vrfVerificationKeyHash":"4888af16310dc9dd2600001ae7d5fc571cd15d38ffb47c802aac599f916207e0","pledge":{"ada":{"lovelace":35000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/100","rewardAccount":"stake_test1uzs5rxys8qy5jnr9g0mkj860ms5n92nrykmrgyumpf2ytmsejj4m6","owners":["a14198903809494c6543f7691f4fdc2932aa6325b634139b0a5445ee"],"relays":[{"type":"ipAddress","ipv4":"207.180.211.199","port":6007}],"metadata":{"url":"https://git.io/JW7b5","hash":"7296d38d3c67d769c38924679e132e7d9098e70891d7574cc5cf053574305629"}},"pool1agzq8htqr80dr0wu6ppvm4azkrmhelg4jy4x4qes9n5cuau7esc":{"id":"pool1agzq8htqr80dr0wu6ppvm4azkrmhelg4jy4x4qes9n5cuau7esc","vrfVerificationKeyHash":"fb27957133f79e8e308e0bb47f26a3b8c9c6ada920a4b1121410d55ad4f2f90a","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/187d7406-a87e-449e-8849-9a8.json","hash":"68d0f12660b653892627f2c26c5206dd7cec9fe5c28680f30130aee36188cefd"}},"pool1a7h89sr6ymj9g2a9tm6e6dddghl64tp39pj78f6cah5ewgd4px0":{"id":"pool1a7h89sr6ymj9g2a9tm6e6dddghl64tp39pj78f6cah5ewgd4px0","vrfVerificationKeyHash":"1d8199fd0a82c29b242d62f6aca7d166200e47c0596fab5b1d4cf56399b6eded","pledge":{"ada":{"lovelace":100000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/10","rewardAccount":"stake_test1uqd2nz8ugrn6kwkflvmt9he8dr966dszfmm5lt66qdmn28qt4wff9","owners":["1aa988fc40e7ab3ac9fb36b2df2768cbad36024ef74faf5a0377351c"],"relays":[{"type":"hostname","hostname":"prv-relay1.apexpool.info","port":3001}],"metadata":{"url":"https://apexpool.info/preview/poolmetadata.json","hash":"a207f23a6255eeb0b508945e5170b169eb5c3220109d7fa17a7d88d462c8a199"}},"pool178q9xf62yr0rkkgrx6lxwk7h0md4ms3jamc8j206q0r5xr3qc8l":{"id":"pool178q9xf62yr0rkkgrx6lxwk7h0md4ms3jamc8j206q0r5xr3qc8l","vrfVerificationKeyHash":"fabe3a1aa31e714e62d4b77cfabe22759ec854565a827e1161cd162edfee9427","pledge":{"ada":{"lovelace":100000000}},"cost":{"ada":{"lovelace":345000000}},"margin":"3/20","rewardAccount":"stake_test1urkd8fd78n9ce886q20wnqjf8dg3v3g5xszhv5hptpvkj5cq3h6fk","owners":["ecd3a5be3ccb8c9cfa029ee982493b5116451434057652e158596953"],"relays":[{"type":"ipAddress","ipv4":"62.11.3.72","port":6000}],"metadata":{"url":"https://tinyurl.com/4by9x85x","hash":"2efe7280d7aca9cc51ab6b810482ecb59b89c7bfdf2215ad6f7c81483d78482c"}},"pool17wdfwsyksx7femcxzx7ycf84maqvdf3fmr7z92h2xguy7eanvdf":{"id":"pool17wdfwsyksx7femcxzx7ycf84maqvdf3fmr7z92h2xguy7eanvdf","vrfVerificationKeyHash":"b5ad4eb8d4d7d07c993670d34e475a0ebd3553b297eaec49f297645365f3319e","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"0/1","rewardAccount":"stake_test1uzu4m5xsmd0lw2y7n3rrh70feevp5sghqk9nmkr30f0yyjcx0eu53","owners":["b95dd0d0db5ff7289e9c463bf9e9ce581a4117058b3dd8717a5e424b"],"relays":[{"type":"hostname","hostname":"preview-testnet-relay.junostakepool.com","port":4521}],"metadata":{"url":"https://junostakepool.com/juno-testnet.metadata.json","hash":"b2cbd9af0915b7f4b170a3dda7487f763e2ff31b9b960511a1a7d754c2d5714e"}},"pool17njlrn0jgdw626utskz0zmrnduz9ra8d3al6aw5hvszxkx88q2r":{"id":"pool17njlrn0jgdw626utskz0zmrnduz9ra8d3al6aw5hvszxkx88q2r","vrfVerificationKeyHash":"392d334b0670323093e6cf60edf36961e4005de35b2c86f01e41ce2f7428837a","pledge":{"ada":{"lovelace":1000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/1","rewardAccount":"stake_test1urmklja3h07ndxxrg6eu950x9glzws3gcu7wpphz2cdgujql0rxpn","owners":["10d1fd3cc499c8651bc9344fabe05739fa3e5777145eb638d39dc449"],"relays":[{"type":"ipAddress","ipv4":"210.54.38.228","port":4020}],"metadata":{"url":"https://bit.ly/3vlDN4w","hash":"ff6cdb1fba6074de46d95e0f878d9683d2ce2cf3acb57e6a4fdb9d97af8fe739"}},"pool1l9u9ss9xtww8qkt4zqda84z945f6tgq4753jqhtdr4r8yaw7d6g":{"id":"pool1l9u9ss9xtww8qkt4zqda84z945f6tgq4753jqhtdr4r8yaw7d6g","vrfVerificationKeyHash":"d510044198082bb3852d56c29d0901dfc7f2fe7cc9958fffdb2c0a10ca378495","pledge":{"ada":{"lovelace":0}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/1","rewardAccount":"stake_test1up3pv0r49hevqvc23q7zfwnza6d0vs3qhf4w9lhg9w93c7qegmfv6","owners":["62163c752df2c0330a883c24ba62ee9af64220ba6ae2fee82b8b1c78"],"relays":[{"type":"ipAddress","ipv4":"18.219.254.123","port":3001}],"metadata":{"url":"https://tinyurl.com/ye2zvyf4","hash":"60586988c5245b4eb59aff8110da9ebe57d4c7e37aaf6e6a3587523aa14fdee1"}},"pool1ltyxtkh37lfuh73ayulf8jdd742kmrqvx8rvt44r65c7q96xh08":{"id":"pool1ltyxtkh37lfuh73ayulf8jdd742kmrqvx8rvt44r65c7q96xh08","vrfVerificationKeyHash":"4a30b9817ba1af57e8a179ab619d8f49d50b7db1016af16741001dcb730b027d","pledge":{"ada":{"lovelace":9400000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"99/100","rewardAccount":"stake_test1uqr86uc2k2kh7rmveddyjyx4q3nwskc8str3k3y3j3est8qd0hz3t","owners":["067d730ab2ad7f0f6ccb5a4910d50466e85b0782c71b44919473059c"],"relays":[{"type":"ipAddress","ipv4":"14.201.4.90","port":6005},{"type":"ipAddress","ipv4":"14.201.4.90","port":6006},{"type":"ipAddress","ipv4":"139.218.11.14","port":6005}],"metadata":{"url":"https://dpadapools.com/preview2meta.json","hash":"63cfd40cdf080705301829a840accb793d0ad8fa8c42863fcd372b91ae3e1d80"}},"pool1l5u4zh84na80xr56d342d32rsdw62qycwaw97hy9wwsc6axdwla":{"id":"pool1l5u4zh84na80xr56d342d32rsdw62qycwaw97hy9wwsc6axdwla","vrfVerificationKeyHash":"39cf4275b0751ee453aee1737c97466543250ec50932dfa0a109a99c9678752b","pledge":{"ada":{"lovelace":127813888409}},"cost":{"ada":{"lovelace":340000000}},"margin":"1/20","rewardAccount":"stake_test1uzwfmyp6jjyupe3pf3h80k5j0p3pzxzn0gf5544p7qzmhmsat2s3z","owners":["9c9d903a9489c0e6214c6e77da9278621118537a134a56a1f005bbee"],"relays":[{"type":"hostname","hostname":"preview.euskalstakepool.win","port":6001}],"metadata":{"url":"https://git.io/JiZgb","hash":"2e421355eb7b4499dd8f0bca206178131f4c9ad90e2bf369ae78aa0c7c4d9472"}},"pool1leml52hm4fcp3hhe4zye08qz27llhj7d339p3gs0tl85cstx59q":{"id":"pool1leml52hm4fcp3hhe4zye08qz27llhj7d339p3gs0tl85cstx59q","vrfVerificationKeyHash":"9bce3347843eea739fe6978c347f08dd6de43443f1964369c42778b874c42783","pledge":{"ada":{"lovelace":9000000000}},"cost":{"ada":{"lovelace":340000000}},"margin":"3/100","rewardAccount":"stake_test1urpj2lxml8ml6dqv58l3f7skw4389e0vq7s22sl8zgekmmcy97awy","owners":["c3257cdbf9f7fd340ca1ff14fa16756272e5ec07a0a543e712336def"],"relays":[{"type":"hostname","hostname":"previewrelay1.intertreecryptoconsultants.com","port":6000}],"metadata":{"url":"https://tinyurl.com/intrtpreview","hash":"b9e21ae6844cd61c812c3d5aec7dbe6f8099962fe1e952d51f297258ba89879f"}}},"id":"queryLedgerState/stakePools-hfkg8z8vlxlxx1je"} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryLedgerState-stakePools-e449fe6e00b4f704f6b9b28c7d42047e.json b/fixtures/test/ogmios/queryLedgerState-stakePools-e449fe6e00b4f704f6b9b28c7d42047e.json deleted file mode 100644 index 0fd2541813..0000000000 --- a/fixtures/test/ogmios/queryLedgerState-stakePools-e449fe6e00b4f704f6b9b28c7d42047e.json +++ /dev/null @@ -1 +0,0 @@ -{"result":{"pool1qzamfq0qzpggch2rk9daqq8skky7rhvs5g38lchnhw67sve4d36":{"id":"pool1qzamfq0qzpggch2rk9daqq8skky7rhvs5g38lchnhw67sve4d36","vrfVerificationKeyHash":"5746d095a8a960de6ebb1fed6acac883a194645b523d5006692a3ba1481ea70e","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uqrty8jrgjn4cywwzds025d64fz39ke2pkjk5rt5nqyrr9gxljplf","owners":["06b21e4344a75c11ce1360f551baaa4512db2a0da56a0d7498083195"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/RSPO5","hash":"9ee2d16fe3a94f0e9ac1fda5b5259ae73612d43ed274504b549e849e863eb992"}},"pool1qrjk9dqdaydy207lw4hf3zlxxg2qlxvxp9kvxx9fscccgwmgfv9":{"id":"pool1qrjk9dqdaydy207lw4hf3zlxxg2qlxvxp9kvxx9fscccgwmgfv9","vrfVerificationKeyHash":"fa730318b97a085aa8722dbb7a2fd59ae35942f880e01c9c8b462d81c84dc4cc","pledge":{"lovelace":9069000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1urdcnx276w4g3h8mgdusutj3wc0uhflgt99ucemgfafd2fqmjjw3u","owners":["db89995ed3aa88dcfb43790e2e51761fcba7e8594bcc67684f52d524"],"relays":[{"type":"ipAddress","ipv4":"194.60.201.143","port":6001}],"metadata":{"url":"https://cardanotech.io/sancho/poolMetaData.json","hash":"ccb6217c050e86cc6128b6c40e9daf5650daeb40225c26abade57c22d68ce7b6"}},"pool1q95luz38nhsw6h7mxud8tptc6mxvnsczhanw4j5htk8h2ltlf3k":{"id":"pool1q95luz38nhsw6h7mxud8tptc6mxvnsczhanw4j5htk8h2ltlf3k","vrfVerificationKeyHash":"00e024fbc63daf0af69eebc5741e7ff183b890ef2628e9bfd4e2bc4d6d1b16b8","pledge":{"lovelace":100000000},"cost":{"lovelace":345000000},"margin":"3/20","rewardAccount":"stake_test1uztsmrxurfw7v3gjz04n8m45kngf4fwhfzxez9wa24rmdxclut9y5","owners":["970d8cdc1a5de6451213eb33eeb4b4d09aa5d7488d9115dd5547b69b"],"relays":[{"type":"ipAddress","ipv4":"83.58.170.227","port":6000}],"metadata":{"url":"https://not.me","hash":"e3568b0190e59d344e0a9803d31ac9fe4ca11c5861b6e3b06527343adbdefae9"}},"pool1qxcz3zxnye8g9ejsqslhl0ljevdx895uc80lr89ulf92gcv40ng":{"id":"pool1qxcz3zxnye8g9ejsqslhl0ljevdx895uc80lr89ulf92gcv40ng","vrfVerificationKeyHash":"e8e9921e6e7428b4a53da8874a843f7cf3ad868cea778f0490dee728273644a5","pledge":{"lovelace":9900000000},"cost":{"lovelace":345000000},"margin":"1/50","rewardAccount":"stake_test1uqm7ecwn9mydtgpnqwcssnc9cq8nsneshs0q9zchq7zrz7gfzcshd","owners":["37ece1d32ec8d5a03303b1084f05c00f384f30bc1e028b1707843179"],"relays":[{"type":"hostname","hostname":"pn1.powerfulpools.com","port":6030}],"metadata":{"url":"https://powerfulpools.com/previewpool1.json","hash":"782694a7c6c9e679f3370bb5aecae8a8988e4c4e37647b2177be59bd0f704ca7"}},"pool1qncwwllw9nwtu7sl7zqw3fpyh4t3q6nhludryfwv0jyqjygd46d":{"id":"pool1qncwwllw9nwtu7sl7zqw3fpyh4t3q6nhludryfwv0jyqjygd46d","vrfVerificationKeyHash":"9b960c725b707c79a4aade62a362be9f35b5b0d7615b8bdd3bfd72a77b0a32a4","pledge":{"lovelace":0},"cost":{"lovelace":345000000},"margin":"1/20","rewardAccount":"stake_test1ur4n0pv3cagnah7atw58qr8an8vm8f75tq5u2q9h925nwasuxt25m","owners":["eb378591c7513edfdd5ba8700cfd99d9b3a7d45829c500b72aa93776"],"relays":[{"type":"hostname","hostname":"beadapool.ddns.net","port":6001}],"metadata":{"url":"https://beadapool.com/media/poolMetaDatapreview.json","hash":"c760f6e23539c052bff72bbc0d921a0663a0fea445b401871d5f65eb3debfc55"}},"pool1q65ag8panwayzaqfs6je7jz2ywt8x2032yaunq5hf25t7t8c26e":{"id":"pool1q65ag8panwayzaqfs6je7jz2ywt8x2032yaunq5hf25t7t8c26e","vrfVerificationKeyHash":"240b5246bc511fa4d7873d91a627aae4e74a60ecfd1165309774a0a7b1dab952","pledge":{"lovelace":42000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzhzr9qzlcr98rhuek3t623e008rye68grawtx6gc5v7g7q2j5u2z","owners":["ae219402fe06538efccda2bd2a397bce32674740fae59b48c519e478"],"relays":[{"type":"hostname","hostname":"test.smaug.pool.pm","port":3003}],"metadata":{"url":"https://smaug.pool.pm/meta-testnet-6adaf6af.json","hash":"6adaf6af9346cc941c916534118b48bdc0e0d560164333d7ab79b113421f2b3b"}},"pool1qal80uhlj949mgv0ecvdkmgqjdn5q27wmpaj4crnr5e9v6qmsv7":{"id":"pool1qal80uhlj949mgv0ecvdkmgqjdn5q27wmpaj4crnr5e9v6qmsv7","vrfVerificationKeyHash":"d498ef12879315f2b3b9bf3d944a42ae4062203db8ebc78236d63f3697f1804c","pledge":{"lovelace":420000000},"cost":{"lovelace":420000000},"margin":"69/1000","rewardAccount":"stake_test1uzpafaxd4q5p7adccdefpnv69dkwlpm7dpkpm3yefxzeluc4z24ec","owners":["83d4f4cda8281f75b8c37290cd9a2b6cef877e686c1dc49949859ff3"],"relays":[{"type":"hostname","hostname":"preview.world.bbhmm.net","port":6200}],"metadata":{"url":"https://pool.bbhmm.net/poolmeta-preview.json","hash":"885cbb02d004f75fad5716c878a6074a9c1bd62b3003d1896b1d27831d67239a"}},"pool1p9xu88dzmpp5l8wmjd6f5xfs9z89mky6up86ty2wz4aavmm8f3m":{"id":"pool1p9xu88dzmpp5l8wmjd6f5xfs9z89mky6up86ty2wz4aavmm8f3m","vrfVerificationKeyHash":"2dd02fc85a8ded714d3d56a684f85d741cef553756d760c8c4d5ae325ab6a1a1","pledge":{"lovelace":1111000000},"cost":{"lovelace":170000000},"margin":"1/100","rewardAccount":"stake_test1uzsf4dc8l9r2uxgwk7vpladqf09vvduw43z6cd0p96ru0gcpg49cx","owners":["a09ab707f946ae190eb7981ff5a04bcac6378eac45ac35e12e87c7a3"],"relays":[{"type":"hostname","hostname":"relay-m.fluxpool.cc","port":5001}],"metadata":{"url":"https://cylonyx.github.io/testnet.json","hash":"99e451a46f89b17502196457698bde37d604fe74ef19a8c0cb8518da72b1ecf1"}},"pool1p835jxsj8py5n34lrgk6fvpgpxxvh585qm8dzvp7ups37vdet5a":{"id":"pool1p835jxsj8py5n34lrgk6fvpgpxxvh585qm8dzvp7ups37vdet5a","vrfVerificationKeyHash":"e67d6ccc4b3b0ca3e61ad09ccf2094b4fbf4eee929e8995c52fa0f32a43a707c","pledge":{"lovelace":100000000000},"cost":{"lovelace":170000000},"margin":"0/1","rewardAccount":"stake_test1upn7ehn9g6e9cqp7jcmuv5a79avzxavxe6g6fmfwttsm6lqa9kp7c","owners":["67ecde6546b25c003e9637c653be2f58237586ce91a4ed2e5ae1bd7c"],"relays":[{"type":"hostname","hostname":"firewall.adamantium.online","port":3000}],"metadata":{"url":"https://testforge.adamantium.online/otg-preview.metadata.json","hash":"5f9824434e7fc57a08ab0fe9d7f09ed59f2601ec138af8be0a3c89305aa2dc9c"}},"pool1pf95k36qu4u4c6psd8qwclnzj9cqmxd32q0305dz4fcxg3wyuu5":{"id":"pool1pf95k36qu4u4c6psd8qwclnzj9cqmxd32q0305dz4fcxg3wyuu5","vrfVerificationKeyHash":"666efbd46910b4a0472219a7e9a198c5b07437329a47a89a9d85ca3b6da806f4","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uqedemevyevg5esgdpdpc9awlepc49nhqln75clf5n4n6tsxqzcvz","owners":["32dcef2c26588a6608685a1c17aefe438a967707e7ea63e9a4eb3d2e"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/CD1","hash":"167b65b63ca316b3d6968ccd60ab59ef18202b7218dd2447170218d0f3c40b77"}},"pool1pt39c4va0aljcgn4jqru0jhtws9q5wj8u0xnajtkgk9g7lxlk2t":{"id":"pool1pt39c4va0aljcgn4jqru0jhtws9q5wj8u0xnajtkgk9g7lxlk2t","vrfVerificationKeyHash":"d9f1792aeb20bf814c367e6b3dd5e2c3f4c7f91f45247da2d0de451a2a2c1f85","pledge":{"lovelace":9000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzftx5dwygs4k88svkh4gp6hz4l628ydvskx5yzff55wlmskas3cr","owners":["92b351ae22215b1cf065af540757157fa51c8d642c6a10494d28efee"],"relays":[{"type":"hostname","hostname":"preview.bladepool.com","port":3001}],"metadata":{"url":"https://public.bladepool.com/metadata.json","hash":"2738e2233800ab7f82bd2212a9a55f52d4851f9147f161684c63e6655bedb562"}},"pool1pw345epmct6cuummleuu5hc7qq2h96zawvf0e9062uw7gnjz9ej":{"id":"pool1pw345epmct6cuummleuu5hc7qq2h96zawvf0e9062uw7gnjz9ej","vrfVerificationKeyHash":"420f04838a553e3e959b9b402e36bdd8123888b5f22126491294238150ba385a","pledge":{"lovelace":1000000000},"cost":{"lovelace":345000000},"margin":"3/4","rewardAccount":"stake_test1urmpvvedk8cjnzxp0g89u87ghenhdkyrwn7vl2qg9aly99cp6ypdy","owners":["f616332db1f12988c17a0e5e1fc8be6776d88374fccfa8082f7e4297"],"relays":[{"type":"ipAddress","ipv4":"73.70.8.87","port":6000}],"metadata":{"url":"https://tinyurl.com/yy69a8eh","hash":"52977d65de765d1ec235c59676d4fea81046dc6ef561ab2790d4c359d8611b1d"}},"pool1pn9sffcqqzkx70m0gujks4h3wf8p4y706t2f0cjcyreekg83wtf":{"id":"pool1pn9sffcqqzkx70m0gujks4h3wf8p4y706t2f0cjcyreekg83wtf","vrfVerificationKeyHash":"3cfeffec7d5b5dbbc4f0494271fad41952fdb82937189fb3f2581d9de3fad81b","pledge":{"lovelace":400000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1up8dnh6ywzs96upw6ycmeafzmkvrv096njjkphgqzuts0wgnxsaqg","owners":["4ed9df4470a05d702ed131bcf522dd98363cba9ca560dd00171707b9"],"relays":[{"type":"hostname","hostname":"preview-r1.panl.org","port":3015}],"metadata":{"url":"https://preview-metadata.panl.org","hash":"a2d8a47fc4d3a6e707487b65b3ab790e6fff71c2afd72f0fe17bc5e523024019"}},"pool1p4kh4yt0vwh6yexf9ae36qfwnch7vqa7l77akh94pv4u6rq7tuk":{"id":"pool1p4kh4yt0vwh6yexf9ae36qfwnch7vqa7l77akh94pv4u6rq7tuk","vrfVerificationKeyHash":"c3e92038b50de0e70bd3066f83c067e1726f126a6cc4c9044f3c87582194bee6","pledge":{"lovelace":1000000},"cost":{"lovelace":568800000},"margin":"1/1","rewardAccount":"stake_test1urull23za5j968nez2952k0fpdzk49raz5qvadyer7d8fxqtpzyfh","owners":["f9ffaa22ed245d1e79128b4559e90b456a947d1500ceb4991f9a7498"],"relays":[{"type":"ipAddress","ipv4":"142.132.218.54","port":6001}],"metadata":{"url":"http://gmbh.roastfrog.com","hash":"62ba8350ad0da97a45cb5cf4940204c702bb5a89c81dff3eab95e35a9657b775"}},"pool1phj3kpraf3vgn0zzlugpts8k6eps8d3fgp9ddceu4s43cq00nzr":{"id":"pool1phj3kpraf3vgn0zzlugpts8k6eps8d3fgp9ddceu4s43cq00nzr","vrfVerificationKeyHash":"d4d04f919daf4e89a556f5555a2a68ba89ccf03f022ee77954b1bf1c37a7c8ff","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1up046thgsc2fg0wcwfzvmpmy6r6c0psanu9wyxg8vcknt9sumrgc7","owners":["5f5d2ee88614943dd87244cd8764d0f587861d9f0ae21907662d3596"],"relays":[{"type":"hostname","hostname":"https://aggregator.dev-preview.api.mithril.network/"}],"metadata":{"url":"https://mithril.network/tbd.json","hash":"5e96bfc37d05582545c91727d73e11a26fa0ebcd4e482a9714d02ab96e83ed19"}},"pool1perfzsuh2l59jd5jzqs0a2774uqmelymuflw9nm3q4lmslpmk92":{"id":"pool1perfzsuh2l59jd5jzqs0a2774uqmelymuflw9nm3q4lmslpmk92","vrfVerificationKeyHash":"2661c5f0a335170cc2342c8dc322c5b47f8e2611df6bcc4d5192adb79cc20257","pledge":{"lovelace":500000000},"cost":{"lovelace":500000000},"margin":"1/20","rewardAccount":"stake_test1uruhhewtul8tkg88vdp4l84ds5t5j4s8tlrdjafr4crh7xckcrc2x","owners":["f97be5cbe7cebb20e763435f9ead85174956075fc6d97523ae077f1b"],"relays":[{"type":"ipAddress","ipv4":"3.72.231.105","port":30002}],"metadata":{"url":"https://cardanofiles.blob.core.windows.net/test/poolMdata.json","hash":"3b29e608eed25bb13c9d0950599634ed6d4f498ec4a748322dff5e5cca5deddb"}},"pool1p79majfcn554nkl88auu5njmprfsx9jdkv29rtltkn44y2h04qy":{"id":"pool1p79majfcn554nkl88auu5njmprfsx9jdkv29rtltkn44y2h04qy","vrfVerificationKeyHash":"b6168f2e63d95d18756328cf2ea0f869c7f227e50e13f55228cf3854dea16475","pledge":{"lovelace":2000000000000},"cost":{"lovelace":170000000},"margin":"99/100","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/c856b8c5-0f0a-42db-8a78-59a.json","hash":"8de3639f2d956664dd0d58903461853572e01355895cbc5932e42e22b0c1b960"}},"pool1p73yrd7vzwkkjd2rff4g683smhlm3jkg45f2hwm79cke6uxxwq9":{"id":"pool1p73yrd7vzwkkjd2rff4g683smhlm3jkg45f2hwm79cke6uxxwq9","vrfVerificationKeyHash":"92a482dd75c257122c3eb24de9b2f3b029319aa4e1ca0ac1125f62a912ce8c9d","pledge":{"lovelace":100000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1urnuwkjxcf0erfm53fx9tnkvs6ye0shcwk3lt0wzzy500tcu0xf8f","owners":["e7c75a46c25f91a7748a4c55cecc868997c2f875a3f5bdc21128f7af"],"relays":[{"type":"ipAddress","ipv6":"2a01:e0a:3d1:770:216:3eff:feb6:d700","port":6000}],"metadata":{"url":"https://api.monrma.fr/meta/JOSEP.json","hash":"6c133a6ba49006eee1fdd1525662d64de10f4a54566e715246525b3b386f0c02"}},"pool1zpsskvu5q00lpezkj53xm7a5y9wv0jqt5j0xsvn42jdx2gajwr6":{"id":"pool1zpsskvu5q00lpezkj53xm7a5y9wv0jqt5j0xsvn42jdx2gajwr6","vrfVerificationKeyHash":"7827b526f0599b169c664b0dd8733a38a702d6d9e868e689cd8404e110a96dcb","pledge":{"lovelace":10000000000},"cost":{"lovelace":170000000},"margin":"0/1","rewardAccount":"stake_test1url5r2tsk5j9sd49exdale4da6vd2ucn44hcqeygqcfdyyc84hjr3","owners":["ff41a970b5245836a5c99bdfe6adee98d57313ad6f8064880612d213"],"relays":[{"type":"ipAddress","ipv4":"90.251.253.249","port":3000}],"metadata":{"url":"https://raw.githubusercontent.com/OYSTERPOOL/GIT/main/prev.json","hash":"cd19e8c622a0c35e0384caeeced99552fe989a6ee8bd98018b8236328663132d"}},"pool1zyvx690fps6a9m3m89q6fwcfgd8jyupzgv8wrfpvd0fm5cyzxd0":{"id":"pool1zyvx690fps6a9m3m89q6fwcfgd8jyupzgv8wrfpvd0fm5cyzxd0","vrfVerificationKeyHash":"e0c09cfd7e6b1766efe46f4297d5ada1a5f8b006c1ed72535e16c6fd2f384174","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"3/100","rewardAccount":"stake_test1uzzx65ylw8yrkeusmfwa6exesgpzlw74630cxusgq3jn9jqrgsrjc","owners":["846d509f71c83b6790da5ddd64d982022fbbd5d45f837208046532c8"],"relays":[{"type":"ipAddress","ipv4":"129.152.11.126","port":3002}],"metadata":{"url":"https://raw.githubusercontent.com/stefanosu-code/stpz/a/s2.j","hash":"0bf71440af0a351555045ae2a59e65c8661748a2781476f9bd560871afb2069f"}},"pool1z2dpsu58adkxtet672s6c46szylvcxs7vk9evq6clj49jcm6s4f":{"id":"pool1z2dpsu58adkxtet672s6c46szylvcxs7vk9evq6clj49jcm6s4f","vrfVerificationKeyHash":"cf027ebfbfec5c3f964b05341519180003e2ed092829a402f775efec666d78e1","pledge":{"lovelace":0},"cost":{"lovelace":456789123000000},"margin":"1/10000000","rewardAccount":"stake_test1uzcyml6eacaevjnana8a5pxe3m6rmcateqepztxr0g6azwq30tk38","owners":["b04dff59ee3b964a7d9f4fda04d98ef43de3abc832112cc37a35d138"],"relays":[{"type":"ipAddress","ipv4":"5.161.75.212","port":5003},{"type":"ipAddress","ipv4":"100.100.100.100","port":100},{"type":"ipAddress","ipv4":"200.200.200.200","port":200}],"metadata":{"url":"https://digitalfortress.online/digi7.json","hash":"0dd9984a4a83fd1e15a182fa318787acfea2d9e26fd416bc71f939367a0dc625"}},"pool1zt3l0pv74ms3j0uspstj3k26ndq93ej37djcw86gkk487pgpthh":{"id":"pool1zt3l0pv74ms3j0uspstj3k26ndq93ej37djcw86gkk487pgpthh","vrfVerificationKeyHash":"17842dce450acb74a96644b90ad38f7713f57f06526b620a4de322506fb67e6e","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uq8slx8ar3a6srktfrwjrqfsj9qgcapd7rn9xxd4z6dssyg4a57zg","owners":["0f0f98fd1c7ba80ecb48dd21813091408c742df0e65319b5169b0811"],"relays":[{"type":"hostname","hostname":"testrl2.duckdns.org","port":6000},{"type":"hostname","hostname":"bbotest.duckdns.org","port":3000}],"metadata":{"url":"https://ada-bamboo.com/testccb.json","hash":"bd75a5e72fe17426f170ac3a3ec1a82b151ddca9ce2f2ad49e0187edcf736c4a"}},"pool1z737pypn7xgvmnwazy6s7z2a8ts37xnpcetnzdn82qth5w6n8sf":{"id":"pool1z737pypn7xgvmnwazy6s7z2a8ts37xnpcetnzdn82qth5w6n8sf","vrfVerificationKeyHash":"4eb3784dc978391209b63132e32cdbd180cdb4eb5a08e2d38551d907907dea51","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uq4r9wzkug92c2pfhl6l60rpnvtqyklncdezr4p7p668rpgnjtsyx","owners":["2a32b856e20aac2829bff5fd3c619b16025bf3c37221d43e0eb47185"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/SSNA","hash":"f801fa03129fb7fc2dc8478c2fc7fbe5a7711be676ca6fb7f6660b09477ea0a1"}},"pool1rzgvf9rytug9p3hz6a9q8zeu3mp6trl70qdyw0g9c7ywzy984yr":{"id":"pool1rzgvf9rytug9p3hz6a9q8zeu3mp6trl70qdyw0g9c7ywzy984yr","vrfVerificationKeyHash":"0e0c0f257842b44b19dda1a20d8e406401f7696725f1c00a5b2768a4c684a089","pledge":{"lovelace":70000000000},"cost":{"lovelace":345000000},"margin":"3/25","rewardAccount":"stake_test1upxxj9un9j6xyaxkxnw0n2hajye3ux6qxn53ex7g4xwdh2cq3xsrd","owners":["4c6917932cb46274d634dcf9aafd91331e1b4034e91c9bc8a99cdbab"],"relays":[{"type":"hostname","hostname":"adarelay-t2-1.nanyka.com","port":1856}],"metadata":{"url":"https://nanyka.com/cardanospo/poolmeta_preview.json","hash":"a14630b7010397fc9bf309f59618b613698851bc1ac5772fd43717405b426bf5"}},"pool1r8t2047f3hj4c070rjns323s5dgyzyrxd2a06v6hkuh7zx7cqp7":{"id":"pool1r8t2047f3hj4c070rjns323s5dgyzyrxd2a06v6hkuh7zx7cqp7","vrfVerificationKeyHash":"f3a05875600f9960501f6b4e3a65b345b018da7a4b11ab2cd61638c08c2370d6","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/40","rewardAccount":"stake_test1urdxvfs090s0wysk9v5fsy70caswrfksjw0j4nzv5xh7ffq06zrw8","owners":["da66260f2be0f712162b289813cfc760e1a6d0939f2acc4ca1afe4a4"],"relays":[{"type":"hostname","hostname":"pv-relays.digitalfortress.online","port":8001}],"metadata":{"url":"https://digitalfortress.online/digi-pv.json","hash":"e42ed99f0b9752054081f0176b33b548bdc3db13558389fef7e0455e990edad8"}},"pool1rf0xxt0xpq0vwyq5jeqn8t9wags7k0mq8vlt0dygkc7rvc85uhn":{"id":"pool1rf0xxt0xpq0vwyq5jeqn8t9wags7k0mq8vlt0dygkc7rvc85uhn","vrfVerificationKeyHash":"41dbf753c8cb0c835d3719de7490a64921a66ad81d598981012a2cf2c1f762f8","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uzvex98c4tw539cel9rj9u7axrxqvpat3r769tlgrw33t3gjxq666","owners":["999314f8aadd489719f94722f3dd30cc0607ab88fda2afe81ba315c5"],"relays":[{"type":"ipAddress","ipv4":"130.162.169.5","port":6000},{"type":"ipAddress","ipv4":"161.0.154.231","port":6000}],"metadata":{"url":"https://tinyurl.com/3kv77zvd","hash":"52daa526fd9d0b35e57ca376d617d0f99068c5f98afd13745f969cc79ef5928f"}},"pool1rwwmnhgsnyzhzpg89lgq4k6uc38qadsdnet9l2xgv34hsjxzj2d":{"id":"pool1rwwmnhgsnyzhzpg89lgq4k6uc38qadsdnet9l2xgv34hsjxzj2d","vrfVerificationKeyHash":"a4057bb1feefee1f968888a3596a6ff463b443ef9d9919398c1b4dbe9a493597","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"99/100","rewardAccount":"stake_test1urarrlsypaptr9lrx8c65qr5qjfd4a6j893caw33mwpxsjgqfxdem","owners":["fa31fe040f42b197e331f1aa00740492daf75239638eba31db826849"],"relays":[{"type":"hostname","hostname":"spec1-staging.spirestaking2.com","port":3005}],"metadata":{"url":"https://data.spireblockchain.com/ADA-PREVIEW/SPF/pool_0.json","hash":"e11362ceaa7817a979a1f703268a0d63a9e65d48e35e5879e4a7e693f47253ed"}},"pool1r0tln8nct3mpyvehgy6uu3cdlmjnmtr2fxjcqnfl6v0qg0we42e":{"id":"pool1r0tln8nct3mpyvehgy6uu3cdlmjnmtr2fxjcqnfl6v0qg0we42e","vrfVerificationKeyHash":"0bf04a518f6e9a49fbc3ca8b98bec244874fa9939427156ec2af28fa2bfdab11","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1uraat6a6egphv996jz7ncmzncp8689fzum4up72c8xfaf4s04shmw","owners":["fbd5ebbaca037614ba90bd3c6c53c04fa39522e6ebc0f9583993d4d6"],"relays":[{"type":"hostname","hostname":"mithril-signer-2.testing-preview.api.mithril.network","port":9092}],"metadata":{"url":"https://tinyurl.com/2nx2ty2d","hash":"8cc5e635ed38182d9c4680129dc8815f7c2af1d0d7c34e36781139a26a47d650"}},"pool1r5mj0h2e5s2kpe0pckesz0x4g8rhr9e5fzr6k598ckjjun5snvk":{"id":"pool1r5mj0h2e5s2kpe0pckesz0x4g8rhr9e5fzr6k598ckjjun5snvk","vrfVerificationKeyHash":"9406b0490a7683eb52c139db3ff4ed3c8f48e6e3c786b9dc12c1fd2639e74ae8","pledge":{"lovelace":5},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uzp8gpkuaz50mqexhfs6tpzqxlznhgdl9ev9q7pv9e9d8dcmva7p6","owners":["827406dce8a8fd8326ba61a5844037c53ba1bf2e5850782c2e4ad3b7","8e901a894907f529925330e4dbb4070e8ee6c45d5a0e85f4102444aa"],"relays":[]},"pool1rk2y9gx6vll8lawzdqlky5p2a3ypzsxg07arg8gmhkjj2905035":{"id":"pool1rk2y9gx6vll8lawzdqlky5p2a3ypzsxg07arg8gmhkjj2905035","vrfVerificationKeyHash":"a86606621866917a797374a33b0dbb73afdb27b82abfe1facdf99f527cc7b434","pledge":{"lovelace":100000000000},"cost":{"lovelace":340000000},"margin":"3/20","rewardAccount":"stake_test1uz6yw4xj9lfkv8dweq3m64vwnmm8c3hpleufjzqf866ar8qjxc6cs","owners":["b44754d22fd3661daec823bd558e9ef67c46e1fe789908093eb5d19c"],"relays":[{"type":"hostname","hostname":"sully.crabdance.com","port":6004}],"metadata":{"url":"tinyurl.com/4uszu5zt","hash":"62710fed07d182806c647d4a2034eccb14035e57f9bb4899aff9ec1c461ee4ae"}},"pool1rutq574pcq30mn9xuytgpqyvn69zq2dnycp2fhnw0hsuyqpnh99":{"id":"pool1rutq574pcq30mn9xuytgpqyvn69zq2dnycp2fhnw0hsuyqpnh99","vrfVerificationKeyHash":"11351c5c5dfe74a8adb76e47b1590ab9e0251915548447db027806fe0d64fd64","pledge":{"lovelace":2000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uz79lrtfw5w9z6pl2047nn7mxtqvzv9x0senqg6g3upwgeqq9zjj6","owners":["bc5f8d69751c51683f53ebe9cfdb32c0c130a67c333023488f02e464"],"relays":[{"type":"hostname","hostname":"preview-node.world.dev.cardano.org"}],"metadata":{"url":"https://git.io/JJWdJ","hash":"bf3eeabce96f495924dc15000ca067699f38fca78ea36e6d69328dc9c88a5e84"}},"pool1r7snhee0af6cykx7vt7ajkdn0cgym9pucpl94m3l9thnw74ggg6":{"id":"pool1r7snhee0af6cykx7vt7ajkdn0cgym9pucpl94m3l9thnw74ggg6","vrfVerificationKeyHash":"7a785758a863bbad51e9fabdeba75009acbe05236f416dacb327c78a5c15a638","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uq578ry6j5t3ud23e4q8grrhfygm0cf6200rwpquts203zs62922g","owners":["29e38c9a95171e3551cd40740c774911b7e13a53de37041c5c14f88a"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/LXSP0","hash":"62acb9589309a17b39d1fa6115541f0fad74d89c07072a835e11fcce93d5d23c"}},"pool1yq5q3unkyr764243l4v3gca6m42jlg04df9k7f5hv00lsjhyj4d":{"id":"pool1yq5q3unkyr764243l4v3gca6m42jlg04df9k7f5hv00lsjhyj4d","vrfVerificationKeyHash":"d6d05e32b4c2eb2e62cb5659d118061473360c2db23a213c377edb2ead2cf591","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1urty9s8ufz8kydh8wfz6k9cqsj4v2q2k5wdu8wtetvlz4fs7adk6p","owners":["d642c0fc488f6236e77245ab170084aac50156a39bc3b9795b3e2aa6"],"relays":[{"type":"hostname","hostname":"pool.sudosu.cyou","port":30443},{"type":"hostname","hostname":"pool.sudosu.cyou","port":30444}],"metadata":{"url":"https://ado-pool.web.app/poolMetadata.json","hash":"aeaaf5c46c1466f65ff731fc3cc82f006acfd0aaedb4d4f6ff665f04224a1bd1"}},"pool1yphncqvpc4n49c4ya3mys7uwpwa25892r70gzkpqglenv093qge":{"id":"pool1yphncqvpc4n49c4ya3mys7uwpwa25892r70gzkpqglenv093qge","vrfVerificationKeyHash":"83602a44cf3b951a3ef83a4d868852ccfa50cc841e93212b302a67c8d1cd9144","pledge":{"lovelace":175000000000},"cost":{"lovelace":345000000},"margin":"1/50","rewardAccount":"stake_test1urt0mxys755epyacjdacm4e0wyyr7kd603tzxrqzstj7auc5l9456","owners":["d6fd9890f5299093b8937b8dd72f71083f59ba7c56230c0282e5eef3"],"relays":[{"type":"hostname","hostname":"129.213.55.211","port":6000}],"metadata":{"url":"https://cardano-blockhouse.de/preview/poolMetaData.json","hash":"b570b17ca6e0b44783f4a18654f14b472460f0f553e2cc29eaa25a7a2f874f09"}},"pool1ywazc6h66tamsfxpfncfhhj282y0j420sze45x3s5qdvkaxssse":{"id":"pool1ywazc6h66tamsfxpfncfhhj282y0j420sze45x3s5qdvkaxssse","vrfVerificationKeyHash":"ad310b61f0ae967eccfcc0557661f421389c9bef3cbef6dc22bf877c7f08f9ea","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1urjxc8q208jfclu9me2zn36luj70d8qsmrgemcga37vr2hg76ymtw","owners":["e46c1c0a79e49c7f85de5429c75fe4bcf69c10d8d19de11d8f98355d"],"relays":[{"type":"hostname","hostname":"relays.planetstake.com","port":30002}],"metadata":{"url":"https://planetstake.s3.eu-west-2.amazonaws.com/STAKEPreview.json","hash":"87fa8b931cb4641c75039d7b3314e9b0d0efc5d0c496d01a67863e7d25453fac"}},"pool1y0uxkqyplyx6ld25e976t0s35va3ysqcscatwvy2sd2cwcareq7":{"id":"pool1y0uxkqyplyx6ld25e976t0s35va3ysqcscatwvy2sd2cwcareq7","vrfVerificationKeyHash":"b2ff1c4e1aee2de9b5212f4d964b6acb09c67e54a9e2aaefdebda42e08125cc6","pledge":{"lovelace":400000000000},"cost":{"lovelace":340000000},"margin":"99/100","rewardAccount":"stake_test1urfvlns8kzw5rl08uns7g35atul8k43unpcyd8we8juwuhclq5pxz","owners":["d2cfce07b09d41fde7e4e1e4469d5f3e7b563c9870469dd93cb8ee5f"],"relays":[{"type":"hostname","hostname":"adaboy-preview-1c.gleeze.com","port":5000},{"type":"hostname","hostname":"adaboy-preview-2c.gleeze.com","port":5000}],"metadata":{"url":"https://tinyurl.com/39a7pnv5","hash":"643a016d84fb171855f8b6d9c9a5efa230fb4665de3ee0ee0a1ed0f486d26be2"}},"pool1ynfnjspgckgxjf2zeye8s33jz3e3ndk9pcwp0qzaupzvvd8ukwt":{"id":"pool1ynfnjspgckgxjf2zeye8s33jz3e3ndk9pcwp0qzaupzvvd8ukwt","vrfVerificationKeyHash":"dbdd412069ed405b8efe1f30d4e7a8ea551a8cbfc949b1a462936e0b55ec632a","pledge":{"lovelace":3000000000000},"cost":{"lovelace":170000000},"margin":"0/1","rewardAccount":"stake_test1urn5vcltkemnl8nnx3xt4ucsej3v45y0r5s4xgkl9v24jpsxs8v3h","owners":["e74663ebb6773f9e73344cbaf310cca2cad08f1d215322df2b155906"],"relays":[{"type":"hostname","hostname":"node1.cardano.gratis","port":6501},{"type":"hostname","hostname":"node2.cardano.gratis","port":6502}],"metadata":{"url":"https://cardano.gratis/poolMetaDataPreView.json","hash":"8bcb8efe6973b8b6bd0918cd356735ff3ce0ca41276fac6fb4b50b900fbcebce"}},"pool1yu60zjc6ykj22ns69e8w5me469r4k4805706vz2mvrnz5qvvfz7":{"id":"pool1yu60zjc6ykj22ns69e8w5me469r4k4805706vz2mvrnz5qvvfz7","vrfVerificationKeyHash":"e84a8a24359b57aec037671ec8597f73ca6d231f06174e7b58c1536ad0f28c9e","pledge":{"lovelace":1000},"cost":{"lovelace":500000000},"margin":"1/1000","rewardAccount":"stake_test1uzp3y24gpe5zjw0nzsc04tteyuhr6yxqpcvl4cg9x6227gcr4s4cs","owners":["83122aa80e682939f31430faad79272e3d10c00e19fae1053694af23"],"relays":[]},"pool19p0rndwuhsyzwjt3v3s946yrq3je8usgcqwn32xjfkd52f3znjf":{"id":"pool19p0rndwuhsyzwjt3v3s946yrq3je8usgcqwn32xjfkd52f3znjf","vrfVerificationKeyHash":"18a7b9fa81478d76b1797a5935f1ba4564c06390ecffb208a02283993f179ceb","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1up829zqr979f4svv7daykuk000nwmvtkas8qpy8rld4t7wqyu059y","owners":["4ea288032f8a9ac18cf37a4b72cf7be6edb176ec0e0090e3fb6abf38"],"relays":[{"type":"hostname","hostname":"mithril-signer-1.dev-preview.api.mithril.network","port":9091}],"metadata":{"url":"https://tinyurl.com/2xn8c23m","hash":"d907a12c9750aa8536fe24bf2e904cef6acc9801d952e851b76530e743244491"}},"pool19zfyfkrfueu8gtqm8mq72fts7z5pte54v0upej5kh905v7q3xya":{"id":"pool19zfyfkrfueu8gtqm8mq72fts7z5pte54v0upej5kh905v7q3xya","vrfVerificationKeyHash":"444a5509caf8074e6bb5f387b93c802837410f45efb4867f22a0e4e4d1fc9866","pledge":{"lovelace":1200000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uqc9rnvul66ud5azgn95678uy5aj8y2cfy734m3caxlyrjc204n8m","owners":["3051cd9cfeb5c6d3a244cb4d78fc253b239158493d1aee38e9be41cb"],"relays":[{"type":"ipAddress","ipv4":"82.208.22.91","port":6003}],"metadata":{"url":"https://www.cardanolink.net/metadata.json","hash":"9e52ad6d3397ef0e196752f5b6c783d159e6e11b012fc426ed10e5e99b44a8af"}},"pool19x5z6h63kq9tvwt9yz8emdf3fry06pnm6lu8lcuqpf9dunqwng8":{"id":"pool19x5z6h63kq9tvwt9yz8emdf3fry06pnm6lu8lcuqpf9dunqwng8","vrfVerificationKeyHash":"8a97230d41bc99a952bbad1382a384fad365521e3e222a1baf227998f6c5fbdd","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uz488lprpyycw8h6jelrudnuw9syv55judndgdqyrmwnl0qnx56dn","owners":["aa73fc230909871efa967e3e367c7160465292e366d434041edd3fbc"],"relays":[{"type":"hostname","hostname":"preview.ada.chicando.net","port":3002}],"metadata":{"url":"https://chicando.net/resources/metadata/ccdo.json","hash":"c2d117b0ee365a4717ae5e1c1659f5246db80a4cc12f1fc437eab19076b8c09b"}},"pool198jfkrkjf5nk9jxs2nwqh0dpswnw7f8vgea7k07dup5wyr0dtwc":{"id":"pool198jfkrkjf5nk9jxs2nwqh0dpswnw7f8vgea7k07dup5wyr0dtwc","vrfVerificationKeyHash":"002345b996b612fbe645a9e51f0bad41c19570417c92dd16f00785619c3b9691","pledge":{"lovelace":100000000},"cost":{"lovelace":345000000},"margin":"17/100","rewardAccount":"stake_test1urx0wzfjh55njew498usze4jaqu3sjaugu8gdjnxm3faj7cmwkhjg","owners":["ccf70932bd293965d529f90166b2e839184bbc470e86ca66dc53d97b"],"relays":[{"type":"ipAddress","ipv4":"73.222.0.99","port":6000}],"metadata":{"url":"https://tinyurl.com/4w5yp728","hash":"af5d091d79115e56fa7b6d0a5d39fe9901141d93a1beed06003b3b44f75b12b1"}},"pool19ta77tu28f3y7m6yjgnqlcs98ak6a0vvtlcn7mc52azpwr4l2xt":{"id":"pool19ta77tu28f3y7m6yjgnqlcs98ak6a0vvtlcn7mc52azpwr4l2xt","vrfVerificationKeyHash":"b06775ea69068784c2735f6211c537ffd5fa50aa3e3e2a798eea1f3b0e4ec98c","pledge":{"lovelace":1000000000000},"cost":{"lovelace":500000000},"margin":"1/1","rewardAccount":"stake_test1ur9l0p6pr3ctkjaewnwawuykwma9skxjhx9nrdafndhs7jsa0vjgx","owners":["db266813b8285a41aaf806024aa16f4c5a3592e1b012460435224de3"],"relays":[{"type":"hostname","hostname":"preview-node.play.dev.cardano.org","port":3001}]},"pool19wrj23gqupswxefaks40xncv69ca83mqck2e9gxwncza6vl8h47":{"id":"pool19wrj23gqupswxefaks40xncv69ca83mqck2e9gxwncza6vl8h47","vrfVerificationKeyHash":"48de9f061019deaba5729b48be6db15e7169a18574c995cbb27d5b89f243ab9f","pledge":{"lovelace":3000000000},"cost":{"lovelace":170000000},"margin":"1/50","rewardAccount":"stake_test1uz2r2kjj8ulkp2l9l8474pfe800ad77yl2p2ksqg6keza9c8azv2g","owners":["94355a523f3f60abe5f9ebea85393bdfd6fbc4fa82ab4008d5b22e97"],"relays":[{"type":"ipAddress","ipv4":"78.131.56.145","port":7362}],"metadata":{"url":"https://tinyurl.com/2s3jx2rs","hash":"502b700e1c714a9e51534f1f61731a1ae1ec251199bdeb0d7d7fa65fa53b4626"}},"pool190ce9qhpzwzveasvngas7kmwqrn54mfvhk9unqmuesykvtadu8l":{"id":"pool190ce9qhpzwzveasvngas7kmwqrn54mfvhk9unqmuesykvtadu8l","vrfVerificationKeyHash":"ecaaf8a89ead238b71ae9054487c229c1c6bc327062c5211dea2ae78c7cb0280","pledge":{"lovelace":1000000},"cost":{"lovelace":805000000},"margin":"1/100","rewardAccount":"stake_test1uz5qfpx4786s0n847grlqcfrg5ja2g980jtnkfal2jxnaccg69qk0","owners":["a80484d5f1f507ccf5f207f061234525d520a77c973b27bf548d3ee3","c9dc49a676087ba0fb1ab1f28b209e647b4139626d732455bb7d5582","f4cceaa5fff7b592e39519942ea8c3b823f3fee622bb3c81a5f5150f"],"relays":[{"type":"hostname","hostname":"us.netspectrum.com","port":13001}],"metadata":{"url":"http://us.netspectrum.com:13002/pool-meta-data.json","hash":"e9a969b627f3cac9581322dab1f352533d63264fcdbb9e46c11bbd25b8b1c5e3"}},"pool19cmwzwk4vetgtutrunar6vkv7z3n8ldq5e7f8javn8m6ynvhuzv":{"id":"pool19cmwzwk4vetgtutrunar6vkv7z3n8ldq5e7f8javn8m6ynvhuzv","vrfVerificationKeyHash":"61e5b9672e64e846c49cbf305ed1ae7de084c6c5b9b2c202589068337d275295","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uqag28j8d0qahxj3q85mzfgzr7k2duckp46t76ju8snrqug9eknpj","owners":["3a851e476bc1db9a5101e9b125021faca6f3160d74bf6a5c3c263071"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/SSND","hash":"9b41da403200a656749255f4575016eaac46b803656bc96616c89dad89728364"}},"pool1xqycqt2kz6ps4r2ggk0jqsln0st5xtw9xgep4xlg2uxgvq6w6h7":{"id":"pool1xqycqt2kz6ps4r2ggk0jqsln0st5xtw9xgep4xlg2uxgvq6w6h7","vrfVerificationKeyHash":"4664efa0023bf465d8e746a80eefa620ee04c0e9455760779bd484a8dadc1e16","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1urr658f2tpkx8jfnmjczdvv2s8zwpug6cnegdxqc4rvuc8cdy3xrz","owners":["c7aa1d2a586c63c933dcb026b18a81c4e0f11ac4f2869818a8d9cc1f"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/LXSP1","hash":"828d2ec12cdfbd0c989b82e8ceb3ea9ba48491ab6453f2c5d66d503048648d53"}},"pool1x9xkvkrfw6htmnflpad0z2aqsxx50f5mwkyzpylw0tlsk9z5uff":{"id":"pool1x9xkvkrfw6htmnflpad0z2aqsxx50f5mwkyzpylw0tlsk9z5uff","vrfVerificationKeyHash":"af51e586a3601de453af80a5d24d88d3e451cc283aff0602d96e2e7f872d983e","pledge":{"lovelace":100000000000},"cost":{"lovelace":170000000},"margin":"1/20","rewardAccount":"stake_test1upeasuglk6mfjthng6xmua0f7q4tzqpsvn3a6wdjry26z0sscd4la","owners":["73d8711fb6b6992ef3468dbe75e9f02ab1003064e3dd39b21915a13e"],"relays":[{"type":"hostname","hostname":"guavarelay.com","port":6000}],"metadata":{"url":"https://github.com/MontiMarti","hash":"72497a1aa897015a10c30bff37371adde3fedf5da930fbf54c40976856782d46"}},"pool1x9tqyeasf0n3zvq6p6dvaeckz828ygcustd3hngs0mmxgpq7n7v":{"id":"pool1x9tqyeasf0n3zvq6p6dvaeckz828ygcustd3hngs0mmxgpq7n7v","vrfVerificationKeyHash":"066490995d792052c4cf4a1010ca55547035261003fd5d42730b92acb165ce4b","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1upd07wdllf3heh5y0c7893gfh04ye5s9r69nq382m4kgtgcd206pr","owners":["5aff39bffa637cde847e3c72c509bbea4cd2051e8b3044eadd6c85a3"],"relays":[{"type":"hostname","hostname":"grokism.com","port":6003}],"metadata":{"url":"https://www.grokism.com/groktnet.json","hash":"b04da3c89fa84062ab55ef8653b00f469f60137afc1d6ff20cd175b00105d888"}},"pool1xg80gqxp89sllgk6xs6ajwjxkjntwjc2wzc9mjsnzchkgm4z2se":{"id":"pool1xg80gqxp89sllgk6xs6ajwjxkjntwjc2wzc9mjsnzchkgm4z2se","vrfVerificationKeyHash":"3efd3ace7be87e59adfbf0196c75d16bae4c46b6c2eeba65c0a32a97c3043eda","pledge":{"lovelace":7500000000},"cost":{"lovelace":340000000},"margin":"1/50","rewardAccount":"stake_test1uppctwdc07j7aeut3kzwkxddtarc8s5znulauvcp8snl6wsx8ttpx","owners":["4385b9b87fa5eee78b8d84eb19ad5f4783c2829f3fde33013c27fd3a"],"relays":[{"type":"ipAddress","ipv4":"95.88.156.175","port":4444}],"metadata":{"url":"https://sharepool-crypto.github.io/share/poolMetaData.json","hash":"396f9b3f3dfaaa606e6459758f580ec461f5e4a416027038ff4565a3891301d8"}},"pool1xgmqwh23yc2jp52k7jn249x56v6nyhl9nhxaeg6hq8tmc5t78rq":{"id":"pool1xgmqwh23yc2jp52k7jn249x56v6nyhl9nhxaeg6hq8tmc5t78rq","vrfVerificationKeyHash":"360f9057c01159a44581ccc4ba786d64b80c551bae0163f09fc408b5779b0e55","pledge":{"lovelace":10000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1ur3yj9zs0cd9mtx43zssh877qmgp5env3pa0hhytw53fw2se7fthy","owners":["e24914507e1a5dacd588a10b9fde06d01a666c887afbdc8b7522972a"],"relays":[{"type":"ipAddress","ipv4":"73.23.36.140","port":6000}],"metadata":{"url":"https://petloverstake.com/PET_Preview2.json","hash":"87b5fae91c87eb8dbd828c24088dfea6dca290170723092a2575a9d654444a85"}},"pool1x2u60w0uupzv6qdn39pvzeapd54q0jqwd6vv4a7wfe76q8lgsth":{"id":"pool1x2u60w0uupzv6qdn39pvzeapd54q0jqwd6vv4a7wfe76q8lgsth","vrfVerificationKeyHash":"b2f21592a1eeebdfd7a29d997d93d6c73b80f11c5818408836033a4e93aca409","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1up22rprkrxxhme8gqfqqntvzjfvw2app3sxn85rgsn2me6gq0r6c2","owners":["54a18476198d7de4e8024009ad829258e574218c0d33d06884d5bce9"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/LXSP3","hash":"fd7246127084e052c2a6bf8005ff1a35fe4dcbb4dc32cf97bc110d5470cbe71f"}},"pool1xkfew9wzhefz2at44eqdu5d6hk6s6xjdjj8h54tgvmymwea4vk3":{"id":"pool1xkfew9wzhefz2at44eqdu5d6hk6s6xjdjj8h54tgvmymwea4vk3","vrfVerificationKeyHash":"4967db4150525352a6eaaec789d27795fc7bb17cfd72da8b0815e43bef540a6f","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1urw67l30v2at04d2uaa6cazpuzl4csa5xmu6k4cvcj9yadccrvm93","owners":["ddaf7e2f62bab7d5aae77bac7441e0bf5c43b436f9ab570cc48a4eb7"],"relays":[{"type":"hostname","hostname":"adaboy-preview-2c.gleeze.com","port":5000}],"metadata":{"url":"https://tinyurl.com/39a7pnv5","hash":"643a016d84fb171855f8b6d9c9a5efa230fb4665de3ee0ee0a1ed0f486d26be2"}},"pool1xe7ey753aw0v79tysaumamkgcugpw9txahxwrrltqjpx25adrkr":{"id":"pool1xe7ey753aw0v79tysaumamkgcugpw9txahxwrrltqjpx25adrkr","vrfVerificationKeyHash":"5837fb2c83c6c2808deb5269be449a4c16cd337a7a27d379e77587f5fce73ce9","pledge":{"lovelace":65000000000},"cost":{"lovelace":170000000},"margin":"1/200","rewardAccount":"stake_test1ur7a6w4l2tkz3p7krp8y6807lnqd6e03awrstq644wfaksczmnpth","owners":["fddd3abf52ec2887d6184e4d1dfefcc0dd65f1eb87058355ab93db43"],"relays":[{"type":"ipAddress","ipv4":"45.32.18.201","ipv6":"2001:19f0:7001:24a6:5400:4ff:fe31:9996","port":4002}],"metadata":{"url":"https://git.io/JI2Zk","hash":"d50f5e2e137f291889af50e054025af04bdc487e747c6cfa2521810157a5dfe6"}},"pool1xas798gr6u5kjy2y34ge0jhpp6fwlg88cycrg28swx50z83a9ye":{"id":"pool1xas798gr6u5kjy2y34ge0jhpp6fwlg88cycrg28swx50z83a9ye","vrfVerificationKeyHash":"342463d308642d685df96501b3727510cd10a690927e80727721c837eaff390f","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1uzcd50ffs5upkujgw2wa88ky099wka33a6yd6y9zexd6cyss0mu6v","owners":["b0da3d2985381b7248729dd39ec4794aeb7631ee88dd10a2c99bac12"],"relays":[{"type":"hostname","hostname":"adaboy-preview-2c.gleeze.com","port":5000}],"metadata":{"url":"https://tinyurl.com/39a7pnv5","hash":"643a016d84fb171855f8b6d9c9a5efa230fb4665de3ee0ee0a1ed0f486d26be2"}},"pool18pn6p9ef58u4ga3wagp44qhzm8f6zncl57g6qgh0pk3yytwz54h":{"id":"pool18pn6p9ef58u4ga3wagp44qhzm8f6zncl57g6qgh0pk3yytwz54h","vrfVerificationKeyHash":"82419eaa78194ea40711dea37ab068e6ee101dd7785fe9e41e9acd4b98290d49","pledge":{"lovelace":1659000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1urpl4kvj3jfn3zxzxud9px6she3suks5fdyygyke7nnpkcslky9um","owners":["c3fad9928c933888c2371a509b50be630e5a144b484412d9f4e61b62"],"relays":[{"type":"ipAddress","ipv4":"51.104.251.142","port":3001}],"metadata":{"url":"https://adacapital.io/adact_preview.json","hash":"e345a478726731a08900d2cbad4b8455815d41b562fe2b862a3d8fd2c3e36d78"}},"pool18xr0tmqrqffd7yu5jh4pq7hs4eezkremxmgzkq8ua4y82dmmrxp":{"id":"pool18xr0tmqrqffd7yu5jh4pq7hs4eezkremxmgzkq8ua4y82dmmrxp","vrfVerificationKeyHash":"d9df3f4eee37db91a204ef07d8240e4822d8a1d0c0009d2384e7057dcd9cd7c8","pledge":{"lovelace":220000000000},"cost":{"lovelace":170000000},"margin":"69/10000","rewardAccount":"stake_test1ur9pv4652sv524d5qdy9q5h354er45jc3s562jp6vjykwwqyz0kzj","owners":["ca16575454194555b403485052f1a5723ad2588c29a5483a64896738"],"relays":[{"type":"ipAddress","ipv4":"130.162.231.122","port":6001}],"metadata":{"url":"https://tinyurl.com/2ku8unuf","hash":"f5d13701d87a7a6d2642c194c7517a411ac662bfe63fa1d1c63f7558ed83e7ea"}},"pool18x0rtv0vznym7cczsunqcfs5atrve4dfcavfmpe7wkg8ga4urve":{"id":"pool18x0rtv0vznym7cczsunqcfs5atrve4dfcavfmpe7wkg8ga4urve","vrfVerificationKeyHash":"2288a7b58fe88ea76717ba5dd7741e4274042e6806307c10804c581788098d9b","pledge":{"lovelace":2000000000000},"cost":{"lovelace":170000000},"margin":"9999/10000","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/f60a27ae-11a4-4e87-9707-3d9.json","hash":"32c22289da648abcb85bf98d81ab0cde0959e92bb01dfd2837966d6b6858d3d0"}},"pool18x5zg95n59xvysu3rq7ygqn6f842ud29dlcc5jmw97xkv2renhy":{"id":"pool18x5zg95n59xvysu3rq7ygqn6f842ud29dlcc5jmw97xkv2renhy","vrfVerificationKeyHash":"eb7084adcbbe7c2f29e4ad162969dfc80ec4d53a1598d2b4277340c29fd99b35","pledge":{"lovelace":9400000000},"cost":{"lovelace":340000000},"margin":"99/100","rewardAccount":"stake_test1upa7k9ag7zpst5h63lpxa9syq5l4wqk2p2qjvfc04j4ncygq73sxl","owners":["7beb17a8f08305d2fa8fc26e9604053f5702ca0a8126270facab3c11"],"relays":[{"type":"ipAddress","ipv4":"139.218.11.14","port":6005},{"type":"ipAddress","ipv4":"14.201.4.90","port":6005},{"type":"ipAddress","ipv4":"14.201.4.90","port":6006}],"metadata":{"url":"https://dpadapools.com/preview1meta.json","hash":"fafe0366055360d905a2f12da33af561518ae141151fadc9a8a61de850c45664"}},"pool18800lgwlelse96swl6e7n0xes7qeqcnlkkgweq0njrxk66zlj9a":{"id":"pool18800lgwlelse96swl6e7n0xes7qeqcnlkkgweq0njrxk66zlj9a","vrfVerificationKeyHash":"a21d1f6c4c25e3c81754fb21b73b20a4cf64264978980ee1b42c4cfed4c0217f","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzfmqylayt305l5h2lh9xe4h5snu8dqm853fkaj0ex92n4sk3zgy0","owners":["93b013fd22e2fa7e9757ee5366b7a427c3b41b3d229b764fc98aa9d6"],"relays":[{"type":"hostname","hostname":"relay1.preview.metablx.com","port":8092}],"metadata":{"url":"https://bit.ly/8BOOL_01","hash":"b8be919f1da5d19de98673907c00530ccb15eb8f728712cfca433432ffc84f77"}},"pool188a03x468k4t908x265knzc29sz7v7wqlvmqaehrk34vkll3e2h":{"id":"pool188a03x468k4t908x265knzc29sz7v7wqlvmqaehrk34vkll3e2h","vrfVerificationKeyHash":"dbefdeb6466e8c439d6f2c433677bb4baadd745778ee83480d29cb54dcda0c25","pledge":{"lovelace":7000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1upha97flpp5xn22nq0n8k3pg5gk85g6p7fmh9u89q8df5kg9axepw","owners":["6fd2f93f086869a95303e67b4428a22c7a2341f27772f0e501da9a59"],"relays":[{"type":"hostname","hostname":"relay3.preview.metablx.com","port":8093}],"metadata":{"url":"https://bit.ly/8BOOM_01","hash":"843ac18da9b54c0fa8262d6bb99868c29dae4ad9181a1ac1e44ed97ff7e8b2bd"}},"pool183nyxe4nwwxs3rmnsxchhlep4guzm8ayhqwr3se0evz7v0jnnd0":{"id":"pool183nyxe4nwwxs3rmnsxchhlep4guzm8ayhqwr3se0evz7v0jnnd0","vrfVerificationKeyHash":"6dbfd220765e0271d5bc9619238ec289d954e4ac9b435f0444bef87c8a89b2ba","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzfjqkmx3uatgthyk70uazalp2vrgg3vffjrwgfc2uwksncxh5z6a","owners":["93205b668f3ab42ee4b79fce8bbf0a9834222c4a64372138571d684f"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/LXSP5","hash":"0db9041127868af4eb8675f134648d2d3776768b2e658206c840867280579ec3"}},"pool18cq0sr4ryw4t63hvgmdp00z7f8h3hgxef0gjldsgk6j75ajza6y":{"id":"pool18cq0sr4ryw4t63hvgmdp00z7f8h3hgxef0gjldsgk6j75ajza6y","vrfVerificationKeyHash":"18c331fcf6535b1d597c8c661c54eedc36029982c3a3b9779e1525ce73b8d884","pledge":{"lovelace":10000000000},"cost":{"lovelace":340000000},"margin":"9999/10000","rewardAccount":"stake_test1uza6lr2dqs8skq7wut7rp77xvn42w67gsqslpca3r6v6kwqxmcuup","owners":["9ca82a28ceafb9b3bbd77faf6ac500519e6fcbd54f49ef387ca507ab"],"relays":[{"type":"hostname","hostname":"relay.preview.cardanostakehouse.com","port":11000}],"metadata":{"url":"https://cardanostakehouse.com/459b8a9e-b96a-43cc-9981-970.json","hash":"e5e31422e1e2bc34d9ddc87aa974ffc841079a0773dc6972b6efbdb17c8d0ffe"}},"pool18ccrdt0hyj6vd9qwzfwttp2dsq0yqxk03h8nvswecr8yctuynt3":{"id":"pool18ccrdt0hyj6vd9qwzfwttp2dsq0yqxk03h8nvswecr8yctuynt3","vrfVerificationKeyHash":"1d77bf5d2db5645ebde81bf496105973c50f780479dffe796772c3fac4382e99","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/2","rewardAccount":"stake_test1urh699v5gws437m5x5qn09mwv68r9jcmmwngltwjeyfpensx3dcvn","owners":["491ed3664c9cb520f39f4d7eb3275dab8e26f0b6b52bb7deeba111f2","7c344ba81cddc582d4683d093fe1cdb152b4ed3809e52cc719e863bd"],"relays":[{"type":"hostname","hostname":"relays.tradingtools.software","port":6000}],"metadata":{"url":"https://tradingtools.software/downloads/pool_description.json","hash":"aff79b84a4543912a5db601af91474b8b4d6077e1c49d3828793f34bacb2219e"}},"pool186kkpzde9e5ns0sy0852k9nwfvs4sg6m7zgkd272sms6xxslzqv":{"id":"pool186kkpzde9e5ns0sy0852k9nwfvs4sg6m7zgkd272sms6xxslzqv","vrfVerificationKeyHash":"671132f505c4fa210ac3f8d35c6d390a610b555d9c16452fd8c80aed79f82275","pledge":{"lovelace":9000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uznvpusq22cmypf9qefkpersmghzqgk492sju2elhfvmnzcrwrrkn","owners":["a6c0f20052b1b20525065360e470da2e2022d52aa12e2b3fba59b98b"],"relays":[{"type":"ipAddress","ipv4":"172.19.0.3","port":3002}],"metadata":{"url":"https://short.gy/huOsbi","hash":"229136efb689e4c9c4246fd9ba19832a815db1b08f8126b2e3df7132e3b4427a"}},"pool18u47gq2ps4hqawl2sfr8uu8rn4yvkue7c68mw45v2ra4wj7pdx0":{"id":"pool18u47gq2ps4hqawl2sfr8uu8rn4yvkue7c68mw45v2ra4wj7pdx0","vrfVerificationKeyHash":"63de13cac6902f7b63a6530ab41297734554bc7932a68496dce10aa187da8bfc","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uzmxaaxxnrk7qcmx7mr3dtshc6e4xgfh5t5w8e690msqtyqgnzx08","owners":["b0348c669fe3cb7446b5084a669e304dd1cff63762352e8355e14482","b66ef4c698ede06366f6c716ae17c6b3532137a2e8e3e7457ee00590"],"relays":[{"type":"hostname","hostname":"4728f95d.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://4728f95d.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool1gslhruyd8pk4f6am9zjjzgwuvetge6tztswwfrjqpnvdsex3455":{"id":"pool1gslhruyd8pk4f6am9zjjzgwuvetge6tztswwfrjqpnvdsex3455","vrfVerificationKeyHash":"59fa47761c925ff90e191c5d7d18d62ddd15ff88094575c2b1b139ea231b8485","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/2","rewardAccount":"stake_test1ur5p8rcnye82hu4ukkt8xru2hqxa3f9z58pe53qkl9wzz0sn83hhf","owners":["e8138f13264eabf2bcb596730f8ab80dd8a4a2a1c39a4416f95c213e"],"relays":[{"type":"hostname","hostname":"spec2-staging.spirestaking2.com","port":3006}],"metadata":{"url":"https://data.spireblockchain.com/ADA-PREVIEW/SPF/pool_1.json","hash":"9f4e03dd87a814ef9407212ca61355edd9ff266d29a14eb43ad8ad312851b2bc"}},"pool1ghxsz57l4rhsju328dk0t8j3ycmz80xtf8w8xzpkk7pfwtca9u9":{"id":"pool1ghxsz57l4rhsju328dk0t8j3ycmz80xtf8w8xzpkk7pfwtca9u9","vrfVerificationKeyHash":"5fa64452a0b245bd9778b32ca0b65ecf13d658903419a4978d5ee70dd1eec6b8","pledge":{"lovelace":5000000000},"cost":{"lovelace":341000000},"margin":"1/25","rewardAccount":"stake_test1uznc9768hq2qvkg3f588ps9gssw05jztp8n0s7zc7tldlmcku0gxs","owners":["a782fb47b8140659114d0e70c0a8841cfa484b09e6f87858f2fedfef"],"relays":[{"type":"hostname","hostname":"preview.testnet.cryptobounty.org","port":6161}],"metadata":{"url":"https://bnty.one","hash":"677d4eba97170f5267a84ca9d12e0c2bdd116c87128aaa2aaf6905912841fa63"}},"pool1fr8hdmcl5vadqdxrtdks6vzc44ddqmxpzfuxeuezjt965z8hr04":{"id":"pool1fr8hdmcl5vadqdxrtdks6vzc44ddqmxpzfuxeuezjt965z8hr04","vrfVerificationKeyHash":"4b4e8c37e61a53313028a84eef9bcd1d0ddc77c5da6570be8d23ab77e0088318","pledge":{"lovelace":100},"cost":{"lovelace":340000000},"margin":"3/10","rewardAccount":"stake_test1uzp3y24gpe5zjw0nzsc04tteyuhr6yxqpcvl4cg9x6227gcr4s4cs","owners":["83122aa80e682939f31430faad79272e3d10c00e19fae1053694af23"],"relays":[]},"pool1fv5dyzcaydlj3gvkxqdjsxvey29cvk5zz8jjxncqhch4xxj3lgr":{"id":"pool1fv5dyzcaydlj3gvkxqdjsxvey29cvk5zz8jjxncqhch4xxj3lgr","vrfVerificationKeyHash":"4ab5835f2302ea9d183e1d56143ee82e224657f46403ffc2bc0c4a557f1afeb6","pledge":{"lovelace":1104000000},"cost":{"lovelace":411000000},"margin":"1/100","rewardAccount":"stake_test1ur9h9qtr739mhuypqmhfxvzux3g9h0tksew8w6ravaj3t8qacq6d9","owners":["c9dc49a676087ba0fb1ab1f28b209e647b4139626d732455bb7d5582","cb728163f44bbbf08106ee93305c34505bbd76865c77687d6765159c","f4cceaa5fff7b592e39519942ea8c3b823f3fee622bb3c81a5f5150f"],"relays":[{"type":"hostname","hostname":"us.netspectrum.com","port":13001}],"metadata":{"url":"http://us.netspectrum.com:13002/pool-meta-data.json","hash":"41bbeb6b2f37c5c9195c4c816fb9b641723b92ba14ecf5f4adf210155b08d0e3"}},"pool1fvmzpfjatfgg0jx5l56ttuprc8g9p42782rdg4e8a9cwvplk9th":{"id":"pool1fvmzpfjatfgg0jx5l56ttuprc8g9p42782rdg4e8a9cwvplk9th","vrfVerificationKeyHash":"02f96e2a0f0e25b1fe59eade571d1389eae47cda456f949de278791ca2f300e7","pledge":{"lovelace":500000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1upvea236pch7jvvrdsxczr0t9t4f5n9plnx4u8rrkz4h74gxy80l0","owners":["599eaa3a0e2fe931836c0d810deb2aea9a4ca1fccd5e1c63b0ab7f55"],"relays":[{"type":"ipAddress","ipv4":"142.132.229.15","port":6001}],"metadata":{"url":"https://udknow.github.io/extend.github.io/pool_MetaData.json","hash":"2afac2a4edec44da0f81ba5bd6c23eb2a895e172c8561c6680819feb4872f667"}},"pool1fw9mq9eyrp5yydl3njau2568jal62rx5f8anp2llt0e5s3pl3py":{"id":"pool1fw9mq9eyrp5yydl3njau2568jal62rx5f8anp2llt0e5s3pl3py","vrfVerificationKeyHash":"171fdc0c6430bddfdc725553a2d84d01042cfb586f1e4b546853da5d96a604db","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uq27femrn9wj07uad23waxfnc29f7wk86s9mddtp7qhlepcnk0r4r","owners":["15e4e763995d27fb9d6aa2ee9933c28a9f3ac7d40bb6b561f02ffc87"],"relays":[{"type":"hostname","hostname":"d8bdbfbe.cardano-relay.bison.run","port":1338}],"metadata":{"url":"https://d8bdbfbe.cardano-metadata.bison.run/metadata.json","hash":"64c1813d814e5c2abb5f65864ec26f0b060d49f3d206a31f34aa6428d7b682e3"}},"pool1fw7yf4mehfuszpdf2g0u72gu8d948qamwut5c6jm3d3lkj3e4an":{"id":"pool1fw7yf4mehfuszpdf2g0u72gu8d948qamwut5c6jm3d3lkj3e4an","vrfVerificationKeyHash":"838ca6096cff572b788d840445bf2167345f3d87485133ebcbfc729af016ee14","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"7/100","rewardAccount":"stake_test1ur7dav7tz75n7qd4p5fx2su0m5vdu6udvpn2aw4gusx536sag3auf","owners":["fcdeb3cb17a93f01b50d1265438fdd18de6b8d6066aebaa8e40d48ea"],"relays":[{"type":"ipAddress","ipv4":"162.55.3.29","port":3003}],"metadata":{"url":"https://test.com","hash":"0ba562271b66ca6929aff5026bb127d05fb7fdab05cb165854f13f57ed87a222"}},"pool1fszljutkfl8kvvnm0l585tzqevuuvyxmp7rt6346q0nkxxg33mj":{"id":"pool1fszljutkfl8kvvnm0l585tzqevuuvyxmp7rt6346q0nkxxg33mj","vrfVerificationKeyHash":"10236e06f67a865caf85cb51a7465dba3e35d0afab2ff55a0ae4626502c91793","pledge":{"lovelace":4567},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1upq6yxehs9le5fzav7476zngs4kvmrn5qane0mwe9y8a8tqzmjfcd","owners":["10417a1f689bb4328ca92d6ba5eae93da2eb2d5e25c34acbbe0cdfee","17cf6f438e4eec78e697919fee6a4a2095207cfd96a3aaa1a84b59c4","41a21b37817f9a245d67abed0a68856ccd8e74076797edd9290fd3ac"],"relays":[],"metadata":{"url":"https://www.updated_location.com","hash":"4cd0cdc50f4220f9c134c7370e68a50142c9e272da4eeba45c1bc367792ef224"}},"pool1fsxwamyfh5aqwg707m69zpfvwyrj5fz5ep7a8yk92wnavck4pdf":{"id":"pool1fsxwamyfh5aqwg707m69zpfvwyrj5fz5ep7a8yk92wnavck4pdf","vrfVerificationKeyHash":"e091185050f16c36c140ff83df893a6ee90abc4e4b6c9e6f61feec71fb2af439","pledge":{"lovelace":1000000},"cost":{"lovelace":340000000},"margin":"1/50","rewardAccount":"stake_test1up50rxfvpmvh2k0e9ku7vypfk5w8280j3w6nm4nkk76qkfcqpc9wn","owners":["68f1992c0ed97559f92db9e61029b51c751df28bb53dd676b7b40b27"],"relays":[{"type":"ipAddress","ipv4":"154.12.248.114","port":6001}],"metadata":{"url":"https://raw.githubusercontent.com/hodlonaut/a/master/t1.json","hash":"81986b8f246cb39979af55fc01215f193df2dc07107989b886e131633e880e43"}},"pool1f7geezz3s4jlcej03v62wm75wvunu2dzwk4qa6fvkjl9j23yp03":{"id":"pool1f7geezz3s4jlcej03v62wm75wvunu2dzwk4qa6fvkjl9j23yp03","vrfVerificationKeyHash":"bb6a74b787c6c3f59dce9524356655c714d28c18af92dc14007a90cd5cf84851","pledge":{"lovelace":2000000000},"cost":{"lovelace":340000000},"margin":"1/25","rewardAccount":"stake_test1uz6wcl67glqj2sfx7e55afxv58g6f0p9rlwq0xyt6cm33hqxczkka","owners":["b4ec7f5e47c1254126f6694ea4cca1d1a4bc251fdc07988bd63718dc"],"relays":[{"type":"ipAddress","ipv4":"194.28.129.203","port":3001}],"metadata":{"url":"https://shorturl.at/hloWY","hash":"3be51e24185ed60ebcc73af79dd1e13167d78093dbbbb4dc61f4e26f1b10e40a"}},"pool12q7fskmv767qv8yn7mvcxj5azam9cdg0lpm3cajjqr2rqxc7y6a":{"id":"pool12q7fskmv767qv8yn7mvcxj5azam9cdg0lpm3cajjqr2rqxc7y6a","vrfVerificationKeyHash":"d1dc9125cf57397889b155799e3e6e89ce70c41b6b3b94d3e6e08a48bc4ea5e3","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"19/1000","rewardAccount":"stake_test1urfrzvw6yyunusyx4creuzysuyly3tqkj353v7fv58jl6hcfyzy5d","owners":["d23131da21393e4086ae079e0890e13e48ac16946916792ca1e5fd5f"],"relays":[{"type":"hostname","hostname":"pv.blockchainlens.org","port":6306}],"metadata":{"url":"https://raw.githubusercontent.com/bclens/cardano/main/pv.json","hash":"82dc82447da80029382fb904948c09431e0848260a504bcf4a75c575a040b05e"}},"pool12yqmdst9axjwgav7jgcu2umfa0vdm8cnh6rq9ctvaqhhvtuys5z":{"id":"pool12yqmdst9axjwgav7jgcu2umfa0vdm8cnh6rq9ctvaqhhvtuys5z","vrfVerificationKeyHash":"f39deed0607f101e4d3de99930f0a1532c914a2796651c6e2bef756eaf0636ed","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1uq5j484c9yd0v2836knjpyldgpy3havq7252xjlyhd2kt2qfcesug","owners":["292a9eb8291af628f1d5a72093ed40491bf580f2a8a34be4bb5565a8"],"relays":[{"type":"hostname","hostname":"alpha.relay.preview.mochipool.com","port":7777}],"metadata":{"url":"https://preview.mochipool.com/poolmeta.json","hash":"156868305e96086404ebfdbef2b552d266771597a206f1bfa34874e83fe46c4a"}},"pool12yrhvezsrqxlafahf02ka28a4a3qxgcgkylku4vqjg385jh60wa":{"id":"pool12yrhvezsrqxlafahf02ka28a4a3qxgcgkylku4vqjg385jh60wa","vrfVerificationKeyHash":"9692c9b1540de270cff040ba6df0d680b91c524b2e01673b97b4679a9e2d91eb","pledge":{"lovelace":1000000000000},"cost":{"lovelace":500000000},"margin":"1/1","rewardAccount":"stake_test1ur9dz9x9yzn65ys0ms72l6gsmk9w3dfdj26qrvknjvlhmrgnzpcmv","owners":["25d448544726958c9232dab0aa12c63b06b1db494ea133b96e73c836"],"relays":[{"type":"hostname","hostname":"preview-node.play.dev.cardano.org","port":3001}]},"pool123gjej7l8f53906d4xp6f2jxa8zxav8arx3t8af5r3fkvgxx2wx":{"id":"pool123gjej7l8f53906d4xp6f2jxa8zxav8arx3t8af5r3fkvgxx2wx","vrfVerificationKeyHash":"442324fe40068b5c1dca530dab61fdbc273e1ec20aed07b13fbba87f6e45840a","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uq8jgpx346l6hwuxa3vdecegtyfcv35wy4hmyfczw39876g0mhcw7","owners":["0f2404d1aebfabbb86ec58dce328591386468e256fb22702744a7f69"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/SSNE","hash":"2424d0726b990ec170fd1f9298bde6cfe1792153ea6ba56387ad098cec30c4ea"}},"pool12645cty3fsa7a79vx2nsd8yupl3quyhr6h3vqk6duqn0yy7vkv0":{"id":"pool12645cty3fsa7a79vx2nsd8yupl3quyhr6h3vqk6duqn0yy7vkv0","vrfVerificationKeyHash":"c1b125e070bea224be6663ebf5cf748194a70cf6aa8c16885b56e684d12450d5","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/bf2f257f-2776-4c14-aae4-1c1.json","hash":"98db945cdff93d149a30e0d9010927f1417fb1b9796c63a2bcbb85cd551b2fb6"}},"pool12l8602apyt7a52l0746te57y4wtl9rv0pxjvsg6w5p7vk2pcwk2":{"id":"pool12l8602apyt7a52l0746te57y4wtl9rv0pxjvsg6w5p7vk2pcwk2","vrfVerificationKeyHash":"254e89d363387a17fecaedaf04ff7cee91be656a25f9d4371416722b078c8c6f","pledge":{"lovelace":100000000},"cost":{"lovelace":345000000},"margin":"6969/10000","rewardAccount":"stake_test1uqjgdtza3mr6k9w76798vs3hpu4dm963rdkpxrlqrcvknmcn38xkh","owners":["2486ac5d8ec7ab15ded78a7642370f2add97511b6c130fe01e1969ef"],"relays":[{"type":"ipAddress","ipv4":"146.235.201.221","port":6000}],"metadata":{"url":"https://tinyurl.com/3rp46mu3","hash":"dc2e0b9de0a745efcfc863dbbb9a69553899c0bdc1daadf2656e9d32ec53cd93"}},"pool1tycl9a9cqgffccgsh0867u65qpk0qlm43kjqggepmflajsmcds6":{"id":"pool1tycl9a9cqgffccgsh0867u65qpk0qlm43kjqggepmflajsmcds6","vrfVerificationKeyHash":"e89c87e0d1527f047cdb4254d8139987124e9a06d07538bfb4ceda29f43ee098","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uzd5msh6y083l597yacq5pcgs82pzfrm50j3nemmynmqfcsg2m4r0","owners":["9b4dc2fa23cf1fd0be27700a070881d411247ba3e519e77b24f604e2"],"relays":[{"type":"hostname","hostname":"e566964e.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://e566964e.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool1t9uuagsat8hlr0n0ga4wzge0jxlyjuhl6mugrm8atc285vzkf2e":{"id":"pool1t9uuagsat8hlr0n0ga4wzge0jxlyjuhl6mugrm8atc285vzkf2e","vrfVerificationKeyHash":"957d1696507a9f88c641db39cc2e34274456efeee9538a2bb4f332f44fb1d25c","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1uq9yp8wqvgpnucpe6s6yavnrvqnuykadx8y40sv0c5ur93gapzeka","owners":["0a409dc062033e6039d4344eb2636027c25bad31c957c18fc53832c5"],"relays":[{"type":"hostname","hostname":"mithril-signer-3.testing-preview.api.mithril.network","port":9092}],"metadata":{"url":"https://tinyurl.com/2qvmy5xy","hash":"adaff9f5327ad0a3b9a47ba88a14100235915c80da2806f9bf8d271dbc0a6e13"}},"pool1txg39f9mdatrvv3mp7nwfj07he3cqe0y4cach06e2z6ykmysytj":{"id":"pool1txg39f9mdatrvv3mp7nwfj07he3cqe0y4cach06e2z6ykmysytj","vrfVerificationKeyHash":"64e14353b2cc4050d5fa27c40acbea2556089d57527e595101ef0e1ef2986009","pledge":{"lovelace":9000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uqe8qlh2xqneakexw06jgfl9pev9r5vqj743de0a6uqw8ygs0gw82","owners":["32707eea30279edb2673f52427e50e5851d18097ab16e5fdd700e391"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3001}],"metadata":{"url":"https://bit.ly/43u9ybcJ","hash":"c1ef608ac6ba33acba208cdbbb2eaa7eb8fc944103f84646040931b1284478e7"}},"pool1tfgdvuc8p8zrmyhxc2g82denxkrxuy9dx5qwzp9lx85xgjedvdg":{"id":"pool1tfgdvuc8p8zrmyhxc2g82denxkrxuy9dx5qwzp9lx85xgjedvdg","vrfVerificationKeyHash":"afb03550e8b2974b2ddeb22231132b361ca45d4b3d4fc45435c053c510dc6481","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uqz3lkuqxjh42yujn5l3zegcvc6a82lmyhr8ylc68sq44fcj9dppz","owners":["051fdb8034af5513929d3f1165186635d3abfb25c6727f1a3c015aa7"],"relays":[{"type":"hostname","hostname":"preview.frcan.com","port":6010}],"metadata":{"url":"https://raw.githubusercontent.com/Mikederel/p/main/p.json","hash":"ade52fe0bf2d23ed509ce2fc5b3990f4178ad8768f66ead1955a1f7e04b11c82"}},"pool1t3pl903zsy3wqgl4392hmuwx8a3f259f3yzhl2ns4xlhskxkr43":{"id":"pool1t3pl903zsy3wqgl4392hmuwx8a3f259f3yzhl2ns4xlhskxkr43","vrfVerificationKeyHash":"dd6686e356e2bec35ee51b17356d801e69917e3b472e2e59d3371e48207fd990","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1urp9rkuj73fqcuc47u3r92huffdmfgnxszkk8nl3dpdmwvqjwpjgz","owners":["c251db92f4520c7315f72232aafc4a5bb4a26680ad63cff1685bb730"],"relays":[{"type":"hostname","hostname":"sator89.ddns.net","port":25369}],"metadata":{"url":"https://capitalstakepool.info/CSP.json","hash":"04028c72c74f04d605fc0d1a04c99357c8563bcf5cc408a6b6e8c7e72176c9d9"}},"pool1tmhw3wga9qdvz5enyxkhm7h9j4u7lp60y9lvvsdv3323wa447y6":{"id":"pool1tmhw3wga9qdvz5enyxkhm7h9j4u7lp60y9lvvsdv3323wa447y6","vrfVerificationKeyHash":"697920a02a8ec26f6b77ad9c0b8744339b26433e80974cfc35f68e4e38fee2f2","pledge":{"lovelace":8000000000},"cost":{"lovelace":340000000},"margin":"29/1000","rewardAccount":"stake_test1uzwev96me9lpndczchkgaytxwrjlny97qh0dl4zk5hs3wagw9s0c3","owners":["9d96175bc97e19b702c5ec8e916670e5f990be05dedfd456a5e11775"],"relays":[{"type":"ipAddress","ipv4":"128.140.96.209","port":8000}],"metadata":{"url":"https://cardano24.com/premeta.json","hash":"bf9b1cfe6a7caf8adb5c868f49d6e2414960aa1fefd815694f4525622c73efd7"}},"pool1vzqtn3mtfvvuy8ghksy34gs9g97tszj5f8mr3sn7asy5vk577ec":{"id":"pool1vzqtn3mtfvvuy8ghksy34gs9g97tszj5f8mr3sn7asy5vk577ec","vrfVerificationKeyHash":"cc688f3f4c8152bbc71cd7b2e8da059856ea06e1520cda4a0724c4cd2632acd3","pledge":{"lovelace":250000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uzyzlml7sqd9kpdq5xv6y6dzme78xtgllpt3yv62mjmj9cg082gaa","owners":["882feffe801a5b05a0a199a269a2de7c732d1ff85712334adcb722e1"],"relays":[{"type":"hostname","hostname":"tn-preview.psilobyte.io","port":4201},{"type":"hostname","hostname":"tn-preview2.psilobyte.io","port":4202}],"metadata":{"url":"https://psilobyte.io/adatest/psb-meta.json","hash":"18c2dcb8d69024dbe95beebcef4a49a2bdc3f0b1c60e5e669007e5e39edd4a7f"}},"pool1vhdl0z496gxlkfpdzxhk80t4363puea6awp6hd0w0qwnw75auae":{"id":"pool1vhdl0z496gxlkfpdzxhk80t4363puea6awp6hd0w0qwnw75auae","vrfVerificationKeyHash":"db19e2b96aabf2a9dd42c8d91d88bca9feff8286e77ca6b0873d4de3b06f7d1e","pledge":{"lovelace":45000000000},"cost":{"lovelace":170000000},"margin":"0/1","rewardAccount":"stake_test1upylhjc96sxhmawg0z4vut0c2nku4nhayul28a0w2msnfdcjyehf0","owners":["49fbcb05d40d7df5c878aace2df854edcacefd273ea3f5ee56e134b7"],"relays":[{"type":"ipAddress","ipv4":"204.216.214.226","port":6000}],"metadata":{"url":"https://bit.ly/48BnVgU","hash":"c74260178b12b253edc70b950a9dc9dbbfb94c4e76f74172dbbe2ad4f06d0879"}},"pool1vhclwkzyf6ahyt260sh5gsr2udz47074q0slxp20sqn75xjy2xx":{"id":"pool1vhclwkzyf6ahyt260sh5gsr2udz47074q0slxp20sqn75xjy2xx","vrfVerificationKeyHash":"5cd33abcda61776fa52893373e96b8c63430635f74d2f604faf23ffdd7fe614c","pledge":{"lovelace":5000000000},"cost":{"lovelace":4321000000},"margin":"1/25","rewardAccount":"stake_test1upvhfqp8qywsyhe45zflp7ytphwuq8uzxtx0eed4agqsl3cx966vk","owners":["59748027011d025f35a093f0f88b0dddc01f8232ccfce5b5ea010fc7"],"relays":[{"type":"ipAddress","ipv4":"10.0.0.31","port":3000}],"metadata":{"url":"https://tinyurl.com/y2z4cvnt","hash":"91514f535468f45ee8bf8aae5c06e69bae95aeaec8775e2ee7c519ec42525c00"}},"pool1vc577hmjzpgz6mlccdv8ddwplfgvjtp639ykqd05anu6jcja69a":{"id":"pool1vc577hmjzpgz6mlccdv8ddwplfgvjtp639ykqd05anu6jcja69a","vrfVerificationKeyHash":"42d1ab64b06293ddcbf63dcf8466939bbfc470cf858b87be468abf46dca407ce","pledge":{"lovelace":1000000000},"cost":{"lovelace":345000000},"margin":"3/20","rewardAccount":"stake_test1uq2ktannndxkd639acvkf3hnllh04ddvmh8ctu9e6u2mstsu6fv2l","owners":["1565f6739b4d66ea25ee1964c6f3ffeefab5acddcf85f0b9d715b82e"],"relays":[{"type":"hostname","hostname":"0.0.0.0","port":6000}],"metadata":{"url":"shorturl.at/itHOW","hash":"d37a27a9a28ece2c898936eaf431287b5cd7b4cd09247a941289273ca70a06a4"}},"pool1vezalga3ge0mt0xf4txz66ctufk6nrmemhhpshwkhedk5jf0stw":{"id":"pool1vezalga3ge0mt0xf4txz66ctufk6nrmemhhpshwkhedk5jf0stw","vrfVerificationKeyHash":"41762f6a5cf97a405230e278c52b9d711937858c3f7c5d54e5d892ca626798c7","pledge":{"lovelace":125000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1uz5ah77y8xvnxs6cyp979hg7fhxezjw39jfrpardqymnz7sg7ea8y","owners":["7981e93ea49a82b02369e8b16b3aca1dd0a015ada02cd72f5f23031b","a9dbfbc43999334358204be2dd1e4dcd9149d12c9230f46d0137317a"],"relays":[{"type":"ipAddress","ipv4":"73.222.122.247","port":23001}],"metadata":{"url":"https://bit.ly/3GNLlTI","hash":"251194136caedddada9227adfe30312af6c011a1628d178fa7377051bd385bd2"}},"pool1vevw38yxlyaxke29d40ace7jzz7d38qtcmd5kk36chf3shh02ek":{"id":"pool1vevw38yxlyaxke29d40ace7jzz7d38qtcmd5kk36chf3shh02ek","vrfVerificationKeyHash":"9b49ae80c094db2bb49ae40e21deb1d7921fde3c8b469e90667c58859836d16c","pledge":{"lovelace":30000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1ur5jhdf8a7lput2qhsa2hndls4h5yh5ukxr7yc7qkdm96jgnrtjmj","owners":["e92bb527efbe1e2d40bc3aabcdbf856f425e9cb187e263c0b3765d49"],"relays":[{"type":"ipAddress","ipv4":"113.43.231.41","port":3001},{"type":"ipAddress","ipv4":"113.43.231.41","port":4001},{"type":"hostname","hostname":"ada.nodes.mresearch.xyz","port":3001},{"type":"hostname","hostname":"ada.nodes.mresearch.xyz","port":4001}],"metadata":{"url":"https://git.io/Jo7m7","hash":"a40c9206f1ccb3e6ccfe71a7eaf7f6d4a0d15770d7b097829089468ed9be21ac"}},"pool1ve7vhcyde2d342wmqcwcudd906jk749t37y7fmz5e6mvgghrwh3":{"id":"pool1ve7vhcyde2d342wmqcwcudd906jk749t37y7fmz5e6mvgghrwh3","vrfVerificationKeyHash":"612e0b5b84ff4e48a924b51e511485a4884a31e9f8094d7ff9f1e190bc1af30d","pledge":{"lovelace":9147456725},"cost":{"lovelace":340000000},"margin":"1/25","rewardAccount":"stake_test1urwy6fkeyl4e38mws7f8k34pyltq6qy5gpn86ws3l67cthccls3hd","owners":["dc4d26d927eb989f6e87927b46a127d60d009440667d3a11febd85df"],"relays":[{"type":"ipAddress","ipv4":"192.168.200.132","port":3001}],"metadata":{"url":"https://raw.githubusercontent.com/mj83263/test/main/tPl.json","hash":"dc4bd67f3b9b6138fcd11b6222a1550d402d367e303cce3e07a683e9c6af8f41"}},"pool1vurgy6s6u7yq36shf9yspesh3rrnd36km8xkghpcr4smgfz278m":{"id":"pool1vurgy6s6u7yq36shf9yspesh3rrnd36km8xkghpcr4smgfz278m","vrfVerificationKeyHash":"1eec12eccea7cdfe494ac8b980a2c6d6a510d44ad87e3fa6f5092d34d86abae4","pledge":{"lovelace":10000000000},"cost":{"lovelace":340000000},"margin":"1/2","rewardAccount":"stake_test1ur0paqh4t5cwgflh4phdjkhvpwdvv3ps6zd8l7cv9ffk20qxjhqwf","owners":["de1e82f55d30e427f7a86ed95aec0b9ac64430d09a7ffb0c2a53653c"],"relays":[{"type":"ipAddress","ipv4":"185.43.205.110","port":3003},{"type":"hostname","hostname":"cardano.illusion.hu"}],"metadata":{"url":"https://www.illusion.hu/cardano/hunada-test.json","hash":"d93c4c6690186dfa973b6a7ee3203a16e953153616d7165895f4ab7b94de6212"}},"pool1vapqexnsx6hvc588yyysxpjecf3k43hcr5mvhmstutuvy085xpa":{"id":"pool1vapqexnsx6hvc588yyysxpjecf3k43hcr5mvhmstutuvy085xpa","vrfVerificationKeyHash":"9f6e5d16ea05c1905907e8aee60b426c7680c32870c2ebe0be50281d889d5cf0","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1uzkxke5d0tjj0utd8tf2v75vytt6wjkx0tp4lr0885slcnqtq2ryf","owners":["ac6b668d7ae527f16d3ad2a67a8c22d7a74ac67ac35f8de73d21fc4c"],"relays":[{"type":"hostname","hostname":"mithril-signer-1.testing-preview.api.mithril.network","port":9091}],"metadata":{"url":"https://tinyurl.com/263p356z","hash":"276f035319f342a84f7e8abf8ec0befde2434bcb29f20f41afd09132fb083fd1"}},"pool1drrylt73ln8jcv0sthcenlkhuan2lfyhthkrrv3vhs9vv4eywdy":{"id":"pool1drrylt73ln8jcv0sthcenlkhuan2lfyhthkrrv3vhs9vv4eywdy","vrfVerificationKeyHash":"c2d3aa0b9ddf84ad6680c8d4dac3375664290b95a290ab7f27c2ebd52bd537cd","pledge":{"lovelace":100000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1up2ldekqxmad8gu89l4dw9r9nde58xvfsh00uhs98x33w4qxeeugs","owners":["55f6e6c036fad3a3872fead714659b7343998985defe5e0539a31754"],"relays":[{"type":"ipAddress","ipv6":"2a01:e0a:3d1:770:216:3eff:fe05:9009","port":6006}],"metadata":{"url":"https://api.monrma.ml/meta/GATOR.json","hash":"66bcc65cac5cb109e0bd4c89696d2dc010902cef15d29f0b73250fc8855af5d3"}},"pool1d4nsv4wa0h3cvdkzuj7trx9d3gz93cj4hkslhekhq0wmcdpwmps":{"id":"pool1d4nsv4wa0h3cvdkzuj7trx9d3gz93cj4hkslhekhq0wmcdpwmps","vrfVerificationKeyHash":"ca839c83356effe8d232fa8dd1335afcf923bf8d151cda561a6e94e0b9f38ac7","pledge":{"lovelace":1000000},"cost":{"lovelace":429000000},"margin":"2/25","rewardAccount":"stake_test1ur8csttjsny8t783dnfeylwangqh94zrahnps3qaw6rphcsswzsft","owners":["cf882d7284c875f8f16cd3927ddd9a0172d443ede618441d76861be2"],"relays":[{"type":"hostname","hostname":"relay.preview.crimsonpool.com","port":3000}],"metadata":{"url":"https://crimsonpool.com/red.metadata.json","hash":"e3db302e127a7929cd741de7df7744448906110f76fb6d7d793716937b7a49a6"}},"pool1dhheyj4y7q8c8nj3z3lkuv9vqfjw75rnt48eet8efcnvczeznr7":{"id":"pool1dhheyj4y7q8c8nj3z3lkuv9vqfjw75rnt48eet8efcnvczeznr7","vrfVerificationKeyHash":"922ce518a7130d31bf31b4501585e51ccb58db022fb4d6fe429ec56eae5f9db9","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzj0zcvrpkt6lv6c2543vshmxqptnxux0qz5nt744e0gjtgycwrj8","owners":["a4f161830d97afb358552b1642fb3002b99b86780549afd5ae5e892d"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/RSPO1","hash":"666f5ac6701133f3b54b43785b2ce4ed4a12432d9a27f3e07583e8714fd8229c"}},"pool1da3p2l74sr347ln6gpmmkkqnnupfxhfh2d7fuur2g7twvddm5ua":{"id":"pool1da3p2l74sr347ln6gpmmkkqnnupfxhfh2d7fuur2g7twvddm5ua","vrfVerificationKeyHash":"d67f65e8c4fa6346a631b6623b35951e63596920c2ccf1c9d4a836fcea66846c","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uzv69q0u5g7zdvepd96ljt0ngex4gdhules9pj9m73s8w3csm5xm5","owners":["99a281fca23c26b3216975f92df3464d5436fcfe6050c8bbf4607747"],"relays":[{"type":"hostname","hostname":"west.piada.io","port":6000}],"metadata":{"url":"https://piada.io/piada_preview.metadata.json","hash":"f4bf83eb38af4c225b5ee264085d5c0bb529e2016e50b731e590019d37c780f0"}},"pool1damnajda3jh3tch3zcpk9f5pajuyeud820n0q7qesxyyx62cel2":{"id":"pool1damnajda3jh3tch3zcpk9f5pajuyeud820n0q7qesxyyx62cel2","vrfVerificationKeyHash":"4afa907233b0f44c6d6293e323a986854fcb0bbc2ba818daa48dc5ef7dd8e048","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/50","rewardAccount":"stake_test1uqnkzt5ju2c6enmg04k63hz9ryc4lgxrjr5ygfq88kfsymczryjw6","owners":["27612e92e2b1accf687d6da8dc4519315fa0c390e84424073d93026f"],"relays":[{"type":"ipAddress","ipv4":"52.166.113.150","port":6000}],"metadata":{"url":"https://raw.githubusercontent.com/aleincsharp/a/main/md.json","hash":"49222a06d7b62846b99583b1dcb76d835bb62b1cec8edf5c4744c1d398182a5e"}},"pool1wx2daxr2qgh4yhf9mn4se8kyadj4cnyad6zkt7eyufhwvz2ycyh":{"id":"pool1wx2daxr2qgh4yhf9mn4se8kyadj4cnyad6zkt7eyufhwvz2ycyh","vrfVerificationKeyHash":"45a81cd08738c9bdb890a312f394a8aabc344f9f5e17dae53a877aa966f3293a","pledge":{"lovelace":2000000000},"cost":{"lovelace":340000000},"margin":"3/100","rewardAccount":"stake_test1uzgcmw4nr5ytnfpvr7khq5nsgh87qc79yat66wzu7s7kzwcqdzjlz","owners":["918dbab31d08b9a42c1fad70527045cfe063c52757ad385cf43d613b"],"relays":[{"type":"hostname","hostname":"10.0.3.15","port":6000}],"metadata":{"url":"https://gaiastakepool.com/wp-content/uploads/2023/10/md.json","hash":"d123bf56ab892805ea6c215c88af2b73ba9e7eafc156fc19f27e9f6cf5441272"}},"pool1w83ux7vrwafrsuz044knxl9xxtr38q5jj2l3p28fl3g26faqqwg":{"id":"pool1w83ux7vrwafrsuz044knxl9xxtr38q5jj2l3p28fl3g26faqqwg","vrfVerificationKeyHash":"5c44de7dcbbf485040edf760fe91855693ea7e2290a6a9f4b25efdc42a37b025","pledge":{"lovelace":0},"cost":{"lovelace":10000000000},"margin":"1/2","rewardAccount":"stake_test1urqntq4wexjylnrdnp97qq79qkxxvrsa9lcnwr7ckjd6w0cr04y4p","owners":["c13582aec9a44fcc6d984be003c5058c660e1d2ff1370fd8b49ba73f"],"relays":[{"type":"hostname","hostname":"test.stakepool.at","port":9001}],"metadata":{"url":"https://my-ip.at/test/previewpool.metadata.json","hash":"069457ca9fdc1bbeac1f7b4602b9d8fe8ee4255f8af724de2f79702c464402fc"}},"pool1wwh3k3ldzujdvgxllfwlnnkxyheafkacqlufnvpr77n5q72f9hw":{"id":"pool1wwh3k3ldzujdvgxllfwlnnkxyheafkacqlufnvpr77n5q72f9hw","vrfVerificationKeyHash":"81fd203455043724337724f64e67ebbb208d3885ac0063c8b14c4b2bea0bec5e","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1uz3s7gd3rhe9ptechqj7z2r7l6l2gr42rv3lvu4grsdnapg88utxm","owners":["a30f21b11df250af38b825e1287efebea40eaa1b23f672a81c1b3e85"],"relays":[{"type":"ipAddress","ipv4":"51.77.24.220","port":4003}],"metadata":{"url":"https://www.stakecool.io/pools/pvcool-001.metadata.json","hash":"aade4d000f39df2f9ebfc4e23c9a3c49850236fcb924edc1f4da9be844d9691f"}},"pool1wjz475nwhq3fnhfvrjesf4pw70k27fnc5mzvsrzqlxfhy60rmu3":{"id":"pool1wjz475nwhq3fnhfvrjesf4pw70k27fnc5mzvsrzqlxfhy60rmu3","vrfVerificationKeyHash":"663f0b5d8bebb6622de18c0121d3d5bbcb1824b749fe4cbd41a0b232ff4b982e","pledge":{"lovelace":0},"cost":{"lovelace":170000000},"margin":"1/100","rewardAccount":"stake_test1uq3n393q95qu7nswzvnx688ukq69e4p3r78euf2kfwsxg2sygp0rv","owners":["233896202d01cf4e0e13266d1cfcb0345cd4311f8f9e25564ba0642a"],"relays":[{"type":"hostname","hostname":"preview-relays.onyxstakepool.com","port":3001}],"metadata":{"url":"https://onyxstakepool.com/PV-ONYX1.json","hash":"c9e5e56c46dd015c183978583e6f9bc71f7abfc4dc4f949ca12a6f5aff8778fa"}},"pool1w75ukvh77hhz8c2u6rhfjvqlxyptwg37yrkddzatu99qxwwlqhd":{"id":"pool1w75ukvh77hhz8c2u6rhfjvqlxyptwg37yrkddzatu99qxwwlqhd","vrfVerificationKeyHash":"dedb7862c992b2fddfc5fe012e573aead78a0b844ca73748c9feb45a0d68666a","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1urelmc7gcf4ukdf0lakusaunerkm8h6hqzvfgx8z4sflpjc4xeg7h","owners":["f3fde3c8c26bcb352fff6dc87793c8edb3df5700989418e2ac13f0cb"],"relays":[],"metadata":{"url":"https://your_pool_website.com","hash":"6bf124f217d0e5a0a8adb1dbd8540e1334280d49ab861127868339f43b3948bf"}},"pool1w757a30j8cd6nlf5dn9q52lm5ee0fn5permvtlr7mycucpkn6c5":{"id":"pool1w757a30j8cd6nlf5dn9q52lm5ee0fn5permvtlr7mycucpkn6c5","vrfVerificationKeyHash":"6ee546ad0102c3576526fc600b4ab806d5ae3f2cd037110d4cd2505c31c05a18","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"9/500","rewardAccount":"stake_test1uzu2wh3mwjg0pua454hskmehvvte4ut9nn22tqxzuycdclq5kuf7g","owners":["b8a75e3b7490f0f3b5a56f0b6f3763179af1659cd4a580c2e130dc7c"],"relays":[{"type":"ipAddress","ipv4":"139.180.205.134","port":6000}],"metadata":{"url":"https://stakinghouse.com/poolMetaData.json","hash":"021ca91a9f24147bd20c4b7f9a4a1a329998e5fa2ac2a362b40850749ff54b1d"}},"pool10gqm62xy7caj6jhhefsl7h59kse3rv2esuh9rvx55eze2n8dlrj":{"id":"pool10gqm62xy7caj6jhhefsl7h59kse3rv2esuh9rvx55eze2n8dlrj","vrfVerificationKeyHash":"8a9f2e79f70743bdc43b20da993c90b9512849f939fb5b6c3bdad80b5ff3261e","pledge":{"lovelace":25000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uqj0hyhn72p495gntxzt4g9au76ycpcvku693mpexqxdk5s7cwqed","owners":["24fb92f3f28352d1135984baa0bde7b44c070cb73458ec39300cdb52"],"relays":[{"type":"hostname","hostname":"preview.relay.beerpool.io","port":6000}],"metadata":{"url":"https://beerpool.io/poolmeta.json","hash":"3f2d006aa149ac16689d6dd5d0dbbe46d87b41d4b8a282e7621996b6a64cd819"}},"pool10d303wup90j39mmvysf0lhr2xmr3mf38y5vs577nmlq6yy8n666":{"id":"pool10d303wup90j39mmvysf0lhr2xmr3mf38y5vs577nmlq6yy8n666","vrfVerificationKeyHash":"7e076f5dd02cead70dcd2058305392b67f66b8e4e6dc553fa032b918c5ddbce0","pledge":{"lovelace":2090000000},"cost":{"lovelace":340000000},"margin":"1/25","rewardAccount":"stake_test1uqucdhr6kfvgzp2py95cqtqhvmpzswtgh8z6t2klnfr9vdgm7c25a","owners":["3986dc7ab2588105412169802c1766c2283968b9c5a5aadf9a465635"],"relays":[{"type":"hostname","hostname":"scarborough1.ddns.net","port":6000},{"type":"hostname","hostname":"scarborough1.ddns.net","port":6001},{"type":"hostname","hostname":"scarborough1.ddns.net","port":6002}],"metadata":{"url":"https://raw.githubusercontent.com/poonasor/cbcp/main/meta.json","hash":"c23b67ca0d0c470bc2816afa0f0bcf4a46374148be2bcf80a204c03dd1148d09"}},"pool105wx68zqse6v4wyx09nkqhxhmf7e0zj349pclyqsjqch7953j0x":{"id":"pool105wx68zqse6v4wyx09nkqhxhmf7e0zj349pclyqsjqch7953j0x","vrfVerificationKeyHash":"7b0cb25a2a5abf1a97523355002a173cd9ff4b2108b7ace2b4693ee406b06eef","pledge":{"lovelace":9000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uz575pc99c8tr8n09u9ek3vhuys7202naetcj83l6fuzrxqpd3ml9","owners":["a9ea07052e0eb19e6f2f0b9b4597e121e53d53ee57891e3fd2782198"],"relays":[{"type":"hostname","hostname":"relay1.doctorstake.network","port":6061}],"metadata":{"url":"https://doctorstake.network/pvpoolmetadata.json","hash":"8ad1a438122bcbab46ab21bb077e818948b2d53d8c9798d0598cad713214663b"}},"pool1057njzaaz280688ppewa3df4qshspvh98njh5n4lq4cg7ntcsyj":{"id":"pool1057njzaaz280688ppewa3df4qshspvh98njh5n4lq4cg7ntcsyj","vrfVerificationKeyHash":"a63ae2342ab8c541978c1f12f0a2338b78b1486c9c6fcdc5d516df4f08bbd93f","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uqmeldflttkgjsjelhzxmznfklc2d8awc9g2afs07m55kfcv70208","owners":["379fb53f5aec894259fdc46d8a69b7f0a69faec150aea60ff6e94b27"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/RSPO2","hash":"170ccb211dcc6ca0074b6f36077799a40a1d5aa421066feb09a5aa60692e9db0"}},"pool10cpz0zepq23hm6lrk8vgnsdwl772lasq9caaemvw9kh9ktxqygk":{"id":"pool10cpz0zepq23hm6lrk8vgnsdwl772lasq9caaemvw9kh9ktxqygk","vrfVerificationKeyHash":"d203f215f4ebd6374ca67745a4d7ca99caff1b1b364cc630d18519e5ddb118ac","pledge":{"lovelace":2000000000},"cost":{"lovelace":340000000},"margin":"3/100","rewardAccount":"stake_test1uzp6ykjc52zfcx5a5xqcxdwv20s66y0pqmzpn4pczuqpzqs83gzya","owners":["83a25a58a2849c1a9da1818335cc53e1ad11e106c419d43817001102"],"relays":[{"type":"hostname","hostname":"esq.ddns.net","port":6010},{"type":"hostname","hostname":"esq.ddns.net","port":6011}],"metadata":{"url":"https://raw.githubusercontent.com/bspdefi/esq/master/meta","hash":"7ae1ee1e5ad1645a9f8ee5bde677cbddafe60bcb1d014e655451ab5777aec7f7"}},"pool10c40pnzz3e00kuej05xfcs2ptkekhys48q7qc4jjcsysypj46qv":{"id":"pool10c40pnzz3e00kuej05xfcs2ptkekhys48q7qc4jjcsysypj46qv","vrfVerificationKeyHash":"904c35106259f1c80add13381d730f8bf6291499b9df48dd19a930d0ab865093","pledge":{"lovelace":8000000},"cost":{"lovelace":340000000},"margin":"3/20","rewardAccount":"stake_test1uqk6t7lajwssrzer6xjarc0n78y26d7p3lswnzrnnegng5ggr5lhm","owners":["2da5fbfd93a1018b23d1a5d1e1f3f1c8ad37c18fe0e988739e513451"],"relays":[{"type":"hostname","hostname":"preview.seaside-staking.best","port":18000}],"metadata":{"url":"https://raw.githubusercontent.com/Seaside-Staking/m/main/m.json","hash":"d843ac7c8ab3a17fe28d5a68c975dc846fe87479364bcff7dd3b30e5c442ca07"}},"pool106rnmvjt0n27y34py0qytashgm04v4hlqurp3w28z789v8scxat":{"id":"pool106rnmvjt0n27y34py0qytashgm04v4hlqurp3w28z789v8scxat","vrfVerificationKeyHash":"482a895958b40cb9b00aa0069ded71dc7516c203e8b30d3c9993d7a3e50d47f6","pledge":{"lovelace":10000000000},"cost":{"lovelace":345000000},"margin":"3/50","rewardAccount":"stake_test1ur8xh997mc3p7vduu0ufkm3wda6dan9wxv3zz4rhguzglqs3elq2d","owners":["ce6b94bede221f31bce3f89b6e2e6f74deccae332221547747048f82"],"relays":[{"type":"ipAddress","ipv4":"190.225.246.141","port":6000}],"metadata":{"url":"https://t.ly/QCIeZ","hash":"5dba9fe7cd4be8e0aebea2012090d3f0f5dcb6f14f86b2a9aa0596b568763bb1"}},"pool10u9jtq8xewg3x80fulh7tuucktckfqzm9h38lz3ldp64y57fku0":{"id":"pool10u9jtq8xewg3x80fulh7tuucktckfqzm9h38lz3ldp64y57fku0","vrfVerificationKeyHash":"2c1baf122a9eb546c89b8cd975461cf2a82fc0ef370cb53459e24d39ca852c4e","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1upq35kyukearpcp58waywdpxxwc3k8kt75cs05mz3mssm6g7ac95u","owners":["411a589cb67a30e0343bba47342633b11b1ecbf53107d3628ee10de9"],"relays":[{"type":"ipAddress","ipv4":"13.229.226.159","port":3001}],"metadata":{"url":"https://git.io/JJWdJ","hash":"d5688399cc3e9c839a21d4ae577e1e7ac4de2e97f54cc05b228e4b53bc6fd52d"}},"pool1srdhn8v6ly36vdvvzthjkv6jjp7wqnzated6unxujrmzkqn40hm":{"id":"pool1srdhn8v6ly36vdvvzthjkv6jjp7wqnzated6unxujrmzkqn40hm","vrfVerificationKeyHash":"8b69b1e8752c05884f3356cf375b648f62110997de4bb5f60f7ee2a75153b115","pledge":{"lovelace":100000000},"cost":{"lovelace":345000000},"margin":"3/20","rewardAccount":"stake_test1upzd8a7wtfwfumdlnf95shwezqg6hpqcvuah8t372atntas9rpfa6","owners":["44d3f7ce5a5c9e6dbf9a4b485dd91011ab8418673b73ae3e575735f6"],"relays":[{"type":"hostname","hostname":"cbfr.ddns.net","port":6000}],"metadata":{"url":"https://cardanoblockchain.fr/md.json","hash":"b29d5f3120ef7dd8cfbbf7204e5c923a6a21ae821f6870abb374a7adaedb76a4"}},"pool1stkzkvxqcd0vx0trg34wjntvs94kykk3260p6lrqsp8fjn8zqf5":{"id":"pool1stkzkvxqcd0vx0trg34wjntvs94kykk3260p6lrqsp8fjn8zqf5","vrfVerificationKeyHash":"c068cab82739462b7f5c3c937105e9194e09d6aba368c3ebdef1a235bca1d450","pledge":{"lovelace":1},"cost":{"lovelace":341000000},"margin":"9/10","rewardAccount":"stake_test1upps8qhch0n9a79fms75tgtxrvutt6qzj0lktz0fa7evyssnnpavx","owners":["31888329dde5e0bf984d564311c8d1f409212227301c6e63d9a0c80b","430382f8bbe65ef8a9dc3d45a1661b38b5e80293ff6589e9efb2c242"],"relays":[],"metadata":{"url":"https://www.where_metadata_file_is_located.com","hash":"767a3a2606485fd86800173f6878b387ab908523019e2b181b48196b41114db4"}},"pool1s337lucxxrhl8tz8c3r6c4crk784xtga225w3uh2tm0w2kqf0l9":{"id":"pool1s337lucxxrhl8tz8c3r6c4crk784xtga225w3uh2tm0w2kqf0l9","vrfVerificationKeyHash":"a34e2815232397c8680656eda7bb0a7f47531715a083e68432fd18c9a03049e8","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1urp5muju83v5853rwpe7g7yt7u8la35uqpa08ym07ht7jqqymvhfn","owners":["c34df25c3c5943d2237073e4788bf70ffec69c007af3936ff5d7e900"],"relays":[{"type":"ipAddress","ipv4":"69.244.216.147","port":6000}],"metadata":{"url":"https://arcadiastakepool.com/INDGO.metadata.json","hash":"874b5cffdb3cb0720d82802bfc9b68446d858d852dd7694be43a291000fdadbe"}},"pool1sj3gnahsms73uxxu43rgwczdw596en7dtsfcqf6297vzgcedquv":{"id":"pool1sj3gnahsms73uxxu43rgwczdw596en7dtsfcqf6297vzgcedquv","vrfVerificationKeyHash":"e8c4df26e49c8f3c7a033297fffb3732f54563e89e5db9ef812380eb708a1733","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"3/100","rewardAccount":"stake_test1up5zw8rhwj7ew09ggqtzdrrlg77xq3et7627wegaylgt5fc2lvmw7","owners":["68271c7774bd973ca84016268c7f47bc60472bf695e7651d27d0ba27"],"relays":[{"type":"ipAddress","ipv4":"5.12.45.138","port":1337}],"metadata":{"url":"https://tinyurl.com/mpde34ve","hash":"cb74d28b4cacd5153c146fb2bc5eaf3428d87db172ef4e8efb63575bb8b5e316"}},"pool1s5c2wws3s0trn7agdrwfgz3knq37pule65knyxh0s0dhkdvhn3h":{"id":"pool1s5c2wws3s0trn7agdrwfgz3knq37pule65knyxh0s0dhkdvhn3h","vrfVerificationKeyHash":"e57ecb6a02223c6e8ee503c94929947462fdd2acdad2190360478274a95d6bb1","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/25","rewardAccount":"stake_test1urj7dmqqqfd6qsl8638ezh3zu7lh0cjsfc92q2uf2d2calg458h8e","owners":["e5e6ec00025ba043e7d44f915e22e7bf77e2504e0aa02b8953558efd"],"relays":[{"type":"hostname","hostname":"0c563fdf.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://0c563fdf.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool1sk8n2v844jgpwzvpd4eze374pfvygzcrqlld2mfzx484yrtq74l":{"id":"pool1sk8n2v844jgpwzvpd4eze374pfvygzcrqlld2mfzx484yrtq74l","vrfVerificationKeyHash":"1cbfd07a6145d0d2859c4d114f7e71cb5b9fc7e29cbfa37a393db2637241ce92","pledge":{"lovelace":9000000000},"cost":{"lovelace":400000000},"margin":"0/1","rewardAccount":"stake_test1uqza4tpx4698h0w793fjhtnqh4amhyfcftyx78h54q2wh0qgq074z","owners":["05daac26ae8a7bbdde2c532bae60bd7bbb91384ac86f1ef4a814ebbc"],"relays":[{"type":"hostname","hostname":"relay1.dynip.org","port":28000}],"metadata":{"url":"http://panyvino.com","hash":"9ac046260b09e2befc7addb05b469f90279338821285da90f5cc6e8cb4c5ab15"}},"pool13q0eh32ptwmns8wyket34dnzal6jwltc6audq4s5ehcdg9e7xvs":{"id":"pool13q0eh32ptwmns8wyket34dnzal6jwltc6audq4s5ehcdg9e7xvs","vrfVerificationKeyHash":"66cf87b05688c2872b17f57da72550758a8cd23097484f68803b8f250d9f90bc","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1uq90sudgsaa0wj4z27yeeeggwpjyzh6w2kxvujffcax0llc8aqm32","owners":["0af871a8877af74aa257899ce5087064415f4e558cce4929c74cffff"],"relays":[{"type":"ipAddress","ipv4":"127.0.0.1","port":6000}],"metadata":{"url":"https://raw.githubusercontent.com/politikoz/p/master/p.json","hash":"0321dff086209d0f90a1804199e4c296e91b2bbc6fdbb596af11a51c4d1d2c4f"}},"pool13zafxlpfgymf474uv52qt557z5k5frn9p83yr55zp267wj5mpu4":{"id":"pool13zafxlpfgymf474uv52qt557z5k5frn9p83yr55zp267wj5mpu4","vrfVerificationKeyHash":"628980b886a274e43a09810a91f8a1e1d8241a8c67ddf51e78c8efff1236698a","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1ur0vznanca5kzcwmjyscudf6f38wal8qxcr4nkefdh089mg2kg7lh","owners":["dec14fb3c7696161db91218e353a4c4eeefce0360759db296dde72ed"],"relays":[{"type":"hostname","hostname":"mithril-signer-2.pre-release-preview.api.mithril.network","port":9092}],"metadata":{"url":"https://tinyurl.com/2fej7w5a","hash":"85212d92b197fa7402e0047ed2f2411cabfab4ad1ee54201f5043c0a0fcbaeca"}},"pool13rh3005usjnr7ks76llpn07p0z4dxnxzp8aj33lnncaawfp9vn6":{"id":"pool13rh3005usjnr7ks76llpn07p0z4dxnxzp8aj33lnncaawfp9vn6","vrfVerificationKeyHash":"9ab23eba9fbe7912061f4e2dbc1a4f98ea684156f2811737452506c70cf54e44","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1uq5j484c9yd0v2836knjpyldgpy3havq7252xjlyhd2kt2qfcesug","owners":["292a9eb8291af628f1d5a72093ed40491bf580f2a8a34be4bb5565a8"],"relays":[{"type":"hostname","hostname":"alpha.relays.preview.mochipool.com","port":7777}],"metadata":{"url":"https://preview.mochipool.com/poolmeta.json","hash":"96e877b9c2852f47a31570794f4845c3cf9c5e2a78687129a770d2c7768efd62"}},"pool1397kpa7ylzg4lqrmj3xr28xzq2548c8lafw90qyxvucsslap03v":{"id":"pool1397kpa7ylzg4lqrmj3xr28xzq2548c8lafw90qyxvucsslap03v","vrfVerificationKeyHash":"9381a0f5511d5f033eb8b707ae620e038e6c8abca7f6d0200331cbe2c7b3cb7e","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/50","rewardAccount":"stake_test1ur2wt3rv5sty3eh6ge9fcxapn0v4ytne06tvdvg8vlv7y8cqvs5eh","owners":["d4e5c46ca41648e6fa464a9c1ba19bd9522e797e96c6b10767d9e21f"],"relays":[{"type":"hostname","hostname":"relay1.preview.stakepool.quebec","port":4000}],"metadata":{"url":"https://qcpol.stakepool.quebec/poolMetaData.json","hash":"ca053fef4b28242ebbdec5bfe99fdcd0ce37927a281dbfd3173f09a59a7a8432"}},"pool13gsw9kvuepwhm8dfw7g2a2fwthxrwa088yq5xjaf39hqsekhqsy":{"id":"pool13gsw9kvuepwhm8dfw7g2a2fwthxrwa088yq5xjaf39hqsekhqsy","vrfVerificationKeyHash":"c1cc951ff3f672f20e31ae5bce743ebef7cf1eed6594c2842cf76d29d6d91f09","pledge":{"lovelace":1},"cost":{"lovelace":341000000},"margin":"9/10","rewardAccount":"stake_test1uqh2r3mmdwgqqzjc3fqtfgx3a02tlx6dvjs6t56aeyqnnds9xydza","owners":["2ea1c77b6b90000a588a40b4a0d1ebd4bf9b4d64a1a5d35dc90139b6","d9cabfbd20d5e0250f063fc138f1c7dc401c1a84cf418059f4b3d5fa"],"relays":[],"metadata":{"url":"https://www.where_metadata_file_is_located.com","hash":"1cc405454be71cd728d3842d30ba187d5ea3287d05056e62df4a90f87b579891"}},"pool13vuxg9gw3fftvfg56xwl5rq82nqtjhhkeacxtg0jgqlfup9qz66":{"id":"pool13vuxg9gw3fftvfg56xwl5rq82nqtjhhkeacxtg0jgqlfup9qz66","vrfVerificationKeyHash":"96fd4b5bbeedf7fb46010d970875c434fc59ceecf566d240dd88489421ae3161","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/1","rewardAccount":"stake_test1up6hq4rnpfmykas4p3f6kytpuqzn0s2p3xwcegng9ysn0egzcqrr9","owners":["757054730a764b76150c53ab1161e00537c141899d8ca268292137e5"],"relays":[{"type":"hostname","hostname":"cardano-relay.int.t-dx.com","port":3000}],"metadata":{"url":"https://adastakepool.t-dx.com/test.json","hash":"20c5dfe0fc1aa2190ec6e344523adbbce96a03edd47f0009a40dca1fe4f260cd"}},"pool1jx2uun9v45gtnlkq83xj6w4chy8rl5g78qqd026e0w89wt4vq9s":{"id":"pool1jx2uun9v45gtnlkq83xj6w4chy8rl5g78qqd026e0w89wt4vq9s","vrfVerificationKeyHash":"d9d2fae43a1c6b3efa0ee48142292e4b2a864150e8030f1fedf2115a60bd0442","pledge":{"lovelace":15000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1up4l9hjwtqjwgx3n25q76tw757lagm20f6zk3dc9wmmrjeq0c0s3k","owners":["6bf2de4e5824e41a335501ed2ddea7bfd46d4f4e8568b70576f63964"],"relays":[{"type":"hostname","hostname":"koios-preview.themorphium.io","port":6969}],"metadata":{"url":"https://bit.ly/310ytob","hash":"1f71674f2483c9cdc3c65c77a910dd432d0ae9026157584e34380fdad3a6f44b"}},"pool1jsa3rv0dqtkv2dv2rcx349yfx6rxqyvrnvdye4ps3wxyws6q95m":{"id":"pool1jsa3rv0dqtkv2dv2rcx349yfx6rxqyvrnvdye4ps3wxyws6q95m","vrfVerificationKeyHash":"4c75e85016f939ff51b56b9e676ac7b164f36bc09f68782991c000ad54ef55e5","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1upq49hkcwpayt9dfwe3sfz94t32zqypytdp4lux7fh0uhwclxwzmm","owners":["4152ded8707a4595a976630488b55c542010245b435ff0de4ddfcbbb"],"relays":[{"type":"hostname","hostname":"cardano-preview-relay-1.syn.pizza","port":30800},{"type":"hostname","hostname":"cardano-preview-relay-2.syn.pizza","port":30800},{"type":"hostname","hostname":"cardano-preview-relay-3.syn.pizza","port":30800}],"metadata":{"url":"shorturl.at/acKO0","hash":"acba1a147fbce589cf1d556097b19e441fd2506f86417db03e5cdc06395c06ab"}},"pool1j3x329u0uxh9s9vjvsad9kx37tzal8gndz6ttxumcz4nw947djw":{"id":"pool1j3x329u0uxh9s9vjvsad9kx37tzal8gndz6ttxumcz4nw947djw","vrfVerificationKeyHash":"dccaf70188440911259f798f29caec271cb561d250fcdbe56b9eb0e3a73a12f9","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1upvzzxmzr02kw529cna76e9aga4udj7x45crxx83z2zgvqgu754de","owners":["58211b621bd5675145c4fbed64bd476bc6cbc6ad303318f112848601"],"relays":[{"type":"hostname","hostname":"relay01.preview.junglestakepool.com","port":3001}],"metadata":{"url":"https://csouza.me/jp-p.json","hash":"7fdeea9ed970f2e5eb06a7a8c272c84ce2ca2f6a48ab5912b75f25346a0acbf6"}},"pool1jnakc0ghqgu0x3ayg3yyut7hmm3f46g8ssrh4hkeaqz7vtylv84":{"id":"pool1jnakc0ghqgu0x3ayg3yyut7hmm3f46g8ssrh4hkeaqz7vtylv84","vrfVerificationKeyHash":"5d6cfbf6cb00aef9009058eec7e6a2aaa4f341d8ff0862a6cc2840c308a2f8b5","pledge":{"lovelace":50000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1uzd3kkuwvul6ydz869tp8fym6602y24wqww7z5qtc2a9pnst74u6p","owners":["9b1b5b8e673fa23447d15613a49bd69ea22aae039de1500bc2ba50ce"],"relays":[],"metadata":{"url":"https://foo.bat/poolmeta.json","hash":"16ccef737d542fcc0ee71f8ed13526c7d7cd76858326cdd7ca417ab93e889bbc"}},"pool1n935yzlmu7528fx4qjf2gak0cdv2nune9cku730zg7vh707rnnd":{"id":"pool1n935yzlmu7528fx4qjf2gak0cdv2nune9cku730zg7vh707rnnd","vrfVerificationKeyHash":"829ee2ddb2984b5e23c93a8b67a7b7aa7af02da2340177ae386d54d8c7ad42ee","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/40","rewardAccount":"stake_test1uzflds3zydwqeqk28qy97zwwum7v862vm0uh4ll6uxkxrts92gtm7","owners":["93f6c222235c0c82ca38085f09cee6fcc3e94cdbf97afffae1ac61ae"],"relays":[{"type":"hostname","hostname":"pv-relays.digitalfortress.online","port":8001}],"metadata":{"url":"https://digitalfortress.online/digi3-pv.json","hash":"6588af1eb497556ea55193a3e0cc15686b95ac38695d42417ccc696063e8b21b"}},"pool1ntts25w3wvt7gjrxs58esflkge8ssel9p0l44pa3l83uqvsp5h5":{"id":"pool1ntts25w3wvt7gjrxs58esflkge8ssel9p0l44pa3l83uqvsp5h5","vrfVerificationKeyHash":"891823d960e31bb9f1fbd8c64b28771c917f46fbdc036ed29bbbef5005e780bb","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzklqrm9xmagw0t7r63mf8ce8x26yawrqcr6ux5r3x9ve5crp8sha","owners":["adf00f6536fa873d7e1ea3b49f193995a275c30607ae1a83898accd3"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/SSNF","hash":"8ed31aa584c62fe11967425b6596144ca7822128031d374fcc1a43e662c914f4"}},"pool1n5aacu3chuvxkm7p2mwcpdvnmkkkvpsje6mclnwj59c6x3wpghh":{"id":"pool1n5aacu3chuvxkm7p2mwcpdvnmkkkvpsje6mclnwj59c6x3wpghh","vrfVerificationKeyHash":"bad28ede267da0d5dc61af65cfa17285257d81ac106b74bd77f507a5b161498f","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/1","rewardAccount":"stake_test1upx0n32j5cne3p0n4pervdjy43j7222h656vgl2uksrxe6gxujj3l","owners":["4cf9c552a6279885f3a872363644ac65e52957d534c47d5cb4066ce9"],"relays":[{"type":"hostname","hostname":"cardano-relay.int.t-dx.com","port":3000}],"metadata":{"url":"https://bit.ly/3O7yle2","hash":"2ad5e7a64a28105e386ec12ad29c3bb6b8a28d07d69da93f11a0c99cc2f737e2"}},"pool1nk3uj4fdd6d42tx26y537xaejd76u6xyrn0ql8sr4r9tullk84y":{"id":"pool1nk3uj4fdd6d42tx26y537xaejd76u6xyrn0ql8sr4r9tullk84y","vrfVerificationKeyHash":"590be0c42cae1fa7e93ab166343a29c83237f297f6c10ea35e5c5e6cd2eb32fa","pledge":{"lovelace":1112000000},"cost":{"lovelace":413000000},"margin":"1/50","rewardAccount":"stake_test1ur9h9qtr739mhuypqmhfxvzux3g9h0tksew8w6ravaj3t8qacq6d9","owners":["c9dc49a676087ba0fb1ab1f28b209e647b4139626d732455bb7d5582","cb728163f44bbbf08106ee93305c34505bbd76865c77687d6765159c","f4cceaa5fff7b592e39519942ea8c3b823f3fee622bb3c81a5f5150f"],"relays":[{"type":"hostname","hostname":"us.netspectrum.com","port":13001}],"metadata":{"url":"http://us.netspectrum.com:13002/pool-meta-data.json","hash":"6e31d534b0d8bdde4ce9bd04ac8d7a6906b680304a3150400304c46f0f393af5"}},"pool1n6tcrkjjn7dr70e4vjmtayswl2rne947fue7w2htthaq6men4yp":{"id":"pool1n6tcrkjjn7dr70e4vjmtayswl2rne947fue7w2htthaq6men4yp","vrfVerificationKeyHash":"9792680b674d04b392cb637a223d327d7af568ef358080cea4d2e10790040f08","pledge":{"lovelace":14000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uq9f3jgmfywhgcmhtd0mv7m3qwp22ah08sd3x8s4ljylpxghkf2yx","owners":["0a98c91b491d7463775b5fb67b710382a576ef3c1b131e15fc89f099"],"relays":[{"type":"hostname","hostname":"preview.blockchainbill.lol","port":3003}],"metadata":{"url":"https://preview.blockchainbill.lol/SNSOB.metadata.json","hash":"4792d9a653baab097047724e97896697c4d1f04accd9e9d126f1786102f1e2d4"}},"pool15qlyejqxu99n2p3980wtwmne4ykzd9vn4mz7ldtncepnuh6rqeh":{"id":"pool15qlyejqxu99n2p3980wtwmne4ykzd9vn4mz7ldtncepnuh6rqeh","vrfVerificationKeyHash":"94ac627b9db9da8d083bd83a6e1e902788566b4db5ba691f5c7f12ef717ed1bf","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/be39feb0-5cba-4552-a044-68f.json","hash":"54920331d130d8949bff1fd6b3f01bc693de7d36de32fc9a29ea2ef60a65da71"}},"pool15zu40d05gy43gyyxy7svumkxyac9qy6shlpdrgyz5gh8g48qaaj":{"id":"pool15zu40d05gy43gyyxy7svumkxyac9qy6shlpdrgyz5gh8g48qaaj","vrfVerificationKeyHash":"3b18c66658a5d9dd1a2bd876f1e0b076451641c41017017ccc6b448bcf38c529","pledge":{"lovelace":70000000000},"cost":{"lovelace":4321000000},"margin":"1/25","rewardAccount":"stake_test1uqz0vs8vnxqpdcuey0qcvufn95gydj6x5g37wgy975wlfwgdhyuk4","owners":["04f640ec998016e39923c18671332d1046cb46a223e72085f51df4b9"],"relays":[{"type":"ipAddress","ipv4":"184.73.135.122","port":3002}],"metadata":{"url":"bit.ly/3Eh3p7A","hash":"9b9d00fcec79d306e3dffcc6865d4088f35b13c268e32c7a2fabb1845947f9c7"}},"pool15rneqfpzde87huszzstymzxu6f5u2jqelsaczr99e3z62dywau7":{"id":"pool15rneqfpzde87huszzstymzxu6f5u2jqelsaczr99e3z62dywau7","vrfVerificationKeyHash":"74838ee89acb2caf072cd50705f0dd0a958af9cb20ec70500ee3c2c2e800b316","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1urx0fs8j3lqfkjtmuzd64futqtucqkmlj32ufgza2xhhutgmx79n2","owners":["ccf4c0f28fc09b497be09baaa78b02f9805b7f9455c4a05d51af7e2d"],"relays":[{"type":"hostname","hostname":"gateway.adavault.com","port":4061}],"metadata":{"url":"https://adavault.com/advpreview.json","hash":"336a78f742447c0af780583059167eff24a4268dad3947373397f5ccfe6a883e"}},"pool1580a362kwnqt7v2lgun5t02u0r7dyl70x9nsy37zj46xkq8mp22":{"id":"pool1580a362kwnqt7v2lgun5t02u0r7dyl70x9nsy37zj46xkq8mp22","vrfVerificationKeyHash":"69f0a026835764345061abdd6d566ae509c1cdfa630999cdc57b5e43a6d6c6f7","pledge":{"lovelace":2000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1uqnxa67e6jc4dr89kdkr0e6ucvvzucd772p9vnalrr7h0xskjsgeg","owners":["266eebd9d4b1568ce5b36c37e75cc3182e61bef282564fbf18fd779a"],"relays":[{"type":"hostname","hostname":"s2.lost-in.tech","port":3001}],"metadata":{"url":"https://cardano.lost-in.tech/LIT-Pool.metadata.json","hash":"5e30e12a869cf6f5b8c8fd2d74cccd7e0825b37719a978914877b56e50e82bf9"}},"pool152x6q0ly050yr7cnatwq0087jzwyxxlkyuch6s4xex8ljaeu0ng":{"id":"pool152x6q0ly050yr7cnatwq0087jzwyxxlkyuch6s4xex8ljaeu0ng","vrfVerificationKeyHash":"c4b14fc6e1e4a632f51e245990b0d9a75096f26ad22930df52ac06ad2dc06149","pledge":{"lovelace":5000000000},"cost":{"lovelace":170000000},"margin":"1/20","rewardAccount":"stake_test1urc970azyxew8lf0s0wdw8z5pckjxcdn63v7575v4upprks6h5yys","owners":["f05f3fa221b2e3fd2f83dcd71c540e2d2361b3d459ea7a8caf0211da"],"relays":[{"type":"hostname","hostname":"testnet-relay.xstakepool.com","port":3001}],"metadata":{"url":"https://xstakepool.com/testnet-xstakepool.json","hash":"25d14c92cd852bbe666858ba040db7d5dd0767838e604e16c12b8fb842cf89ec"}},"pool15jqsjphnxg7hcx2rvd0ryhg5xwshg7xktthj3zf70nmxx9ffjet":{"id":"pool15jqsjphnxg7hcx2rvd0ryhg5xwshg7xktthj3zf70nmxx9ffjet","vrfVerificationKeyHash":"35cf12acb20ade24b4a1b09b8b033299e0551a556519b42ca47f32511e64531e","pledge":{"lovelace":9369000000},"cost":{"lovelace":369000000},"margin":"9369/10000","rewardAccount":"stake_test1uz7ne2udchys5e3kjfzpjj2f84v63csfhhpluz80kfwegpqawzmqc","owners":["bd3cab8dc5c90a663692441949493d59a8e209bdc3fe08efb25d9404"],"relays":[{"type":"hostname","hostname":"testicles.kiwipool.org","port":9720}],"metadata":{"url":"https://bit.ly/3R870ZK","hash":"19dcf5a17af5475da21aae1046a1bdae92ebac5e06e93e8c9a41b7a844fc6af8"}},"pool15j50kmtrmy3mxm0e5dej5vka9keapqtm3gv2zq96lqgjqc6sdh3":{"id":"pool15j50kmtrmy3mxm0e5dej5vka9keapqtm3gv2zq96lqgjqc6sdh3","vrfVerificationKeyHash":"e5ae4cca1fc629ef51b88e6224dddc93d9b87eabfeee18cfc90fd7b35e396dc3","pledge":{"lovelace":9000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzjqrwex060z6w0f3j87sz6cehvmw2h5hk3szz0kyth9f7sd977ss","owners":["a401bb267e9e2d39e98c8fe80b58cdd9b72af4bda30109f622ee54fa"],"relays":[],"metadata":{"url":"https://pastebin.com/raw/xDxT4v5n","hash":"da9773e26d50eea8283a80ff5b0549c28ff2ec4d64015e7532b5acc22f0c57ee"}},"pool15e04rzx0lu7hryn68l5n8n6nd9yum4rn48j64kupadc4qalulgk":{"id":"pool15e04rzx0lu7hryn68l5n8n6nd9yum4rn48j64kupadc4qalulgk","vrfVerificationKeyHash":"678c83627cbe1378f39d12b5c7bdd27a2e90358a7b80fa0cece79e39139f08b2","pledge":{"lovelace":1000000000},"cost":{"lovelace":444000000},"margin":"1/100","rewardAccount":"stake_test1up28m49ylffdnc8fwty0d5waau8udzuzv6uh0e6m0n2n5lgactsc7","owners":["547dd4a4fa52d9e0e972c8f6d1ddef0fc68b8266b977e75b7cd53a7d"],"relays":[{"type":"hostname","hostname":"ava1.sytes.net","port":6031}],"metadata":{"url":"https://avacsp.com/metadata/ava-preview-MetaData.json","hash":"c0db5e94c1dbe73a6abd0f837b8165d06709e7c02ef02ca2d7400e04ae972db5"}},"pool15ecfwjfqcc35gvpqrmut0g5hr7e0u794ywkxg5tk8rl2q4zqu9j":{"id":"pool15ecfwjfqcc35gvpqrmut0g5hr7e0u794ywkxg5tk8rl2q4zqu9j","vrfVerificationKeyHash":"c85155a3402b3d36b205b7657eb1c787f7ea9c5ed02003a39c08ebb2530453bd","pledge":{"lovelace":10000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uz5h6parv7gfk7hk3kgna07svwq5qaumrfut437965r0p4gt650jf","owners":["a97d07a367909b7af68d913ebfd0638140779b1a78bac7c5d506f0d5"],"relays":[{"type":"ipAddress","ipv4":"185.2.100.31","port":6000}],"metadata":{"url":"https://me2.do/5QGindar","hash":"13ff652f003ffde0d19c92450f89b19b056f7976f758b3e1e4f95e5ec58f10eb"}},"pool14rn9dq87dgj2z8g3lp4n0a78fewxff3gkgjkmz72ew44ym79xpp":{"id":"pool14rn9dq87dgj2z8g3lp4n0a78fewxff3gkgjkmz72ew44ym79xpp","vrfVerificationKeyHash":"3e583b72203f1659bb73653baf0e2d7850d238d4c96435eff4331060bf926801","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uz7xx6hy2xnnrmz0av0xl7qn9vdkhage7myf0nd49e7mvcg6z0smn","owners":["bc636ae451a731ec4feb1e6ff8132b1b6bf519f6c897cdb52e7db661"],"relays":[{"type":"hostname","hostname":"f7ca89d1.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://f7ca89d1.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool14fdr8cpz0qpgzkrucu2q7hst2pa3u5ssfej7kuepdq4v7lkyxg3":{"id":"pool14fdr8cpz0qpgzkrucu2q7hst2pa3u5ssfej7kuepdq4v7lkyxg3","vrfVerificationKeyHash":"896bac573601caf048566f3562e99be9c742832ad7e4527b5b1cdc330e9384c1","pledge":{"lovelace":30000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uqr9uznkqeuv6e7ez79yf8us678xus3y6ac0su9d253r0eg5l4clt","owners":["065e0a760678cd67d9178a449f90d78e6e4224d770f870ad552237e5"],"relays":[{"type":"ipAddress","ipv4":"75.119.130.108","port":6000}],"metadata":{"url":"https://hamster-stake-pool.de/preview_poolmeta.json","hash":"81813b6eb7904fb8533aa51f9aebc16f14e6ade80576078b83a8b307ace6b987"}},"pool140axp85wjr7qhwtf5y9utlht6eq42n4sl8wjh6fmlu02gel0aqg":{"id":"pool140axp85wjr7qhwtf5y9utlht6eq42n4sl8wjh6fmlu02gel0aqg","vrfVerificationKeyHash":"9b0cdfd880b67152d7b808ee37f33c0e9181ebda8ecab369b239fdbfdf3ecaad","pledge":{"lovelace":45000000000},"cost":{"lovelace":170000000},"margin":"1/1","rewardAccount":"stake_test1uzyvlggps4p4c0aejtr4qqxywwp9gg9xk6f9u49s7tzcdmqstww5s","owners":["88cfa10185435c3fb992c75000c473825420a6b6925e54b0f2c586ec"],"relays":[{"type":"hostname","hostname":"adrelay.hawak.cloud","port":6000}],"metadata":{"url":"https://tinyurl.com/hawakpool","hash":"f06c26e560a1395007149ef13dc7301348a77f43f67ce9f504f0be571cc59e6e"}},"pool14cwzrv0mtr68kp44t9fn5wplk9ku20g6rv98sxggd3azg60qukm":{"id":"pool14cwzrv0mtr68kp44t9fn5wplk9ku20g6rv98sxggd3azg60qukm","vrfVerificationKeyHash":"b8b2e69a0b590af68cbf1411aad7c93c1b48346047551461ec2a2ccf9dc182d6","pledge":{"lovelace":8000000000},"cost":{"lovelace":340000000},"margin":"1/1","rewardAccount":"stake_test17r76qtu38a29387whc40a5e6da3xqrkkf87sf78kjgggals8xt5hy","owners":["69c9b2655d27e06722905f4ae9e356a18886340964baa472f29d8586"],"relays":[{"type":"hostname","hostname":"preview-node.pool.milkomeda.com","port":3001}],"metadata":{"url":"https://is.gd/Ikn7kl","hash":"8fc709584d2f7d859a902539fc28e8c9a7f6d046b8c8d89a793aad1594fbdfc2"}},"pool14u22dyym8k2g2twvgct86njg3m9cc7j2fc74yamy6672s6up7a0":{"id":"pool14u22dyym8k2g2twvgct86njg3m9cc7j2fc74yamy6672s6up7a0","vrfVerificationKeyHash":"600f54b88675a354a87bea473ac776fb2684254d55431585904b89b71ef74620","pledge":{"lovelace":200000000000},"cost":{"lovelace":170000000},"margin":"0/1","rewardAccount":"stake_test1uzpck3ssxf3cw5mxs8umex3stuf4pk5m9qyfp57ymrkc3fg0mmtsj","owners":["838b4610326387536681f9bc9a305f1350da9b280890d3c4d8ed88a5","f999c5ee8ec8de584be7f07150c00a841c8b0be6ca6acb56c2c31c43"],"relays":[{"type":"hostname","hostname":"preview.leadstakepool.com","port":3001},{"type":"hostname","hostname":"preview.leadstakepool.com","port":3002}],"metadata":{"url":"https://raw.githubusercontent.com/lead-pool/l/master/p.json","hash":"91a080cf2aa797c24efe5b26330a634209ec152a0f079ffc0b31157a6f4a6993"}},"pool14lfkzjvlp2prlwt0ykxceemhdd4ej9rc0em4xt4cnpvt2fmtg9v":{"id":"pool14lfkzjvlp2prlwt0ykxceemhdd4ej9rc0em4xt4cnpvt2fmtg9v","vrfVerificationKeyHash":"71762169bc3dfc516e39854f78e572f24d5a7ab85d42a55c1bfd4e86e0b531a7","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"19/1000","rewardAccount":"stake_test1uperlgjrwsqv0gluun7xk670lnevmlc9v3m0zxjx76p7z3q95gj3k","owners":["723fa2437400c7a3fce4fc6b6bcffcf2cdff056476f11a46f683e144"],"relays":[{"type":"ipAddress","ipv4":"184.174.32.106","port":6002}],"metadata":{"url":"https://mladenlm.github.io/poolMetadata.json","hash":"30c5b5372462def97e466b84ff8179ab80dc4deac67b61981e9db947915c8558"}},"pool1krjtqew2jg203nvnec39vt77leqyfsc8e42u4ywx534t62h9fth":{"id":"pool1krjtqew2jg203nvnec39vt77leqyfsc8e42u4ywx534t62h9fth","vrfVerificationKeyHash":"3a238800d748179b955445d9c2488125785f1e271e8d43449e292d5a7c4b7b71","pledge":{"lovelace":1000000},"cost":{"lovelace":200000000},"margin":"1/2","rewardAccount":"stake_test1upxs40dqlfrh4gkd7djhwr5qlq225c3etv66f8m0mgsahxgk45c6j","owners":["4d0abda0fa477aa2cdf365770e80f814aa62395b35a49f6fda21db99"],"relays":[{"type":"ipAddress","ipv4":"212.24.98.109","port":5333}],"metadata":{"url":"https://adawallet.io/public_files/MDS_ST_meta_v2.json","hash":"ef3aca5a37d0bc4d81c4f85da513e3565be372e9bc3ecdf6fe5cb1a5bb55bff2"}},"pool1kfzv75la3rfgrh3uly7dt5syqxf0r2n2khr7s6ylhjmnkkdfwye":{"id":"pool1kfzv75la3rfgrh3uly7dt5syqxf0r2n2khr7s6ylhjmnkkdfwye","vrfVerificationKeyHash":"0b9f2a9f73eb7d35054626b561f9b4d4d4d5040a547c0cc2beffe50829b36c93","pledge":{"lovelace":1000000000},"cost":{"lovelace":345000000},"margin":"3/25","rewardAccount":"stake_test1urgqett9quhpsjm4cygp3uf7u63tz5gzx4czf5t965xejegd67zc0","owners":["d00cad65072e184b75c11018f13ee6a2b15102357024d165d50d9965"],"relays":[{"type":"hostname","hostname":"xsecpreview.infra.getlenses.co.uk","port":3000}],"metadata":{"url":"https://tinyurl.com/bdfmuct6","hash":"afb2956e054911e178c9d5556e560155e2f663022112bc476820348d1006eb32"}},"pool1k4rdvvuhy7h927psyew9syupwddy77t4j8lc74hpgzpvv7yklwg":{"id":"pool1k4rdvvuhy7h927psyew9syupwddy77t4j8lc74hpgzpvv7yklwg","vrfVerificationKeyHash":"ff8d88fd6b39985c9ddbef0363f87ec0ae32016c62a305e2497e4b54cb161d52","pledge":{"lovelace":6000000000},"cost":{"lovelace":340000000},"margin":"3/40","rewardAccount":"stake_test1uqw2h3092ka5mctav6d07cwumxagvcm9zs2aj9g2m4n74cgcf5r9x","owners":["1cabc5e555bb4de17d669aff61dcd9ba8663651415d9150add67eae1"],"relays":[{"type":"hostname","hostname":"preview-test.ahlnet.nu","port":2102}],"metadata":{"url":"https://ahlnet.nu/pool/preview-meta.json","hash":"8f52b4840726c157c50c1b972fadb21b2f0c852e99004a48e649319218960c55"}},"pool1kkhr6m0syfgqamr3klzhj2trjd3q4vyg8trzdjxdp64nqzshwea":{"id":"pool1kkhr6m0syfgqamr3klzhj2trjd3q4vyg8trzdjxdp64nqzshwea","vrfVerificationKeyHash":"b4ea03eb58cbfa9059e0b8478f09762f002e4cebc9aae7bf6de04b9ccebb9d94","pledge":{"lovelace":100000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uzx366cdgqv9lg69y7ufw59af3y7yh9jxflnym8z8qz3pfgmef2r8","owners":["8d1d6b0d40185fa34527b89750bd4c49e25cb2327f326ce2380510a5"],"relays":[{"type":"hostname","hostname":"preview.adanorthpool.com","port":9613}],"metadata":{"url":"https://www.adanorthpool.com/ANPPREVIEW.metadata.json","hash":"e4f9a2cf26e72b93955893bbcae4a37c27c061b04ab2a8d79856350e6dc3fb26"}},"pool1kewhspt8fsxk9kx6pw2nukcrs940dkwcwh89llj233ahghexeum":{"id":"pool1kewhspt8fsxk9kx6pw2nukcrs940dkwcwh89llj233ahghexeum","vrfVerificationKeyHash":"9d009cac22c72b8200e473c71330cc5907832880a2098c1fea0affb68df5f52f","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uptdhvz442mcem2lqd3y23nlypudpdm7d32aeyn3y72d8tcs7scmy","owners":["56dbb055aab78ced5f036245467f2078d0b77e6c55dc92712794d3af","b0348c669fe3cb7446b5084a669e304dd1cff63762352e8355e14482"],"relays":[{"type":"hostname","hostname":"605691fa.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://605691fa.cardano-metadata.stagebison.net/metadata.json","hash":"c0719d1437e1bf09915b0dbfaae2e384d737e326f17d8f1ae82d6a40111a1035"}},"pool1hykgd0kw0n6vx08j8vcyu7q0q6rqkwxr7cql03vf2at9kdmlxpy":{"id":"pool1hykgd0kw0n6vx08j8vcyu7q0q6rqkwxr7cql03vf2at9kdmlxpy","vrfVerificationKeyHash":"c636a7c8aa43ee105919d24a62f0d80bdc3981de0951672e7a316cc9a0f57b74","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uz5sce2cv9kkykjqhakrvma65xhlyzt3p7n4aamexkg0jtcf54jnu","owners":["a90c6558616d625a40bf6c366fbaa1aff209710fa75ef7793590f92f"],"relays":[{"type":"hostname","hostname":"node.armadacardano.io","port":6000},{"type":"hostname","hostname":"node2.armadacardano.io","port":6000}],"metadata":{"url":"https://armadacardano.io/metadata.json","hash":"45ce75ec2304fce3afb1a8c11316cedc5a20aea417b58ca59f6ad97ea4518112"}},"pool1h2wx7wnf079jfz6vyzs9jnjczme2nlufryyw68e2fhe2x0swk3e":{"id":"pool1h2wx7wnf079jfz6vyzs9jnjczme2nlufryyw68e2fhe2x0swk3e","vrfVerificationKeyHash":"d9a1ba9598e9613974ce89526c30d70bc9763af61b86d5e28638ecfc88e837ce","pledge":{"lovelace":45000000000},"cost":{"lovelace":340000000},"margin":"1/500","rewardAccount":"stake_test1upam5e8xunaktc2qwwq3aa6wumkya75x68ce32a0dkfh60qyxhst8","owners":["7bba64e6e4fb65e14073811ef74ee6ec4efa86d1f198abaf6d937d3c"],"relays":[{"type":"ipAddress","ipv4":"159.138.55.134","port":3001},{"type":"ipAddress","ipv4":"192.168.0.105","port":3001}],"metadata":{"url":"https://raw.githubusercontent.com/mj83263/test/main/tp2.json","hash":"5ff4cd6df6afda00a70f9480b72acaa0e2271371c2e6daf89e7c53ef6192ec90"}},"pool1htdmnme5s6d824trqq33czlm82f473w04h4xghprzaj3cff53mp":{"id":"pool1htdmnme5s6d824trqq33czlm82f473w04h4xghprzaj3cff53mp","vrfVerificationKeyHash":"98a662ae890d7c2d48b8bf5fb55602c20a04d59e499d0446586189680d039a9f","pledge":{"lovelace":8000000000},"cost":{"lovelace":340000000},"margin":"1/200","rewardAccount":"stake_test1uzsapk9c9x5frdk99wqktd6udusxhe6u0qnaryxmg4cqe9clhncf4","owners":["a1d0d8b829a891b6c52b8165b75c6f206be75c7827d190db45700c97"],"relays":[{"type":"hostname","hostname":"relaynode25t.irfada.co","port":6000},{"type":"hostname","hostname":"relaynode26t.irfada.co","port":6000}],"metadata":{"url":"https://tinyurl.com/munhhxv9","hash":"dfe61ced98cfa2fd81658686ea824910f3e6a5306c89bf1bc362f54e2000927c"}},"pool1hs2ah9q0kjy8rx7rf7qdavhmxznnesfctlu8lkqzukfdsp9kfcp":{"id":"pool1hs2ah9q0kjy8rx7rf7qdavhmxznnesfctlu8lkqzukfdsp9kfcp","vrfVerificationKeyHash":"9cd4eab04ea0073076b33c6501787d932edd031f49daa0c0fdecc4774a2ef977","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uzuahv2t7qhvgshhsnj47xhmh32n6hhpgjk5e296kwyr8lq5fvd5s","owners":["b9dbb14bf02ec442f784e55f1afbbc553d5ee144ad4ca8bab38833fc"],"relays":[{"type":"hostname","hostname":"c-pv-rn01.liv.io","port":30002},{"type":"hostname","hostname":"c-pv-rn02.liv.io","port":30002}],"metadata":{"url":"https://liv.io/poolMetaData.json","hash":"66309fa9a6726eaf1ede2bd73b1ffe02dcbc0f966730221b0cbc71702bb1742a"}},"pool1h7c2jq3pmvn3f8jht4ulhgha3h60k6syu3rw6pmkfrhqs9j7m0l":{"id":"pool1h7c2jq3pmvn3f8jht4ulhgha3h60k6syu3rw6pmkfrhqs9j7m0l","vrfVerificationKeyHash":"941c6ac6afb53de451e95ec203d6093ce6c8ef0fd58e8a78e406ac3bb668c796","pledge":{"lovelace":1000000000000},"cost":{"lovelace":340000000},"margin":"1/25","rewardAccount":"stake_test1uqkn6dhxl7mg542afm858jxudl7cwd9f0gys3qkuh3al5eq5zzhss","owners":["2d3d36e6ffb68a555d4ecf43c8dc6ffd8734a97a090882dcbc7bfa64"],"relays":[{"type":"hostname","hostname":"relay.test.lidonation.com","port":3010}],"metadata":{"url":"https://test.lidonation.com/metadata.json","hash":"edc82ecfb1cabeb15cb122bd6a65b6de6006e2201617e3c8dfdf8cc652baacfe"}},"pool1hlgaznlja8jau6wg3u4curvs7ng6yhxaxa2urp7qylxkc2e4pjk":{"id":"pool1hlgaznlja8jau6wg3u4curvs7ng6yhxaxa2urp7qylxkc2e4pjk","vrfVerificationKeyHash":"f727fdc0e656c1faea14c812b9cf7648795f5b606f6428f6e8dd68d0f729514d","pledge":{"lovelace":4000000000},"cost":{"lovelace":340000000},"margin":"3/200","rewardAccount":"stake_test1uzpp6e09x70k4wu4ccwujgwfdjwluf4nzyekkaa2l0dlgjq07ax2w","owners":["821d65e5379f6abb95c61dc921c96c9dfe26b311336b77aafbdbf448"],"relays":[{"type":"ipAddress","ipv4":"51.255.82.47","port":6000}],"metadata":{"url":"http://config.ada-staking.fr/metadatas_preview.json","hash":"86fd4e3118fe835008a699f339ec111ac35682de1d449b15255544b1570b601f"}},"pool1cyqx4ecp36gkca407ml2hf9pqauz3d3qchkpxndlnvqp60j2339":{"id":"pool1cyqx4ecp36gkca407ml2hf9pqauz3d3qchkpxndlnvqp60j2339","vrfVerificationKeyHash":"1764a62306c3f165ab2a890709c9b5c17559cfbadf77923948d3dc8fa41bcdf6","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1up0me0jesha4wvnnn5j28tdkdqpk0ufdwa8fk9wdl4q9kts8rpqh9","owners":["5fbcbe5985fb5732739d24a3adb6680367f12d774e9b15cdfd405b2e"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/SSNG","hash":"de0fcdf1da51661d27fbf97ce6e78d71a038e5582e90659eb216c19d66738cfa"}},"pool1cf88r4wgq4m2pa7phq6hevg798n0gfkteeq52vcvum8hc5czxas":{"id":"pool1cf88r4wgq4m2pa7phq6hevg798n0gfkteeq52vcvum8hc5czxas","vrfVerificationKeyHash":"fc012f1cd6346ba64f1faed6ad9676769d1cb12c46901c8b2c12f6bb71d90aed","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1up536agqy6nr5u0gpddwjlx5m2r9sevhd4nwp5su8ktg4wqlrp2vc","owners":["691d750026a63a71e80b5ae97cd4da865865976d66e0d21c3d968ab8"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/RSPO3","hash":"07945a19eb6413ce7b8523495d7670c3d2b6ce90f75a54c023845a87fdde2fb3"}},"pool1cv9fr477zeznqrk8uxa5hh72tsjukkuqtnet7wgyxx3rq700kl5":{"id":"pool1cv9fr477zeznqrk8uxa5hh72tsjukkuqtnet7wgyxx3rq700kl5","vrfVerificationKeyHash":"b1ab6692d0af93c5e61e99f4ba39a5a10352b729fe370145e35e5eb39bc53b13","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"1/50","rewardAccount":"stake_test1upv2favfz6vqs782yg9kc8sxdely9g3dqd4w4v492jw6hvcypj9hu","owners":["58a4f58916980878ea220b6c1e066e7e42a22d036aeab2a5549dabb3"],"relays":[{"type":"hostname","hostname":"previewrelay.stakepoolcentral.com","port":15654}],"metadata":{"url":"https://bi-preview.stakepoolcentral.com/CENT.preview.json","hash":"fb6a7bdf6c6827d16c33b1173cb436897cdad7a3fe399c01813797180fe97db3"}},"pool1cwsvslzd5y2rp9qt6ne6hhrwdxuweupdfy243erke3euytp7j5m":{"id":"pool1cwsvslzd5y2rp9qt6ne6hhrwdxuweupdfy243erke3euytp7j5m","vrfVerificationKeyHash":"654ed6220e9cc5fd5ceb71f1bc1b4cf34e1826eea3261ba595cc290e9469a79f","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"1/1","rewardAccount":"stake_test1urk948umhqw2z6c95r0dhdr62898urgf46y2plpzre2fe7qzntp6f","owners":["ec5a9f9bb81ca16b05a0dedbb47a51ca7e0d09ae88a0fc221e549cf8"],"relays":[{"type":"hostname","hostname":"preview.relays.liqwid.finance","port":3001}],"metadata":{"url":"https://lqwdpool.s3.amazonaws.com/metadata","hash":"9af8ffcc01e792191a220e45b1342178ccd65ac6ce721ee3c37c3614ce18c2a4"}},"pool1ceact5c2pt4ynn5nwv2rqm04krzsm4jd26r468mdqannv5crxd6":{"id":"pool1ceact5c2pt4ynn5nwv2rqm04krzsm4jd26r468mdqannv5crxd6","vrfVerificationKeyHash":"c2075042ece1ad9b41000c53598349ec2735c649f456f3836901ade5b31eca10","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uq0r8cvtjnz8y0kw4x09rv3fk8gev98gp5fg28u0zk0kaqgwxl5eq","owners":["1e33e18b94c4723ecea99e51b229b1d19614e80d12851f8f159f6e81"],"relays":[{"type":"hostname","hostname":"9caee114.cardano-relay.stagebison.net","port":1338}],"metadata":{"url":"https://9caee114.cardano-metadata.stagebison.net/metadata.json","hash":"985e4efc3b6a10c375968c1de0a138fc75bd357d3e1ffa581aafbd96a43d37a5"}},"pool1cuxthc4lyescly7lq4tgvf72td75l2hrm8zmks2qnmffkqvpsyn":{"id":"pool1cuxthc4lyescly7lq4tgvf72td75l2hrm8zmks2qnmffkqvpsyn","vrfVerificationKeyHash":"46b2dca70839f8515b2d65cb7abe6c251aef8f0221025dc30c4b63af7bf355e3","pledge":{"lovelace":50000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1upedrdplfruuaplyaet524e4x6nxus2z3hss8gnwep62eqqsq4mym","owners":["72d1b43f48f9ce87e4ee5745573536a66e41428de103a26ec874ac80"],"relays":[{"type":"hostname","hostname":"172.30.100.12","port":6000},{"type":"hostname","hostname":"172.30.100.10","port":6000}],"metadata":{"url":"https://tinyurl.com/DVJMDG","hash":"56949b92b173ecdc5852d9fe5946411f384a1ef1659a26840f4467ffd1a62fb0"}},"pool1epeq86e8vuuar86kk9hgtn6ty3yzcjun5nrm2xyysfl07fsrwc4":{"id":"pool1epeq86e8vuuar86kk9hgtn6ty3yzcjun5nrm2xyysfl07fsrwc4","vrfVerificationKeyHash":"09f8f0bcd8dba98f8d0d5cf76624610eda099fcfd813df66b43ce23a3be7e35f","pledge":{"lovelace":9000000},"cost":{"lovelace":340000000},"margin":"9/100","rewardAccount":"stake_test1uza6wgdaec5kulpd5ft2xtchcfhgry6te8az8h5r2xzp7kgxc3hvp","owners":["bba721bdce296e7c2da256a32f17c26e81934bc9fa23de8351841f59"],"relays":[{"type":"ipAddress","ipv4":"127.0.0.1","port":80}],"metadata":{"url":"https://foo.bat/poolmeta.json","hash":"47fa1c955765325622a3d1bcff79d78ce719a8823ee3169998348cf585edc469"}},"pool1ez9khv2gx82mqrnj0qenr47dy8grecm8qkkrtnn69wzzwkvc9l6":{"id":"pool1ez9khv2gx82mqrnj0qenr47dy8grecm8qkkrtnn69wzzwkvc9l6","vrfVerificationKeyHash":"30ff40541e2c155acfcdfa844069e705dee1ae8eef9bdcde22de465de6fa8fdd","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"3/20","rewardAccount":"stake_test1up3pxcv3etz7d8h5e6csly3yggnmnwrgqrvhhjsqak7828ck4ytys","owners":["62136191cac5e69ef4ceb10f92244227b9b86800d97bca00edbc751f"],"relays":[{"type":"hostname","hostname":"c-pv-rn01.liv.io","port":30002},{"type":"hostname","hostname":"c-pv-rn02.liv.io","port":30002}],"metadata":{"url":"https://liv.io/poolMetaData.json","hash":"66309fa9a6726eaf1ede2bd73b1ffe02dcbc0f966730221b0cbc71702bb1742a"}},"pool1erufgazt3scqvjvsqv7ehayfscj93llzu3e6lknh2m6d5xcfjdr":{"id":"pool1erufgazt3scqvjvsqv7ehayfscj93llzu3e6lknh2m6d5xcfjdr","vrfVerificationKeyHash":"ee04d2c090ad7cfb572b32776eb694f336b2e26048a0423de1d66241deadeac8","pledge":{"lovelace":19000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uqevz4f8d5z9pv7jx8rtlvxascwqx7v6ygrmf4kj2vta43q7kjpzk","owners":["32c155276d0450b3d231c6bfb0dd861c03799a2207b4d6d25317dac4"],"relays":[{"type":"hostname","hostname":"preview-testnet-relay.cardanistas.io","port":3001}],"metadata":{"url":"https://stakepool.page.link/cards-preview-testnet-metadata","hash":"ce0eb65620e544b8614517f495fd0bd371a6a5ee70c3ddc6b210c3dff0a3f8b3"}},"pool1erajsxw8ejry8flz6gwsd885dmx9uv6k9wd8dl5vme7cxrzv9hl":{"id":"pool1erajsxw8ejry8flz6gwsd885dmx9uv6k9wd8dl5vme7cxrzv9hl","vrfVerificationKeyHash":"b327686ee38df980c15a5c9f9eeefeb5a03f5079531805cfead05a33739d23b4","pledge":{"lovelace":5000000000},"cost":{"lovelace":340000000},"margin":"3/20","rewardAccount":"stake_test1upnsszyt4g7wtl4s729kqysjph9mpv9f8hy5tk2srxr5swqnl38cl","owners":["6708088baa3ce5feb0f28b6012120dcbb0b0a93dc945d95019874838"],"relays":[{"type":"hostname","hostname":"g5.datadyne.earth","port":3005}],"metadata":{"url":"http://datadyne.earth/cardano/dataDyneCardanoPool.json","hash":"23f3b6da129943598cc39d57de2569810e5564558f1db8ab0bb80bd85194b3c4"}},"pool1e8sfzuvrpqm9t42e4tekfeygs9pk8uwja0qewxxpeyxwg5hvvcn":{"id":"pool1e8sfzuvrpqm9t42e4tekfeygs9pk8uwja0qewxxpeyxwg5hvvcn","vrfVerificationKeyHash":"a6b8428cc8ef74f793adb8469e2a36b7ae063186f0b314f837397d71ae6bf974","pledge":{"lovelace":15000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1ur6paxqxatgnvwjedszllqn54wd0t0xu9tq7lj8qjx4py2su8z4zw","owners":["f41e9806ead1363a596c05ff8274ab9af5bcdc2ac1efc8e091aa122a"],"relays":[{"type":"hostname","hostname":"75.119.159.254","port":3001}],"metadata":{"url":"https://raw.githubusercontent.com/TurboEgon/ada/master/md.json","hash":"9e02e9270ef85cc9415878d079a9237f2d55a924438b5cbf03850d894130d7b2"}},"pool1et694n52r9scvec3n32jej0juh4za6xucaj3zy822wajkegmdh3":{"id":"pool1et694n52r9scvec3n32jej0juh4za6xucaj3zy822wajkegmdh3","vrfVerificationKeyHash":"7d96da7d962d2bf0b372f5626e34b124bd38e8996d1d8880ec902b12b3a6a47d","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1ursgmmafa26uqmacut9k9ewgxrja60gv5gxlevrgevmx28gm8c59h","owners":["e6f0fb6aa711a3ce9f89d3d85d75e9215d990586b899aa80837744ef"],"relays":[{"type":"ipAddress","ipv4":"1.1.1.1","port":11}],"metadata":{"url":"http://baidu.com/","hash":"5418650706007cbfb0f784cb6a4a274c3c00ef4345e76cb053c3046cf481e74b"}},"pool1ewxvkzqnvfzaf48092n4t2crdventhxhtmpvydxnsnj322qc47c":{"id":"pool1ewxvkzqnvfzaf48092n4t2crdventhxhtmpvydxnsnj322qc47c","vrfVerificationKeyHash":"9842080c08dfce55e9d6758b9c57c51a83003c29920cbb94a828399f2472bc64","pledge":{"lovelace":5000000000},"cost":{"lovelace":500000000},"margin":"392699/12500000","rewardAccount":"stake_test1upp6fr9evvqcprgr57vq0u9mdwxck2whdlyjhve750xl29gu5zexv","owners":["43a48cb96301808d03a79807f0bb6b8d8b29d76fc92bb33ea3cdf515"],"relays":[{"type":"hostname","hostname":"preview.canadastakes.ca","port":5002}],"metadata":{"url":"https://www.canadastakes.ca/metadata/can1-preview-metadata.json","hash":"756e0c7c2640e526c055d0fe4eb453c0c2e2c3af85138a99a8e0d74ef9c0eeb3"}},"pool1ewed82f7tdluggkj2qsrajyjakzqewj3e37p25cddurtwejl6tz":{"id":"pool1ewed82f7tdluggkj2qsrajyjakzqewj3e37p25cddurtwejl6tz","vrfVerificationKeyHash":"dca941225e309e0aa7a4ca3a2f49280fa860098a17ab231a5e9b4347a0f2d241","pledge":{"lovelace":167369000000},"cost":{"lovelace":369000000},"margin":"9369/10000","rewardAccount":"stake_test1uzn99jy8eud3f4jp7pg6natdt3mn76mn33fx5na0a9utk7q03ttkv","owners":["a652c887cf1b14d641f051a9f56d5c773f6b738c526a4fafe978bb78"],"relays":[{"type":"hostname","hostname":"testicles.kiwipool.org","port":9720}],"metadata":{"url":"https://bit.ly/3R870ZK","hash":"19dcf5a17af5475da21aae1046a1bdae92ebac5e06e93e8c9a41b7a844fc6af8"}},"pool1ekezegcepqmhwppzdj7mm5cm26uz6kzmf4l9r8s3lx4kw6y2veh":{"id":"pool1ekezegcepqmhwppzdj7mm5cm26uz6kzmf4l9r8s3lx4kw6y2veh","vrfVerificationKeyHash":"c6cdbfe1e04a602a85be83b553a44657a8dd69835d14255bc820f754b38d55b3","pledge":{"lovelace":555000000},"cost":{"lovelace":350000000},"margin":"3/20","rewardAccount":"stake_test1uqgvynv9sx5kvlpn5a2zs2y6c9hfwxzuwwlntq0s2uqdahspm9ss4","owners":["10c24d8581a9667c33a75428289ac16e97185c73bf3581f05700dede"],"relays":[{"type":"ipAddress","ipv4":"185.161.193.105","port":6012}],"metadata":{"url":"https://clio.one/metadata/clio1_testnet.json","hash":"47530ba97c12e2ac40462e9c86eeb07ea555877d2a1f9d74b6ff8471839267d8"}},"pool1eh39zxmk8z4hxndc2dx6awu6yfpufmckjnyzlpdcsfd7jf2qxtm":{"id":"pool1eh39zxmk8z4hxndc2dx6awu6yfpufmckjnyzlpdcsfd7jf2qxtm","vrfVerificationKeyHash":"04c92fa6798809d11f840b1b15bf94f4a1ca9faebc92b82453741b453c700f6c","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/50","rewardAccount":"stake_test1uzz4zhcllemvlf6n5yr5nuyxrpws3k06nrs6cn200900m8qtufxcz","owners":["85515f1ffe76cfa753a10749f086185d08d9fa98e1ac4d4f795efd9c"],"relays":[{"type":"hostname","hostname":"relay1.afica.io","port":3001}],"metadata":{"url":"https://bit.ly/preview_afica_metadata","hash":"54467a19dd5d5379e1baf0112ce5c2c478d43b53629ba2440e4ad66a50b5cfa4"}},"pool1ecc3gej4jsaskjfq6phxkcklx8l0qtvalyzeefp9shmvj86hchr":{"id":"pool1ecc3gej4jsaskjfq6phxkcklx8l0qtvalyzeefp9shmvj86hchr","vrfVerificationKeyHash":"dc0c2cf51a1033db6cdae7a856d78989ea373d41567b4bd30e850021d84b8843","pledge":{"lovelace":9000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uq6pyvmjrxem8gftst2v23adw5trzvxanhz9vv3p4ng9qkqgwyflc","owners":["3412337219b3b3a12b82d4c547ad75163130dd9dc4563221acd05058"],"relays":[{"type":"hostname","hostname":"relay1.cardano.teamplay.studio","port":6000}],"metadata":{"url":"https://tinyurl.com/2p93ec5b","hash":"6bfbe784117723dbd72811f1ac85acfe49d5ca913102320ae012f39533a97a96"}},"pool1elet8uart9cuw3lmntqhfn2f44rf52dg6v5ppzkcysxx268s43n":{"id":"pool1elet8uart9cuw3lmntqhfn2f44rf52dg6v5ppzkcysxx268s43n","vrfVerificationKeyHash":"e10abc12be25311013a194e97766854c732f0bad09ff6c8bf3554e30f1d21d02","pledge":{"lovelace":9000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1upyrg0gn898nnfeal4c8j0536d9hrdlh82cu9kd39s26mgsd90gfn","owners":["48343d13394f39a73dfd70793e91d34b71b7f73ab1c2d9b12c15ada2"],"relays":[{"type":"hostname","hostname":"1.tcp.au.ngrok.io","port":25432}],"metadata":{"url":"https://t.ly/IT5j2","hash":"d79139620ec27edc094bbf79051bb0b97e599d1826f9545718786a4f9ae4eed0"}},"pool16z5ej7zasdtuljm8r0s5k8pszdm8r7argy7aq0v4czv05kyez76":{"id":"pool16z5ej7zasdtuljm8r0s5k8pszdm8r7argy7aq0v4czv05kyez76","vrfVerificationKeyHash":"bf219f9491ead9d95d362259f14e6ac78e68f3e7b06972b631ba8ac80a82b1af","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"3/10","rewardAccount":"stake_test1up8yrvxz9vvc54jh3xhau9n4hgvp004yj2xgnxrsx665e6qvf8nhl","owners":["4e41b0c22b198a565789afde1675ba1817bea4928c89987036b54ce8"],"relays":[{"type":"hostname","hostname":"beta.stake-cardano-pool.com","port":7002}],"metadata":{"url":"https://bit.ly/prevRCADA","hash":"28b7537b13a8954f80ca50022dce103252a2d64262e62b17847482ff8b474ca0"}},"pool16y556gh885fw5nky8f8qmfwjeer7l8d2wjr8cl7f5vd8x7zgh0d":{"id":"pool16y556gh885fw5nky8f8qmfwjeer7l8d2wjr8cl7f5vd8x7zgh0d","vrfVerificationKeyHash":"968a613baf8ec8e434b663e0a1fdf1c710a7b760a67dfb15e8ede88b818236e9","pledge":{"lovelace":5000000000},"cost":{"lovelace":4321000000},"margin":"1/25","rewardAccount":"stake_test1uppyxzrrhyfh5ja2tgfm87u8h36xgr3a6d6p2ljztpfew8snugder","owners":["42430863b9137a4baa5a13b3fb87bc74640e3dd374157e425853971e"],"relays":[{"type":"ipAddress","ipv4":"123.121.123.121","port":3000}],"metadata":{"url":"https://git.io/JJWdJ","hash":"c5c38833176e2d575bd8693e206e3af2e1088e556def86cae9f6c2fc45579f36"}},"pool16dy6cwrdthfmhn85h56se7dmhp2m8vhg928lvg073r7dwkjvtpg":{"id":"pool16dy6cwrdthfmhn85h56se7dmhp2m8vhg928lvg073r7dwkjvtpg","vrfVerificationKeyHash":"a377abb415ee8e8ae9a15a2a68aa9800261c7ffc77ac9380d416703e7fed9ac8","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/b44bf76a-f93d-491d-bffe-ebf.json","hash":"e0f5672cbb37d0564f5ba3f68fad2ea15484b65ece509500b27213a597a7df03"}},"pool16sjj3ykqznw2pd2m2ug00k0fujtqsmq4amfeeewqzvk7622xetd":{"id":"pool16sjj3ykqznw2pd2m2ug00k0fujtqsmq4amfeeewqzvk7622xetd","vrfVerificationKeyHash":"0cd296f8c5f1337827cacf997a68fc4e700e79632a72ef341419464cea335f87","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1up6g3hdqewdu96xcsaszvfg2jz422aq604ukkaw8cp686xcjnchlw","owners":["7488dda0cb9bc2e8d8876026250a90aaa5741a7d796b75c7c0747d1b"],"relays":[{"type":"hostname","hostname":"preview.happystaking.io","port":3003}],"metadata":{"url":"https://happystaking.io/poolMetadataPreview.json","hash":"cafacba1d7a1e22665204fd41daf451d767e5bb684856b5f58e70511cf8ac076"}},"pool16hphjcfga9jhk5j3rsgmys83kza983utn3zv9jwhjgpe2ah4j8x":{"id":"pool16hphjcfga9jhk5j3rsgmys83kza983utn3zv9jwhjgpe2ah4j8x","vrfVerificationKeyHash":"42b2725232523538f75c49436958209eeec9b0bd081b847816996c3faf1a3ed1","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"3/20","rewardAccount":"stake_test1uzxp3ahlzepch6r7vk43cwjsmyjvp7zvqy6973nw2ejktksa5yrqu","owners":["8c18f6ff16438be87e65ab1c3a50d924c0f84c01345f466e566565da"],"relays":[{"type":"ipAddress","ipv4":"168.138.37.117","port":6000}],"metadata":{"url":"https://tinyurl.com/yc3brjd5","hash":"13538c6980dd25aef3cad66fe9534145168e94e88bdb2db73f469b7b3e2faaeb"}},"pool16e3m59evvjmxsnyu2xqf5ns4zgcdc9m4fpm29avrc5y6qdnhzs6":{"id":"pool16e3m59evvjmxsnyu2xqf5ns4zgcdc9m4fpm29avrc5y6qdnhzs6","vrfVerificationKeyHash":"d35ac02a0872f631f2eeca690a00578d2522af70ee749c75a696b458dfc74a3b","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/200","rewardAccount":"stake_test1ure4jcjcvf0np3hfen3ngfvgqymmur783tdmjw0hnrf4q8s52ymvc","owners":["f3596258625f30c6e9cce33425880137be0fc78adbb939f798d3501e"],"relays":[{"type":"hostname","hostname":"relay1.afica.io","port":3001}],"metadata":{"url":"http://metadata.afica.io/preview.json","hash":"54467a19dd5d5379e1baf0112ce5c2c478d43b53629ba2440e4ad66a50b5cfa4"}},"pool1mykwc7325c2wrur785z22wj6c0fust2ttf6pvt5rh6rtjf2pemg":{"id":"pool1mykwc7325c2wrur785z22wj6c0fust2ttf6pvt5rh6rtjf2pemg","vrfVerificationKeyHash":"fa730318b97a085aa8722dbb7a2fd59ae35942f880e01c9c8b462d81c84dc4cc","pledge":{"lovelace":9069000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1urdcnx276w4g3h8mgdusutj3wc0uhflgt99ucemgfafd2fqmjjw3u","owners":["db89995ed3aa88dcfb43790e2e51761fcba7e8594bcc67684f52d524"],"relays":[{"type":"ipAddress","ipv4":"194.60.201.143","port":6001}],"metadata":{"url":"https://cardanotech.io/sancho/poolMetaData.json","hash":"ccb6217c050e86cc6128b6c40e9daf5650daeb40225c26abade57c22d68ce7b6"}},"pool1m80zlt567eqfessn6pvll5puhl049fkce0w55nmgx84mv74mrqa":{"id":"pool1m80zlt567eqfessn6pvll5puhl049fkce0w55nmgx84mv74mrqa","vrfVerificationKeyHash":"9255fd57d5e228c2228181d99087ab6551eb7d27fc5294813a48c3f1d2327d18","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1upzkdmu99wpclw7h9v8hvdd09vwygyj77qsma0gnef2znwqpk8aff","owners":["4566ef852b838fbbd72b0f7635af2b1c44125ef021bebd13ca5429b8"],"relays":[{"type":"hostname","hostname":"5.161.205.147","port":3001}],"metadata":{"url":"https://udknow.github.io/extend.github.io/pool_MetaData.json","hash":"f7f5329cbaf15b781d1a97f0f596697065f7c453aa2baf3ac034a67c2ac6d0be"}},"pool1mfwwn7k6h4k0qnrn4q4ck0l6lunra8fyvawalt6cpjvp6a253da":{"id":"pool1mfwwn7k6h4k0qnrn4q4ck0l6lunra8fyvawalt6cpjvp6a253da","vrfVerificationKeyHash":"c3e92038b50de0e70bd3066f83c067e1726f126a6cc4c9044f3c87582194bee6","pledge":{"lovelace":1000000},"cost":{"lovelace":568800000},"margin":"1/1","rewardAccount":"stake_test1urull23za5j968nez2952k0fpdzk49raz5qvadyer7d8fxqtpzyfh","owners":["f9ffaa22ed245d1e79128b4559e90b456a947d1500ceb4991f9a7498"],"relays":[{"type":"ipAddress","ipv4":"142.132.218.54","port":6001}],"metadata":{"url":"https://www.roastfrog.com/testpoolMetadata.json","hash":"f03b6faa03747b3657b1e5dd6c2f400421a609529654dbd1c1cfe6a774c5bd19"}},"pool1mfc42za8tj74zc66ez3slwtq4mumdl7yrylaxajd5xugujmhd0c":{"id":"pool1mfc42za8tj74zc66ez3slwtq4mumdl7yrylaxajd5xugujmhd0c","vrfVerificationKeyHash":"5261e39dc3a6a2c1107bded7a5cce9f9e5ba273d92b3832d028c24a23b83db48","pledge":{"lovelace":123000000},"cost":{"lovelace":171000000},"margin":"27/625","rewardAccount":"stake_test1uzckcmv9m39sx0jdvjn5snd8pkhtzwjed50tr9ayjcjdvfctmyegm","owners":["b16c6d85dc4b033e4d64a7484da70daeb13a596d1eb197a49624d627"],"relays":[{"type":"ipAddress","ipv4":"95.216.173.194","port":16000}],"metadata":{"url":"https://raw.githubusercontent.com/hodlonaut/a/master/t1.json","hash":"81986b8f246cb39979af55fc01215f193df2dc07107989b886e131633e880e43"}},"pool1m3d2flwq8kt6ys0e973xwawd042dnn6vfu82p8efyqsvu4wttaq":{"id":"pool1m3d2flwq8kt6ys0e973xwawd042dnn6vfu82p8efyqsvu4wttaq","vrfVerificationKeyHash":"e40dfd70145e63f2eb76398181f9e2f9b9f24aff6800228aa7ff1beef2a3c30c","pledge":{"lovelace":100000000},"cost":{"lovelace":345000000},"margin":"3/20","rewardAccount":"stake_test1ups3a2wv5lnrwusv06zxqrjpga4gwzuuw86y8vh23t9uhgsxarnft","owners":["611ea9cca7e637720c7e84600e41476a870b9c71f443b2ea8acbcba2"],"relays":[{"type":"hostname","hostname":"ada01.liv.io","port":30002}],"metadata":{"url":"liv.io/poolMetaData.json","hash":"78409be753a669ae5eb8c81ee7f3f1a48e8a265ebc6814e6247af4440d50b515"}},"pool1mndner6ppa2ww3zuahk8zg7tv4m235qtrt8tfne4jfl9k7kt8fd":{"id":"pool1mndner6ppa2ww3zuahk8zg7tv4m235qtrt8tfne4jfl9k7kt8fd","vrfVerificationKeyHash":"1077d0e618747203a2c133c9c758f9201a6666c8b342571650b441ed79a8b435","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzdz78y403tg3vr4qs5yz24yxdn5mg5knl09wnyta8sn6ds6xq8dv","owners":["9a2f1c957c5688b0750428412aa433674da2969fde574c8be9e13d36"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/LXSP2","hash":"8c3c4274796876b709eb9fc24b0ed08cdefd0574a011626c307ec83789dd0f61"}},"pool1m4n62kp59efunmu49qfyu38y8g6t9t3mgv4229z0lmpy6fxzdsv":{"id":"pool1m4n62kp59efunmu49qfyu38y8g6t9t3mgv4229z0lmpy6fxzdsv","vrfVerificationKeyHash":"78042dd9de14cb768582a928c234c4bda3c58ce993a2fb67e575eb5035a15335","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzmundjjeta9g6lkszul9zqvnnhnfjgqqkra5a6sfykljfq89ydly","owners":["b7c9b652cafa546bf680b9f2880c9cef34c9000587da7750492df924"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/SSNB","hash":"c15f332d03f1660ac02c025bd89bbb03b313d11f3c8e8a3c3f331709e422e56d"}},"pool1ufzepz9ugl5f72d3d4lk29x43uxexmae79dxj766s6pgu9axvav":{"id":"pool1ufzepz9ugl5f72d3d4lk29x43uxexmae79dxj766s6pgu9axvav","vrfVerificationKeyHash":"8eeabd1fa1f3b29dd9939e75e8ca450f88d77ec6be1f1a038515b0f0460e5312","pledge":{"lovelace":4567},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1upznunn78q5v6myxfmmgfe6czuhszmnwwpvszr2w8sf4aggtdp3ck","owners":["3b957bf2d0a2299394ce7dd21dd42ff0cb2ee8d517b0b2d297e31828","453e4e7e3828cd6c864ef684e758172f016e6e7059010d4e3c135ea1","5fe8542e18bde2f7469871e89b39839db8b782df86cf68b036450b73"],"relays":[],"metadata":{"url":"https://www.updated_location.com","hash":"997efa7ae731f7d203d790985f7ddf6ce37fe07944e2633e9acc386dae553dbe"}},"pool1u2pl6kx4yc77lnyapnveykkpnj07fmc7pd66fa40fvx3khw7cua":{"id":"pool1u2pl6kx4yc77lnyapnveykkpnj07fmc7pd66fa40fvx3khw7cua","vrfVerificationKeyHash":"b015beeb402d42c1607f69634ed3e53962354246f15e64073697aa03c704955b","pledge":{"lovelace":1000000000000},"cost":{"lovelace":500000000},"margin":"1/1","rewardAccount":"stake_test1urfjhemxd66mhxds7g6w07gsfy6dx2fheh6jv7zyd88l54qxghsqh","owners":["9b4052824b5cd89bb9c74ebe9405fbabf76003c5753e35d3bcc86531"],"relays":[{"type":"hostname","hostname":"preview-node.play.dev.cardano.org","port":3001}]},"pool1uk72vv6l3c4l83hw22crx9ytug7ud97grqg8am5p0qv45aa4ymr":{"id":"pool1uk72vv6l3c4l83hw22crx9ytug7ud97grqg8am5p0qv45aa4ymr","vrfVerificationKeyHash":"9003483796788e265a27728db0f83eb9bd41739f821924e286629999e10a88e5","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1urmdhhr5qhr5rgrsnw7wa2kernuahyemrr4pqta3lke6jxguxf7n4","owners":["f6dbdc7405c741a0709bbceeaad91cf9db933b18ea102fb1fdb3a919"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/RSPO4","hash":"611a69c0d90dbff124db9e3f5b21c846958e340fee72ed00bceb6e5e1f429a66"}},"pool1uh5xdjv70q5eyl5z644p23mvhd3dx0gwr8pjnlj9pwd3jgkvd0e":{"id":"pool1uh5xdjv70q5eyl5z644p23mvhd3dx0gwr8pjnlj9pwd3jgkvd0e","vrfVerificationKeyHash":"335399acf3228243efb0fec0e43f18d61a496d4fd740fd800f9b91b5fa7d0540","pledge":{"lovelace":100000000},"cost":{"lovelace":345000000},"margin":"3/4","rewardAccount":"stake_test1upv6ppwktpx45y3x4msy20fpm0fyyt4g6d9xh4ntlf9tykqyulqzd","owners":["59a085d6584d5a1226aee0453d21dbd2422ea8d34a6bd66bfa4ab258"],"relays":[{"type":"hostname","hostname":"lion474.duckdns.org","port":6000}],"metadata":{"url":"https://tinyurl.com/pkmer3hs","hash":"00ab354051a92cecb843d473c1bce7057e8d922c2f790da4326d1e4daff323e2"}},"pool1uh5sc3v77el8egy6rgz59mdgv0097j7nx3usrrkagvmsy6074k0":{"id":"pool1uh5sc3v77el8egy6rgz59mdgv0097j7nx3usrrkagvmsy6074k0","vrfVerificationKeyHash":"ae3c85580444e5a30cfad07b6a70e004c1875faf87851a06ce756e5ed42ee8f4","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1uzds77htp7kk5txdk5e2zntrejgmv5gum445n26ygawv40ghak4zs","owners":["9b0f7aeb0fad6a2ccdb532a14d63cc91b6511cdd6b49ab44475ccabd"],"relays":[{"type":"hostname","hostname":"sp.altzpool.com","port":5001}],"metadata":{"url":"https://altzpool.com/WALTZ/poolmeta.json","hash":"5c8ab40789c4fdc8aeb4684deda3c85aa0202078e0f2d575977f76351da9e771"}},"pool1ayc7a29ray6yv4hn7ge72hpjafg9vvpmtscnq9v8r0zh7azas9c":{"id":"pool1ayc7a29ray6yv4hn7ge72hpjafg9vvpmtscnq9v8r0zh7azas9c","vrfVerificationKeyHash":"4888af16310dc9dd2600001ae7d5fc571cd15d38ffb47c802aac599f916207e0","pledge":{"lovelace":125000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1uzs5rxys8qy5jnr9g0mkj860ms5n92nrykmrgyumpf2ytmsejj4m6","owners":["a14198903809494c6543f7691f4fdc2932aa6325b634139b0a5445ee"],"relays":[{"type":"ipAddress","ipv4":"207.180.211.199","port":6007}],"metadata":{"url":"https://git.io/JW7b5","hash":"7296d38d3c67d769c38924679e132e7d9098e70891d7574cc5cf053574305629"}},"pool1agzq8htqr80dr0wu6ppvm4azkrmhelg4jy4x4qes9n5cuau7esc":{"id":"pool1agzq8htqr80dr0wu6ppvm4azkrmhelg4jy4x4qes9n5cuau7esc","vrfVerificationKeyHash":"fb27957133f79e8e308e0bb47f26a3b8c9c6ada920a4b1121410d55ad4f2f90a","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1urdj5j3jtsj9lsf6xdz27dzxfw92ezj34v5d0qhcrx4ztysksexxe","owners":["db2a4a325c245fc13a3344af34464b8aac8a51ab28d782f819aa2592"],"relays":[{"type":"hostname","hostname":"topo-test.topopool.com","port":3010}],"metadata":{"url":"https://cardanostakehouse.com/187d7406-a87e-449e-8849-9a8.json","hash":"68d0f12660b653892627f2c26c5206dd7cec9fe5c28680f30130aee36188cefd"}},"pool1ag29qua3amyl7fszngeqxnrxpamu6rychrxjjuju5e0tskdpwka":{"id":"pool1ag29qua3amyl7fszngeqxnrxpamu6rychrxjjuju5e0tskdpwka","vrfVerificationKeyHash":"a06673f1adeb90f1c228becf0d7467f750aa2ff22380297b92cba4af98c1f2ac","pledge":{"lovelace":10000000000},"cost":{"lovelace":340000000},"margin":"1/100","rewardAccount":"stake_test1upglkzseasr52vrwa8lyuare8vrlsgj7gd7u7qcapfr4rtcxzny4g","owners":["51fb0a19ec0745306ee9fe4e74793b07f8225e437dcf031d0a4751af"],"relays":[{"type":"ipAddress","ipv4":"144.126.157.40","port":3005}],"metadata":{"url":"https://onecommunityada.com/public/poolmeta-preview-v01.json","hash":"13789ef22250148bba4158df16011318b63a18110d64f2b449bb10df5648f2d6"}},"pool1ad2pw6ch9rpktqt4yfr5qlgt4z87g4v2lky067khwfe9khq246w":{"id":"pool1ad2pw6ch9rpktqt4yfr5qlgt4z87g4v2lky067khwfe9khq246w","vrfVerificationKeyHash":"6c3788da12fce689f7e7d6f50814ad1b21a2ec41f2689bd12770b72958d62689","pledge":{"lovelace":2000000000},"cost":{"lovelace":340000000},"margin":"1/50","rewardAccount":"stake_test1uqyjm25xx2jv62fydccgx036ahs7c5fvwl9a2vpempeemgcj594y7","owners":["092daa8632a4cd29246e30833e3aede1ec512c77cbd53039d8739da3"],"relays":[{"type":"ipAddress","ipv4":"159.203.25.174","port":6000}],"metadata":{"url":"https://tinyurl.com/uakazrpv","hash":"afdf5aa90ad33073ed75f0a72bc72b952e774deac00e7f4cb1020bfb7c6e91ef"}},"pool1aw4ylpwdt6dll08jzkqtpa00rvxpqj8k04g6kdyumwk9cyrqpk8":{"id":"pool1aw4ylpwdt6dll08jzkqtpa00rvxpqj8k04g6kdyumwk9cyrqpk8","vrfVerificationKeyHash":"168dc3fcbe016160b0bb58e60880b2cc422d63937a944e9522bd3c1847f429f0","pledge":{"lovelace":10000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1uz2equk92h9kfjj3v80ls23t4hx4r4n3mwr8tcddgpc9ldcn3cvfz","owners":["959072c555cb64ca5161dff82a2badcd51d671db8675e1ad40705fb7"],"relays":[{"type":"ipAddress","ipv4":"190.225.246.140","port":6000}],"metadata":{"url":"https://t.ly/W1Nni","hash":"167d5e2610687507e54ed74f89c5705a09375e89199ed5c8fbd980a26ad84a7d"}},"pool1a3pepkeacs59d3lqfmk6hks4qc7k84xqsc4q664lpxfvyq9lf5f":{"id":"pool1a3pepkeacs59d3lqfmk6hks4qc7k84xqsc4q664lpxfvyq9lf5f","vrfVerificationKeyHash":"1786535ea1a4e6ee4addea9ea255643515698bfe927b7a631402a274172685ae","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uqxcefkp07zelmy36y3jdpzajxz2w053h027sknlk4fkklqe96s62","owners":["0d8ca6c17f859fec91d12326845d9184a73e91bbd5e85a7fb5536b7c"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/LXSP4","hash":"2d9ef4dab347f7151dbdb884f61dbeb1d1322655d0835a002cba7072dc2baa41"}},"pool1a6ug5gelydu29djkuvxl869257e7v4d3zwqwt69ygu7dcfts59j":{"id":"pool1a6ug5gelydu29djkuvxl869257e7v4d3zwqwt69ygu7dcfts59j","vrfVerificationKeyHash":"1c3ba4a44d07d779d3b699936ead18a3dd9b20eeaa25281df144c404b611f864","pledge":{"lovelace":1000000000},"cost":{"lovelace":170000000},"margin":"1/100","rewardAccount":"stake_test1uqrw4g3al234sqskw87z6t45k42z2t9qyp9jyeec83wm0csq2u08c","owners":["06eaa23dfaa358021671fc2d2eb4b554252ca0204b2267383c5db7e2"],"relays":[{"type":"hostname","hostname":"testnet.valhallapool.net","port":3000}],"metadata":{"url":"https://raw.githubusercontent.com/t0m3kf/v/main/testnet.json","hash":"1d707d6861b2fdb6b46321270e40ea01ff9a49acc3858b5499b5f33fa4f3bebf"}},"pool1a7h89sr6ymj9g2a9tm6e6dddghl64tp39pj78f6cah5ewgd4px0":{"id":"pool1a7h89sr6ymj9g2a9tm6e6dddghl64tp39pj78f6cah5ewgd4px0","vrfVerificationKeyHash":"1d8199fd0a82c29b242d62f6aca7d166200e47c0596fab5b1d4cf56399b6eded","pledge":{"lovelace":100000000000},"cost":{"lovelace":340000000},"margin":"1/10","rewardAccount":"stake_test1uqd2nz8ugrn6kwkflvmt9he8dr966dszfmm5lt66qdmn28qt4wff9","owners":["1aa988fc40e7ab3ac9fb36b2df2768cbad36024ef74faf5a0377351c"],"relays":[{"type":"hostname","hostname":"prv-relay1.apexpool.info","port":3001}],"metadata":{"url":"https://apexpool.info/preview/poolmetadata.json","hash":"a207f23a6255eeb0b508945e5170b169eb5c3220109d7fa17a7d88d462c8a199"}},"pool1alaz72lzlude9flwewegv530za5pl0uuakxa02kdyddv67wpkwj":{"id":"pool1alaz72lzlude9flwewegv530za5pl0uuakxa02kdyddv67wpkwj","vrfVerificationKeyHash":"d2c415e4eb5c7295a10d17b1eecc7791f6217f0dfcf298e83eba53f44a792362","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"19/1000","rewardAccount":"stake_test1ur2pejlgfqa5e4stqg529tqj06k6gamweaawgphvewkdgtqqkuwlr","owners":["d41ccbe8483b4cd60b0228a2ac127eada4776ecf7ae406eccbacd42c"],"relays":[{"type":"ipAddress","ipv4":"194.163.158.69","port":6002}],"metadata":{"url":"https://solidsnakedev.github.io/poolMetadata.json","hash":"66e626854b9d86d419cba818f04e4958247cb7d613d55959cb8df924bdb99c03"}},"pool17wdfwsyksx7femcxzx7ycf84maqvdf3fmr7z92h2xguy7eanvdf":{"id":"pool17wdfwsyksx7femcxzx7ycf84maqvdf3fmr7z92h2xguy7eanvdf","vrfVerificationKeyHash":"b5ad4eb8d4d7d07c993670d34e475a0ebd3553b297eaec49f297645365f3319e","pledge":{"lovelace":19000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uzu4m5xsmd0lw2y7n3rrh70feevp5sghqk9nmkr30f0yyjcx0eu53","owners":["b95dd0d0db5ff7289e9c463bf9e9ce581a4117058b3dd8717a5e424b"],"relays":[{"type":"hostname","hostname":"preview-testnet-relay.junostakepool.com","port":4521},{"type":"hostname","hostname":"passive-preview-testnet-relay.junostakepool.com","port":4531}],"metadata":{"url":"https://junostakepool.com/juno-testnet.metadata.json","hash":"3a0d397aa9bf08753197678d93ee2f615daa4727671497bfd69fabd84c63d907"}},"pool17njlrn0jgdw626utskz0zmrnduz9ra8d3al6aw5hvszxkx88q2r":{"id":"pool17njlrn0jgdw626utskz0zmrnduz9ra8d3al6aw5hvszxkx88q2r","vrfVerificationKeyHash":"392d334b0670323093e6cf60edf36961e4005de35b2c86f01e41ce2f7428837a","pledge":{"lovelace":1000000000},"cost":{"lovelace":340000000},"margin":"1/1","rewardAccount":"stake_test1urmklja3h07ndxxrg6eu950x9glzws3gcu7wpphz2cdgujql0rxpn","owners":["10d1fd3cc499c8651bc9344fabe05739fa3e5777145eb638d39dc449"],"relays":[{"type":"ipAddress","ipv4":"210.54.38.228","port":4020}],"metadata":{"url":"https://bit.ly/3vlDN4w","hash":"ff6cdb1fba6074de46d95e0f878d9683d2ce2cf3acb57e6a4fdb9d97af8fe739"}},"pool17navl486tuwjg4t95vwtlqslx9225x5lguwuy6ahc58x5dnm9ma":{"id":"pool17navl486tuwjg4t95vwtlqslx9225x5lguwuy6ahc58x5dnm9ma","vrfVerificationKeyHash":"f4c30ed620cf34f18f8a03e87a178fa01dcd21f07aeaab8c69bd1ad168177b1a","pledge":{"lovelace":100000000},"cost":{"lovelace":340000000},"margin":"1/40","rewardAccount":"stake_test1urwheaxgd4llq93s85tlnazqtzqpgrxy3nagtagl97xswug363ct0","owners":["dd7cf4c86d7ff016303d17f9f4405880140cc48cfa85f51f2f8d0771"],"relays":[{"type":"hostname","hostname":"pv-relays.digitalfortress.online","port":8001}],"metadata":{"url":"https://digitalfortress.online/digi2-pv.json","hash":"9b7e689634956d37e264f89a9ff1dc9cc38f3f4feb2984193ba55b75fbbe4edc"}},"pool175vq9hqwm9c39uk085xefkr6frtejxcqsf6gh9kh2jaavttrv2p":{"id":"pool175vq9hqwm9c39uk085xefkr6frtejxcqsf6gh9kh2jaavttrv2p","vrfVerificationKeyHash":"54b1898f88cf3e41f0b2d961132a6d35aee6e6c1cd06b10676d07eaaddb739f2","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1uqy849fm6tqp8vvn69tmvtgnc26kkre9xhu236kxf2mpgcg4lusqv","owners":["087a953bd2c013b193d157b62d13c2b56b0f2535f8a8eac64ab61461"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/RSPO6","hash":"7fd82335e38dff9fcf4d7cbc685bc81120b34a8138a5f63ac49bbe34e52f5adf"}},"pool1lqj075ak5u2j9wul3kccll7jg6we27jkeuqwpjctmj9qstcxz2l":{"id":"pool1lqj075ak5u2j9wul3kccll7jg6we27jkeuqwpjctmj9qstcxz2l","vrfVerificationKeyHash":"51e8282e2675e4b384ca03ee2b001d3d430349a80b8c5147215f77a5739a66ba","pledge":{"lovelace":500000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1urvkry4v3ncrhzjhmwg0uluerrr0rx43eh3pafq75ufucpcherj5s","owners":["d96192ac8cf03b8a57db90fe7f9918c6f19ab1cde21ea41ea713cc07"],"relays":[{"type":"ipAddress","ipv4":"0.0.0.0","port":3533}],"metadata":{"url":"https://example.com/SSNC","hash":"ccd9b7349e6a97c5f670f93225c9596bff725a63f7f4f1a42f5ea1367c639a80"}},"pool1l9u9ss9xtww8qkt4zqda84z945f6tgq4753jqhtdr4r8yaw7d6g":{"id":"pool1l9u9ss9xtww8qkt4zqda84z945f6tgq4753jqhtdr4r8yaw7d6g","vrfVerificationKeyHash":"d510044198082bb3852d56c29d0901dfc7f2fe7cc9958fffdb2c0a10ca378495","pledge":{"lovelace":0},"cost":{"lovelace":340000000},"margin":"1/1","rewardAccount":"stake_test1up3pv0r49hevqvc23q7zfwnza6d0vs3qhf4w9lhg9w93c7qegmfv6","owners":["62163c752df2c0330a883c24ba62ee9af64220ba6ae2fee82b8b1c78"],"relays":[{"type":"ipAddress","ipv4":"18.219.254.123","port":3001}],"metadata":{"url":"https://tinyurl.com/ye2zvyf4","hash":"60586988c5245b4eb59aff8110da9ebe57d4c7e37aaf6e6a3587523aa14fdee1"}},"pool1l8k45jgjd58jcg84pclvhzwqt2ql9xk65xc5svggdkslswwlh37":{"id":"pool1l8k45jgjd58jcg84pclvhzwqt2ql9xk65xc5svggdkslswwlh37","vrfVerificationKeyHash":"28c7be4bfae439c34bbd00ee1f38fbdd6da7699348e1a2d8cc8f5a5f37ec0e0e","pledge":{"lovelace":20000000000},"cost":{"lovelace":340000000},"margin":"0/1","rewardAccount":"stake_test1upzyxqc689puxvznynchysv368j4jwjvghzszqsx4fsnsasec99jl","owners":["4443031a3943c3305324f1724191d1e5593a4c45c5010206aa613876"],"relays":[],"metadata":{"url":"http://bit.ly/rabbitholepools","hash":"618d89696eea579b5e4402f220109785e9039181d5a46fc7fff45e035a8cab61"}},"pool1l5u4zh84na80xr56d342d32rsdw62qycwaw97hy9wwsc6axdwla":{"id":"pool1l5u4zh84na80xr56d342d32rsdw62qycwaw97hy9wwsc6axdwla","vrfVerificationKeyHash":"39cf4275b0751ee453aee1737c97466543250ec50932dfa0a109a99c9678752b","pledge":{"lovelace":127813888409},"cost":{"lovelace":340000000},"margin":"1/20","rewardAccount":"stake_test1uzwfmyp6jjyupe3pf3h80k5j0p3pzxzn0gf5544p7qzmhmsat2s3z","owners":["9c9d903a9489c0e6214c6e77da9278621118537a134a56a1f005bbee"],"relays":[{"type":"hostname","hostname":"preview.euskalstakepool.win","port":6001}],"metadata":{"url":"https://git.io/JiZgb","hash":"2e421355eb7b4499dd8f0bca206178131f4c9ad90e2bf369ae78aa0c7c4d9472"}},"pool1leml52hm4fcp3hhe4zye08qz27llhj7d339p3gs0tl85cstx59q":{"id":"pool1leml52hm4fcp3hhe4zye08qz27llhj7d339p3gs0tl85cstx59q","vrfVerificationKeyHash":"9bce3347843eea739fe6978c347f08dd6de43443f1964369c42778b874c42783","pledge":{"lovelace":65000000000},"cost":{"lovelace":340000000},"margin":"3/100","rewardAccount":"stake_test1urpj2lxml8ml6dqv58l3f7skw4389e0vq7s22sl8zgekmmcy97awy","owners":["c3257cdbf9f7fd340ca1ff14fa16756272e5ec07a0a543e712336def"],"relays":[{"type":"hostname","hostname":"previewrelay1.intertreecryptoconsultants.com","port":6000}],"metadata":{"url":"https://tinyurl.com/intrtpreview","hash":"b9e21ae6844cd61c812c3d5aec7dbe6f8099962fe1e952d51f297258ba89879f"}},"pool1lleyxf5xxaxg633c2thh5ttjrf4qxrm3cqaw53kmp7e5q2nlg38":{"id":"pool1lleyxf5xxaxg633c2thh5ttjrf4qxrm3cqaw53kmp7e5q2nlg38","vrfVerificationKeyHash":"3256df2b38272c09c93044fa2702d5ffb1f38c5a2145dc3cb94d5800b28accce","pledge":{"lovelace":100000000000},"cost":{"lovelace":340000000},"margin":"3/10","rewardAccount":"stake_test1uzdgxac7lcan0v7qr4tre4v8aeurwtgk3cszpthf3fra68gc7wnk2","owners":["9a83771efe3b37b3c01d563cd587ee78372d168e2020aee98a47dd1d"],"relays":[{"type":"ipAddress","ipv4":"73.222.0.99","port":3001}],"metadata":{"url":"https://tinyurl.com/6br33xwj","hash":"12b539568a42859dd8a2fe2e9c9ab3095ca4f8dedbb8899f9943ecd54dc16047"}}},"method":"queryLedgerState/stakePools","jsonrpc":"2.0","id":"queryLedgerState/stakePools-3rvj1ml27d5loixowwa","error":null} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryNetwork-startTime-02fa6f9e7ed04ebfe3294c7648be54d5.json b/fixtures/test/ogmios/queryNetwork-startTime-02fa6f9e7ed04ebfe3294c7648be54d5.json deleted file mode 100644 index a708564866..0000000000 --- a/fixtures/test/ogmios/queryNetwork-startTime-02fa6f9e7ed04ebfe3294c7648be54d5.json +++ /dev/null @@ -1 +0,0 @@ -{"result":"2022-10-25T00:00:00Z","method":"queryNetwork/startTime","jsonrpc":"2.0","id":"queryNetwork/startTime-3rvj1ml27d5loixoww6","error":null} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryNetwork-startTime-1a911197c5149cd582be4cbf5a651817.json b/fixtures/test/ogmios/queryNetwork-startTime-1a911197c5149cd582be4cbf5a651817.json new file mode 100644 index 0000000000..5273a4280a --- /dev/null +++ b/fixtures/test/ogmios/queryNetwork-startTime-1a911197c5149cd582be4cbf5a651817.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryNetwork/startTime","result":"2022-10-25T00:00:00Z","id":"queryNetwork/startTime-hfkg1vgolxm0w653"} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryNetwork-startTime-5185237542c7c8a6810aeb0fe74b3b40.json b/fixtures/test/ogmios/queryNetwork-startTime-5185237542c7c8a6810aeb0fe74b3b40.json new file mode 100644 index 0000000000..c0dbb56e69 --- /dev/null +++ b/fixtures/test/ogmios/queryNetwork-startTime-5185237542c7c8a6810aeb0fe74b3b40.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryNetwork/startTime","result":"2022-10-25T00:00:00Z","id":"queryNetwork/startTime-hfkgnvkflxdivdsi"} diff --git a/fixtures/test/ogmios/queryNetwork-tip-0175559aa0cbb9d1a23217a7152cc76f.json b/fixtures/test/ogmios/queryNetwork-tip-0175559aa0cbb9d1a23217a7152cc76f.json new file mode 100644 index 0000000000..bcf53b0c3a --- /dev/null +++ b/fixtures/test/ogmios/queryNetwork-tip-0175559aa0cbb9d1a23217a7152cc76f.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryNetwork/tip","result":{"slot":31932656,"id":"4088d6aad9edebce1047e09259981a52ebdec26904d632090f643811cd137556"},"id":"queryNetwork/tip-hfkgvfollxkiih0l"} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryNetwork-tip-145d4ffd82a9c88c79bdb0f629aa3d3d.json b/fixtures/test/ogmios/queryNetwork-tip-145d4ffd82a9c88c79bdb0f629aa3d3d.json new file mode 100644 index 0000000000..60b4269703 --- /dev/null +++ b/fixtures/test/ogmios/queryNetwork-tip-145d4ffd82a9c88c79bdb0f629aa3d3d.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","method":"queryNetwork/tip","result":{"slot":10577883,"id":"fdfe97a8576b33f2472d793059f2f4d46b26ae3549d54becdaf28bb1dadf3fb9"},"id":"queryNetwork/tip-hfkg8z8vlxlxx1j9"} \ No newline at end of file diff --git a/fixtures/test/ogmios/queryNetwork-tip-fbd01538064b3ef7b5e3a703dddcb32b.json b/fixtures/test/ogmios/queryNetwork-tip-fbd01538064b3ef7b5e3a703dddcb32b.json deleted file mode 100644 index 9bf66db46f..0000000000 --- a/fixtures/test/ogmios/queryNetwork-tip-fbd01538064b3ef7b5e3a703dddcb32b.json +++ /dev/null @@ -1 +0,0 @@ -{"result":{"slot":32379177,"id":"5f88efad29d47924ac3c275ad44ec1e1163d04c9e6d98927b1389ae87325a418"},"method":"queryNetwork/tip","jsonrpc":"2.0","id":"queryNetwork/tip-3rvj1ml27d5loixoww4","error":null} \ No newline at end of file diff --git a/flake.lock b/flake.lock index 3a8562dcd5..d6f263050f 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1702742788, - "narHash": "sha256-lSU0M27LC0d60cJ2C2Kdo6gBwTCCYRiALbD528CoTtc=", + "lastModified": 1721915212, + "narHash": "sha256-itkbLG6DUX/L5XuoSXFPgPBf+9lFOM3ufc1T4BU4MYM=", "owner": "input-output-hk", "repo": "cardano-haskell-packages", - "rev": "4a236a8ad9e3c6d20235de27eacbe3d4de72479c", + "rev": "2126fa53c45842719ee38040f4d5bee8fb17a09d", "type": "github" }, "original": { @@ -18,6 +18,23 @@ } }, "CHaP_2": { + "flake": false, + "locked": { + "lastModified": 1702906471, + "narHash": "sha256-br+hVo3R6nfmiSEPXcLKhIX4Kg5gcK2PjzjmvQsuUp8=", + "owner": "IntersectMBO", + "repo": "cardano-haskell-packages", + "rev": "48a359ac3f1d437ebaa91126b20e15a65201f004", + "type": "github" + }, + "original": { + "owner": "IntersectMBO", + "ref": "repo", + "repo": "cardano-haskell-packages", + "type": "github" + } + }, + "CHaP_3": { "flake": false, "locked": { "lastModified": 1686070892, @@ -34,14 +51,14 @@ "type": "github" } }, - "CHaP_3": { + "CHaP_4": { "flake": false, "locked": { - "lastModified": 1695160702, - "narHash": "sha256-+Mfc6eGA1ZwQ/ZjKzMoMWkHzd+sgR1JbxY0i849HjEU=", + "lastModified": 1702593630, + "narHash": "sha256-IWu27+sfPtazjIZiWLUm8G4BKvjXmIL+/1XT/ETnfhg=", "owner": "input-output-hk", "repo": "cardano-haskell-packages", - "rev": "9932690af3713ef034c928850252eb1b88450ee6", + "rev": "9783a177efcea5beb8808aab7513098bdab185ba", "type": "github" }, "original": { @@ -51,18 +68,18 @@ "type": "github" } }, - "CHaP_4": { + "CHaP_5": { "flake": false, "locked": { - "lastModified": 1694601145, - "narHash": "sha256-p7ZxorrOvoow6N+JKvfrCiRYFtUSPiEMgt8MR+rcTT4=", - "owner": "input-output-hk", + "lastModified": 1721831314, + "narHash": "sha256-I1j5HPSbbh3l1D0C9oP/59YB4e+64K9NDRl7ueD1c/Y=", + "owner": "intersectmbo", "repo": "cardano-haskell-packages", - "rev": "e8298604717dbaa311c1e42e021b571670f4b039", + "rev": "8815ee7598bc39a02db8896b788f69accf892790", "type": "github" }, "original": { - "owner": "input-output-hk", + "owner": "intersectmbo", "ref": "repo", "repo": "cardano-haskell-packages", "type": "github" @@ -84,6 +101,22 @@ "type": "github" } }, + "HTTP_10": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, "HTTP_2": { "flake": false, "locked": { @@ -180,9 +213,41 @@ "type": "github" } }, + "HTTP_8": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, + "HTTP_9": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, "agenix": { "inputs": { - "nixpkgs": "nixpkgs_9" + "nixpkgs": "nixpkgs_38" }, "locked": { "lastModified": 1641576265, @@ -200,8 +265,8 @@ }, "agenix-cli": { "inputs": { - "flake-utils": "flake-utils_6", - "nixpkgs": "nixpkgs_10" + "flake-utils": "flake-utils_21", + "nixpkgs": "nixpkgs_39" }, "locked": { "lastModified": 1641404293, @@ -219,8 +284,8 @@ }, "agenix-cli_2": { "inputs": { - "flake-utils": "flake-utils_7", - "nixpkgs": "nixpkgs_12" + "flake-utils": "flake-utils_22", + "nixpkgs": "nixpkgs_41" }, "locked": { "lastModified": 1641404293, @@ -238,8 +303,8 @@ }, "agenix-cli_3": { "inputs": { - "flake-utils": "flake-utils_18", - "nixpkgs": "nixpkgs_41" + "flake-utils": "flake-utils_33", + "nixpkgs": "nixpkgs_70" }, "locked": { "lastModified": 1641404293, @@ -257,7 +322,7 @@ }, "agenix_2": { "inputs": { - "nixpkgs": "nixpkgs_11" + "nixpkgs": "nixpkgs_40" }, "locked": { "lastModified": 1641576265, @@ -350,7 +415,7 @@ }, "agenix_6": { "inputs": { - "nixpkgs": "nixpkgs_40" + "nixpkgs": "nixpkgs_69" }, "locked": { "lastModified": 1641576265, @@ -418,7 +483,7 @@ "alejandra": { "inputs": { "flakeCompat": "flakeCompat", - "nixpkgs": "nixpkgs_35" + "nixpkgs": "nixpkgs_64" }, "locked": { "lastModified": 1646360966, @@ -434,6 +499,51 @@ "type": "github" } }, + "ameba-src": { + "flake": false, + "locked": { + "lastModified": 1679041484, + "narHash": "sha256-pc9mtVR/PBhM5l1PnDkm+y+McxbrfAmQzxmLi761VF4=", + "owner": "crystal-ameba", + "repo": "ameba", + "rev": "7c74d196d6d9a496a81a0c7b79ef44f39faf41b8", + "type": "github" + }, + "original": { + "owner": "crystal-ameba", + "ref": "v1.4.3", + "repo": "ameba", + "type": "github" + } + }, + "auth-keys-hub": { + "inputs": { + "crystal": "crystal", + "flake-parts": "flake-parts_2", + "inclusive": "inclusive", + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "nixpkgs" + ], + "statix": "statix", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1691483346, + "narHash": "sha256-wvn84eGcc+PMbq/qSCWcZ/kV7/bjwuGOVSn/9rGaaKw=", + "owner": "input-output-hk", + "repo": "auth-keys-hub", + "rev": "ab7c79f49886b8f24cfae4b967a59ea62af9156e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "auth-keys-hub", + "type": "github" + } + }, "bats-assert": { "flake": false, "locked": { @@ -482,6 +592,22 @@ "type": "github" } }, + "bats-assert_4": { + "flake": false, + "locked": { + "lastModified": 1636059754, + "narHash": "sha256-ewME0l27ZqfmAwJO4h5biTALc9bDLv7Bl3ftBzBuZwk=", + "owner": "bats-core", + "repo": "bats-assert", + "rev": "34551b1d7f8c7b677c1a66fc0ac140d6223409e5", + "type": "github" + }, + "original": { + "owner": "bats-core", + "repo": "bats-assert", + "type": "github" + } + }, "bats-support": { "flake": false, "locked": { @@ -530,28 +656,61 @@ "type": "github" } }, + "bats-support_4": { + "flake": false, + "locked": { + "lastModified": 1548869839, + "narHash": "sha256-Gr4ntadr42F2Ks8Pte2D4wNDbijhujuoJi4OPZnTAZU=", + "owner": "bats-core", + "repo": "bats-support", + "rev": "d140a65044b2d6810381935ae7f0c94c7023c8c3", + "type": "github" + }, + "original": { + "owner": "bats-core", + "repo": "bats-support", + "type": "github" + } + }, + "bdwgc-src": { + "flake": false, + "locked": { + "lastModified": 1661523039, + "narHash": "sha256-UYJQGeSykmfydGAmTlNJNyAPBasBkddOSoopBHiY7TI=", + "owner": "ivmai", + "repo": "bdwgc", + "rev": "cd1fbc1dbfd2cc888436944dd2784f39820698d7", + "type": "github" + }, + "original": { + "owner": "ivmai", + "ref": "v8.2.2", + "repo": "bdwgc", + "type": "github" + } + }, "bitte": { "inputs": { "agenix": "agenix", "agenix-cli": "agenix-cli", - "blank": "blank_2", + "blank": "blank_6", "capsules": "capsules", "data-merge": "data-merge", "deploy": "deploy_2", - "fenix": "fenix_4", - "hydra": "hydra_3", - "n2c": "n2c_2", - "nix": "nix_5", - "nixpkgs": "nixpkgs_29", + "fenix": "fenix_6", + "hydra": "hydra_7", + "n2c": "n2c_5", + "nix": "nix_10", + "nixpkgs": "nixpkgs_58", "nixpkgs-docker": "nixpkgs-docker", - "nixpkgs-unstable": "nixpkgs-unstable_3", + "nixpkgs-unstable": "nixpkgs-unstable_8", "nomad-driver-nix": "nomad-driver-nix_2", "nomad-follower": "nomad-follower_2", - "ops-lib": "ops-lib_3", + "ops-lib": "ops-lib_5", "ragenix": "ragenix_3", - "std": "std_2", - "terranix": "terranix_2", - "utils": "utils_12" + "std": "std_6", + "terranix": "terranix_3", + "utils": "utils_17" }, "locked": { "lastModified": 1661790449, @@ -629,20 +788,20 @@ "inputs": { "agenix": "agenix_2", "agenix-cli": "agenix-cli_2", - "blank": "blank_3", + "blank": "blank_7", "deploy": "deploy", - "fenix": "fenix_2", - "hydra": "hydra_2", - "nix": "nix_2", - "nixpkgs": "nixpkgs_15", - "nixpkgs-unstable": "nixpkgs-unstable_2", + "fenix": "fenix_4", + "hydra": "hydra_6", + "nix": "nix_7", + "nixpkgs": "nixpkgs_44", + "nixpkgs-unstable": "nixpkgs-unstable_7", "nomad": "nomad", "nomad-driver-nix": "nomad-driver-nix", "nomad-follower": "nomad-follower", - "ops-lib": "ops-lib_2", + "ops-lib": "ops-lib_4", "ragenix": "ragenix", - "terranix": "terranix", - "utils": "utils_7", + "terranix": "terranix_2", + "utils": "utils_12", "vulnix": "vulnix" }, "locked": { @@ -663,20 +822,20 @@ "inputs": { "agenix": "agenix_6", "agenix-cli": "agenix-cli_3", - "blank": "blank_4", + "blank": "blank_8", "deploy": "deploy_3", - "fenix": "fenix_6", - "hydra": "hydra_4", - "nix": "nix_9", - "nixpkgs": "nixpkgs_44", - "nixpkgs-unstable": "nixpkgs-unstable_4", + "fenix": "fenix_8", + "hydra": "hydra_8", + "nix": "nix_14", + "nixpkgs": "nixpkgs_73", + "nixpkgs-unstable": "nixpkgs-unstable_9", "nomad": "nomad_2", "nomad-driver-nix": "nomad-driver-nix_3", "nomad-follower": "nomad-follower_3", - "ops-lib": "ops-lib_4", + "ops-lib": "ops-lib_6", "ragenix": "ragenix_4", - "terranix": "terranix_3", - "utils": "utils_21", + "terranix": "terranix_4", + "utils": "utils_26", "vulnix": "vulnix_2" }, "locked": { @@ -768,6 +927,51 @@ "type": "github" } }, + "blank_6": { + "locked": { + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "blank", + "type": "github" + } + }, + "blank_7": { + "locked": { + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "blank", + "type": "github" + } + }, + "blank_8": { + "locked": { + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "blank", + "type": "github" + } + }, "blockfrost": { "inputs": { "nixpkgs": "nixpkgs" @@ -787,6 +991,25 @@ "type": "github" } }, + "blockfrost_2": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1716466734, + "narHash": "sha256-h1LdfN/2KlD/XRjgj7rDNRInxSKZCOx6OF4jak/3c/E=", + "owner": "blockfrost", + "repo": "blockfrost-backend-ryo", + "rev": "7204204615be69b2f298ddf11f9a23dbbb184e55", + "type": "github" + }, + "original": { + "owner": "blockfrost", + "ref": "v2.0.3", + "repo": "blockfrost-backend-ryo", + "type": "github" + } + }, "blst": { "flake": false, "locked": { @@ -821,32 +1044,134 @@ "type": "github" } }, - "byron-chain": { + "blst_3": { "flake": false, "locked": { - "lastModified": 1557232434, - "narHash": "sha256-2rclcOjIVq0lFCdYAa8S9imzZZHqySn2LZ/O48hUofw=", - "owner": "input-output-hk", - "repo": "cardano-mainnet-mirror", - "rev": "a31ac7534ec855b715b9a6bb6a06861ee94935d9", + "lastModified": 1656163412, + "narHash": "sha256-xero1aTe2v4IhWIJaEDUsVDOfE77dOV5zKeHWntHogY=", + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "cardano-mainnet-mirror", + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", "type": "github" } }, - "cabal-32": { + "blst_4": { "flake": false, "locked": { - "lastModified": 1603716527, - "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", - "owner": "haskell", - "repo": "cabal", - "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", - "type": "github" - }, + "lastModified": 1656163412, + "narHash": "sha256-xero1aTe2v4IhWIJaEDUsVDOfE77dOV5zKeHWntHogY=", + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", + "type": "github" + }, + "original": { + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", + "type": "github" + } + }, + "blst_5": { + "flake": false, + "locked": { + "lastModified": 1656163412, + "narHash": "sha256-xero1aTe2v4IhWIJaEDUsVDOfE77dOV5zKeHWntHogY=", + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", + "type": "github" + }, + "original": { + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", + "type": "github" + } + }, + "blst_6": { + "flake": false, + "locked": { + "lastModified": 1691598027, + "narHash": "sha256-oqljy+ZXJAXEB/fJtmB8rlAr4UXM+Z2OkDa20gpILNA=", + "owner": "supranational", + "repo": "blst", + "rev": "3dd0f804b1819e5d03fb22ca2e6fac105932043a", + "type": "github" + }, + "original": { + "owner": "supranational", + "ref": "v0.3.11", + "repo": "blst", + "type": "github" + } + }, + "blst_7": { + "flake": false, + "locked": { + "lastModified": 1691598027, + "narHash": "sha256-oqljy+ZXJAXEB/fJtmB8rlAr4UXM+Z2OkDa20gpILNA=", + "owner": "supranational", + "repo": "blst", + "rev": "3dd0f804b1819e5d03fb22ca2e6fac105932043a", + "type": "github" + }, + "original": { + "owner": "supranational", + "ref": "v0.3.11", + "repo": "blst", + "type": "github" + } + }, + "byron-chain": { + "flake": false, + "locked": { + "lastModified": 1557232434, + "narHash": "sha256-2rclcOjIVq0lFCdYAa8S9imzZZHqySn2LZ/O48hUofw=", + "owner": "input-output-hk", + "repo": "cardano-mainnet-mirror", + "rev": "a31ac7534ec855b715b9a6bb6a06861ee94935d9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-mainnet-mirror", + "type": "github" + } + }, + "cabal-32": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-32_10": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, "original": { "owner": "haskell", "ref": "3.2", @@ -956,6 +1281,40 @@ "type": "github" } }, + "cabal-32_8": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-32_9": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, "cabal-34": { "flake": false, "locked": { @@ -973,14 +1332,31 @@ "type": "github" } }, + "cabal-34_10": { + "flake": false, + "locked": { + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", + "owner": "haskell", + "repo": "cabal", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, "cabal-34_2": { "flake": false, "locked": { - "lastModified": 1640353650, - "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", "owner": "haskell", "repo": "cabal", - "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", "type": "github" }, "original": { @@ -993,11 +1369,11 @@ "cabal-34_3": { "flake": false, "locked": { - "lastModified": 1640353650, - "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", "owner": "haskell", "repo": "cabal", - "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", "type": "github" }, "original": { @@ -1008,6 +1384,40 @@ } }, "cabal-34_4": { + "flake": false, + "locked": { + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", + "owner": "haskell", + "repo": "cabal", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34_5": { + "flake": false, + "locked": { + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", + "owner": "haskell", + "repo": "cabal", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34_6": { "flake": false, "locked": { "lastModified": 1640353650, @@ -1024,7 +1434,7 @@ "type": "github" } }, - "cabal-34_5": { + "cabal-34_7": { "flake": false, "locked": { "lastModified": 1640353650, @@ -1041,14 +1451,14 @@ "type": "github" } }, - "cabal-34_6": { + "cabal-34_8": { "flake": false, "locked": { - "lastModified": 1645834128, - "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", + "lastModified": 1640353650, + "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", "owner": "haskell", "repo": "cabal", - "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", + "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", "type": "github" }, "original": { @@ -1058,7 +1468,7 @@ "type": "github" } }, - "cabal-34_7": { + "cabal-34_9": { "flake": false, "locked": { "lastModified": 1640353650, @@ -1092,14 +1502,14 @@ "type": "github" } }, - "cabal-36_2": { + "cabal-36_10": { "flake": false, "locked": { - "lastModified": 1641652457, - "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "lastModified": 1669081697, + "narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=", "owner": "haskell", "repo": "cabal", - "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144", "type": "github" }, "original": { @@ -1109,14 +1519,14 @@ "type": "github" } }, - "cabal-36_3": { + "cabal-36_2": { "flake": false, "locked": { - "lastModified": 1641652457, - "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "lastModified": 1669081697, + "narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=", "owner": "haskell", "repo": "cabal", - "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144", "type": "github" }, "original": { @@ -1126,14 +1536,14 @@ "type": "github" } }, - "cabal-36_4": { + "cabal-36_3": { "flake": false, "locked": { - "lastModified": 1641652457, - "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "lastModified": 1669081697, + "narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=", "owner": "haskell", "repo": "cabal", - "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144", "type": "github" }, "original": { @@ -1143,14 +1553,14 @@ "type": "github" } }, - "cabal-36_5": { + "cabal-36_4": { "flake": false, "locked": { - "lastModified": 1641652457, - "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "lastModified": 1669081697, + "narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=", "owner": "haskell", "repo": "cabal", - "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144", "type": "github" }, "original": { @@ -1160,7 +1570,7 @@ "type": "github" } }, - "cabal-36_6": { + "cabal-36_5": { "flake": false, "locked": { "lastModified": 1669081697, @@ -1177,7 +1587,7 @@ "type": "github" } }, - "cabal-36_7": { + "cabal-36_6": { "flake": false, "locked": { "lastModified": 1641652457, @@ -1194,32 +1604,113 @@ "type": "github" } }, - "capsules": { - "inputs": { - "bitte": "bitte_2", - "iogo": "iogo", - "nixpkgs": "nixpkgs_23", - "ragenix": "ragenix_2" - }, + "cabal-36_7": { + "flake": false, "locked": { - "lastModified": 1658156716, - "narHash": "sha256-c1lH7PIN0rTKdGgosD5fCsHoAklAtGR/E1DFT2exIkM=", - "owner": "input-output-hk", - "repo": "devshell-capsules", - "rev": "88348a415130cee29ce187140e6f57d94d843d54", + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "devshell-capsules", - "type": "github" + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cabal-36_8": { + "flake": false, + "locked": { + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cabal-36_9": { + "flake": false, + "locked": { + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "call-flake": { + "locked": { + "lastModified": 1687380775, + "narHash": "sha256-bmhE1TmrJG4ba93l9WQTLuYM53kwGQAjYHRvHOeuxWU=", + "owner": "divnix", + "repo": "call-flake", + "rev": "74061f6c241227cd05e79b702db9a300a2e4131a", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "call-flake", + "type": "github" + } + }, + "capkgs": { + "locked": { + "lastModified": 1697123727, + "narHash": "sha256-uSXZAELJF5EfivH9qyLssBUAvhcf3RM9sKhD3W2mdhc=", + "owner": "input-output-hk", + "repo": "capkgs", + "rev": "b197e225592dfe38afb80c94b628d99968c0541d", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "capkgs", + "type": "github" + } + }, + "capsules": { + "inputs": { + "bitte": "bitte_2", + "iogo": "iogo", + "nixpkgs": "nixpkgs_52", + "ragenix": "ragenix_2" + }, + "locked": { + "lastModified": 1658156716, + "narHash": "sha256-c1lH7PIN0rTKdGgosD5fCsHoAklAtGR/E1DFT2exIkM=", + "owner": "input-output-hk", + "repo": "devshell-capsules", + "rev": "88348a415130cee29ce187140e6f57d94d843d54", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "devshell-capsules", + "type": "github" } }, "capsules_2": { "inputs": { "bitte": "bitte_3", "iogo": "iogo_2", - "nixpkgs": "nixpkgs_52", + "nixpkgs": "nixpkgs_81", "ragenix": "ragenix_5" }, "locked": { @@ -1238,17 +1729,20 @@ }, "cardano-automation": { "inputs": { - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_4", "haskellNix": [ - "cardano-node", + "cardano-nix", + "cardano-node-8.1.1", "haskellNix" ], "nixpkgs": [ - "cardano-node", + "cardano-nix", + "cardano-node-8.1.1", "nixpkgs" ], "tullia": [ - "cardano-node", + "cardano-nix", + "cardano-node-8.1.1", "tullia" ] }, @@ -1266,5424 +1760,9857 @@ "type": "github" } }, - "cardano-configurations": { - "flake": false, + "cardano-automation_2": { + "inputs": { + "flake-utils": "flake-utils_9", + "haskellNix": [ + "cardano-nix", + "cardano-node-8.7.3", + "haskellNix" + ], + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "nixpkgs" + ], + "tullia": "tullia_2" + }, "locked": { - "lastModified": 1699561895, - "narHash": "sha256-bLNN6lJUe5dR1EOdtDspReE2fu2EV7hQMHFGDinxf5Y=", + "lastModified": 1679408951, + "narHash": "sha256-xM78upkrXjRu/739V/IxFrA9m+6rvgOiolt4ReKLAog=", "owner": "input-output-hk", - "repo": "cardano-configurations", - "rev": "d952529afdfdf6d53ce190b1bf8af990a7ae9590", + "repo": "cardano-automation", + "rev": "628f135d243d4a9e388c187e4c6179246038ee72", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-configurations", - "rev": "d952529afdfdf6d53ce190b1bf8af990a7ae9590", + "repo": "cardano-automation", "type": "github" } }, - "cardano-configurations_2": { - "flake": false, + "cardano-automation_3": { + "inputs": { + "flake-utils": "flake-utils_16", + "haskellNix": [ + "cardano-node", + "haskellNix" + ], + "nixpkgs": [ + "cardano-node", + "nixpkgs" + ], + "tullia": "tullia_3" + }, "locked": { - "lastModified": 1694019972, - "narHash": "sha256-TQEvb6W2VlOWxqIFa4r8UFBVbu82Bb2hRaDtN5Zbiuk=", + "lastModified": 1679408951, + "narHash": "sha256-xM78upkrXjRu/739V/IxFrA9m+6rvgOiolt4ReKLAog=", "owner": "input-output-hk", - "repo": "cardano-configurations", - "rev": "65ef979cf69f420efca0a7aaf0412a610bc48097", + "repo": "cardano-automation", + "rev": "628f135d243d4a9e388c187e4c6179246038ee72", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-configurations", + "repo": "cardano-automation", "type": "github" } }, - "cardano-explorer-app": { + "cardano-configurations": { "flake": false, "locked": { - "lastModified": 1655291958, - "narHash": "sha256-OByt95cIJrA8pXsvCztsWmFcDaQaSYGohSOHoaZWKJs=", + "lastModified": 1721870874, + "narHash": "sha256-qiReN+xxtbb4kEfdIWbBcqcJpPGD8he0p/TVD7U3CqM=", "owner": "input-output-hk", - "repo": "cardano-explorer-app", - "rev": "a65938afe159adb1d1e2808305a7316738f5e634", + "repo": "cardano-configurations", + "rev": "7969a73e5c7ee1f3b2a40274b34191fdd8de170b", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "fix-nix-system", - "repo": "cardano-explorer-app", + "repo": "cardano-configurations", + "rev": "7969a73e5c7ee1f3b2a40274b34191fdd8de170b", "type": "github" } }, - "cardano-graphql": { + "cardano-configurations-8.1.1": { "flake": false, "locked": { - "lastModified": 1657201429, - "narHash": "sha256-kx8Pe5HllnJceQHsBDB4hHcEQNSiq8D+OFFkRuuUFQE=", + "lastModified": 1692193634, + "narHash": "sha256-cKw+iXKoMNrfN8M34/CtUelUZVLktVtzNzOYHI20dC0=", "owner": "input-output-hk", - "repo": "cardano-graphql", - "rev": "ffb40028f51e23983c2ae27693bbdcd152208d9d", + "repo": "cardano-configurations", + "rev": "9b69b59ef2fb2838855017f19af57b38c5d4abe4", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-graphql", + "repo": "cardano-configurations", + "rev": "9b69b59ef2fb2838855017f19af57b38c5d4abe4", "type": "github" } }, - "cardano-mainnet-mirror": { - "inputs": { - "nixpkgs": "nixpkgs_2" - }, + "cardano-configurations-8.7.3": { + "flake": false, "locked": { - "lastModified": 1642701714, - "narHash": "sha256-SR3luE+ePX6U193EKE/KSEuVzWAW0YsyPYDC4hOvALs=", + "lastModified": 1702085095, + "narHash": "sha256-IJChESftdO2tj2pRB+82xMaLP/RqyKHzttE7QMLqvBQ=", "owner": "input-output-hk", - "repo": "cardano-mainnet-mirror", - "rev": "819488be9eabbba6aaa7c931559bc584d8071e3d", + "repo": "cardano-configurations", + "rev": "21249e0d5c68b4e8f3661b250aa8272a8785d678", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "nix", - "repo": "cardano-mainnet-mirror", + "repo": "cardano-configurations", + "rev": "21249e0d5c68b4e8f3661b250aa8272a8785d678", "type": "github" } }, - "cardano-node": { + "cardano-db-sync": { "inputs": { "CHaP": "CHaP_2", - "cardano-automation": "cardano-automation", - "cardano-mainnet-mirror": "cardano-mainnet-mirror", - "customConfig": "customConfig", - "em": "em", - "empty-flake": "empty-flake", - "flake-compat": "flake-compat", + "cardano-parts": "cardano-parts", + "flake-compat": "flake-compat_4", "hackageNix": "hackageNix", "haskellNix": "haskellNix", - "hostNixpkgs": [ - "cardano-node", - "nixpkgs" - ], "iohkNix": "iohkNix", - "nix2container": "nix2container", "nixpkgs": [ - "cardano-node", + "cardano-nix", + "cardano-db-sync", "haskellNix", "nixpkgs-unstable" ], - "ops-lib": "ops-lib", - "std": [ - "cardano-node", - "tullia", - "std" - ], - "tullia": "tullia", - "utils": "utils_2" + "utils": "utils" }, "locked": { - "lastModified": 1687190129, - "narHash": "sha256-JCa9+QhZ2RVSIKkhz2WCZqTKCgdUSuezWS2YsQ5vhM4=", - "owner": "input-output-hk", - "repo": "cardano-node", - "rev": "6f79e5c3ea109a70cd01910368e011635767305a", + "lastModified": 1707925775, + "narHash": "sha256-z3YUrUImpV/wmJi+pfw6YuhBw+2Xd3jGlSWk7WI69/4=", + "owner": "intersectmbo", + "repo": "cardano-db-sync", + "rev": "ed3dc8bbb79f07c26ec43f10bad661b0bef3b915", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "8.1.1", - "repo": "cardano-node", + "owner": "intersectmbo", + "ref": "13.2.0.1", + "repo": "cardano-db-sync", "type": "github" } }, - "cardano-node_2": { + "cardano-db-sync-schema": { "flake": false, "locked": { - "lastModified": 1659625017, - "narHash": "sha256-4IrheFeoWfvkZQndEk4fGUkOiOjcVhcyXZ6IqmvkDgg=", + "lastModified": 1688568916, + "narHash": "sha256-XTGTi3PzCcbLL+63JSXTe7mQmGKB0YgEoW1VpqdX2d0=", "owner": "input-output-hk", - "repo": "cardano-node", - "rev": "950c4e222086fed5ca53564e642434ce9307b0b9", + "repo": "cardano-db-sync", + "rev": "6e69a80797f2d68423b25ca7787e81533b367e42", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "1.35.3", - "repo": "cardano-node", + "ref": "13.1.1.3", + "repo": "cardano-db-sync", "type": "github" } }, - "cardano-shell": { + "cardano-db-sync-schema-ng": { "flake": false, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1694078776, + "narHash": "sha256-QBnUDobTwWQmooCNr1WcaAzRbAKokon8lvAN6VQ1u34=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-db-sync", + "rev": "b44eb735fe64fe4e8079935df722d0a32a41c2a4", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "sancho-1-1-0", + "repo": "cardano-db-sync", "type": "github" } }, - "cardano-shell_2": { + "cardano-db-sync-service": { "flake": false, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1688568916, + "narHash": "sha256-XTGTi3PzCcbLL+63JSXTe7mQmGKB0YgEoW1VpqdX2d0=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-db-sync", + "rev": "6e69a80797f2d68423b25ca7787e81533b367e42", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "13.1.1.3", + "repo": "cardano-db-sync", "type": "github" } }, - "cardano-shell_3": { + "cardano-explorer-app": { "flake": false, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1655291958, + "narHash": "sha256-OByt95cIJrA8pXsvCztsWmFcDaQaSYGohSOHoaZWKJs=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-explorer-app", + "rev": "a65938afe159adb1d1e2808305a7316738f5e634", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "fix-nix-system", + "repo": "cardano-explorer-app", "type": "github" } }, - "cardano-shell_4": { + "cardano-graphql": { "flake": false, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1657201429, + "narHash": "sha256-kx8Pe5HllnJceQHsBDB4hHcEQNSiq8D+OFFkRuuUFQE=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-graphql", + "rev": "ffb40028f51e23983c2ae27693bbdcd152208d9d", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "repo": "cardano-graphql", "type": "github" } }, - "cardano-shell_5": { - "flake": false, + "cardano-mainnet-mirror": { + "inputs": { + "nixpkgs": "nixpkgs_15" + }, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1642701714, + "narHash": "sha256-SR3luE+ePX6U193EKE/KSEuVzWAW0YsyPYDC4hOvALs=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-mainnet-mirror", + "rev": "819488be9eabbba6aaa7c931559bc584d8071e3d", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "nix", + "repo": "cardano-mainnet-mirror", "type": "github" } }, - "cardano-shell_6": { - "flake": false, + "cardano-mainnet-mirror_2": { + "inputs": { + "nixpkgs": "nixpkgs_25" + }, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1642701714, + "narHash": "sha256-SR3luE+ePX6U193EKE/KSEuVzWAW0YsyPYDC4hOvALs=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-mainnet-mirror", + "rev": "819488be9eabbba6aaa7c931559bc584d8071e3d", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "nix", + "repo": "cardano-mainnet-mirror", "type": "github" } }, - "cardano-shell_7": { - "flake": false, + "cardano-mainnet-mirror_3": { + "inputs": { + "nixpkgs": "nixpkgs_34" + }, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1642701714, + "narHash": "sha256-SR3luE+ePX6U193EKE/KSEuVzWAW0YsyPYDC4hOvALs=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-mainnet-mirror", + "rev": "819488be9eabbba6aaa7c931559bc584d8071e3d", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "nix", + "repo": "cardano-mainnet-mirror", "type": "github" } }, - "cardano-wallet": { + "cardano-nix": { "inputs": { - "customConfig": "customConfig_2", - "ema": "ema", - "emanote": "emanote", - "flake-compat": "flake-compat_8", - "flake-utils": "flake-utils_25", - "haskellNix": "haskellNix_2", + "blockfrost": "blockfrost_2", + "cardano-configurations-8.1.1": "cardano-configurations-8.1.1", + "cardano-configurations-8.7.3": "cardano-configurations-8.7.3", + "cardano-db-sync": "cardano-db-sync", + "cardano-node-8.1.1": "cardano-node-8.1.1", + "cardano-node-8.7.3": "cardano-node-8.7.3", + "devour-flake": "devour-flake", + "devshell": "devshell_4", + "flake-parts": "flake-parts_5", + "flake-root": "flake-root", + "hercules-ci-effects": "hercules-ci-effects", + "nixpkgs": [ + "nixpkgs" + ], + "pre-commit-hooks-nix": "pre-commit-hooks-nix", + "treefmt-nix": "treefmt-nix_3" + }, + "locked": { + "lastModified": 1722438671, + "narHash": "sha256-Nb8bROKPjRWFMsaHIK4BOvsTceL9klpF3Ucp/zHqRzM=", + "owner": "mlabs-haskell", + "repo": "cardano.nix", + "rev": "7e696a77440d14f161c8b426d90fecfdb70ad8d8", + "type": "github" + }, + "original": { + "owner": "mlabs-haskell", + "repo": "cardano.nix", + "type": "github" + } + }, + "cardano-node": { + "inputs": { + "CHaP": "CHaP_5", + "cardano-automation": "cardano-automation_3", + "cardano-mainnet-mirror": "cardano-mainnet-mirror_3", + "customConfig": "customConfig_3", + "em": "em_3", + "empty-flake": "empty-flake_4", + "flake-compat": "flake-compat_15", + "hackageNix": "hackageNix_4", + "haskellNix": "haskellNix_4", "hostNixpkgs": [ - "db-sync", - "cardano-world", - "cardano-wallet", + "cardano-node", "nixpkgs" ], - "iohkNix": "iohkNix_2", + "iohkNix": "iohkNix_4", + "nix2container": "nix2container_6", "nixpkgs": [ - "db-sync", - "cardano-world", - "cardano-wallet", + "cardano-node", "haskellNix", "nixpkgs-unstable" - ] + ], + "ops-lib": "ops-lib_3", + "std": "std_5", + "utils": "utils_7" }, "locked": { - "lastModified": 1656674685, - "narHash": "sha256-Uq02O758v7U61a9Ol6VzSDyx3S/CVHn0l/OUM1UYJkY=", + "lastModified": 1722955151, + "narHash": "sha256-pZUg2PbhK35QdMcEP0or6IyKXBr544KyebQ+xiNc6PE=", "owner": "input-output-hk", - "repo": "cardano-wallet", - "rev": "c0ece6ad1868682b074708ffb810bdc2ea96934f", + "repo": "cardano-node", + "rev": "4f4e372a1641ac68cd09fb0339e6f55bef1ab85d", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "v2022-07-01", - "repo": "cardano-wallet", + "repo": "cardano-node", + "rev": "4f4e372a1641ac68cd09fb0339e6f55bef1ab85d", "type": "github" } }, - "cardano-world": { + "cardano-node-8.1.1": { "inputs": { - "bitte": "bitte", - "bitte-cells": "bitte-cells", - "byron-chain": "byron-chain", - "capsules": "capsules_2", - "cardano-db-sync": [ - "db-sync" + "CHaP": "CHaP_3", + "cardano-automation": "cardano-automation", + "cardano-mainnet-mirror": "cardano-mainnet-mirror", + "customConfig": "customConfig", + "em": "em", + "empty-flake": "empty-flake_2", + "flake-compat": "flake-compat_6", + "hackageNix": "hackageNix_2", + "haskellNix": "haskellNix_2", + "hostNixpkgs": [ + "cardano-nix", + "cardano-node-8.1.1", + "nixpkgs" ], - "cardano-explorer-app": "cardano-explorer-app", - "cardano-graphql": "cardano-graphql", - "cardano-node": "cardano-node_2", - "cardano-wallet": "cardano-wallet", - "data-merge": "data-merge_3", - "flake-compat": "flake-compat_9", - "hackage": "hackage_3", - "haskell-nix": "haskell-nix_2", - "iohk-nix": "iohk-nix", - "n2c": "n2c_3", - "nix-inclusive": "nix-inclusive", - "nixpkgs": "nixpkgs_63", - "nixpkgs-haskell": [ - "db-sync", - "cardano-world", - "haskell-nix", + "iohkNix": "iohkNix_2", + "nix2container": "nix2container", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.1.1", + "haskellNix", "nixpkgs-unstable" ], - "ogmios": "ogmios", - "std": "std_3", - "tullia": "tullia_2" + "ops-lib": "ops-lib", + "std": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std" + ], + "tullia": "tullia", + "utils": "utils_3" }, "locked": { - "lastModified": 1662508244, - "narHash": "sha256-s8kroVd8VAZ/Lfv2gNt+RzIuSnWpQxAAL0y90tn1i0o=", - "owner": "input-output-hk", - "repo": "cardano-world", - "rev": "0b6dcb5b61a0f7a2c048cb757463cbc0dfa0fe24", + "lastModified": 1687190129, + "narHash": "sha256-JCa9+QhZ2RVSIKkhz2WCZqTKCgdUSuezWS2YsQ5vhM4=", + "owner": "intersectmbo", + "repo": "cardano-node", + "rev": "6f79e5c3ea109a70cd01910368e011635767305a", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "cardano-world", + "owner": "intersectmbo", + "ref": "8.1.1", + "repo": "cardano-node", "type": "github" } }, - "cicero": { + "cardano-node-8.7.3": { "inputs": { - "alejandra": "alejandra", - "data-merge": "data-merge_2", - "devshell": "devshell_8", - "driver": "driver", - "follower": "follower", - "haskell-nix": "haskell-nix", - "inclusive": "inclusive_8", - "nix": "nix_8", - "nix-cache-proxy": "nix-cache-proxy", - "nixpkgs": "nixpkgs_39", - "poetry2nix": "poetry2nix", - "utils": "utils_16" + "CHaP": "CHaP_4", + "cardano-automation": "cardano-automation_2", + "cardano-mainnet-mirror": "cardano-mainnet-mirror_2", + "customConfig": "customConfig_2", + "em": "em_2", + "empty-flake": "empty-flake_3", + "flake-compat": "flake-compat_10", + "hackageNix": "hackageNix_3", + "haskellNix": "haskellNix_3", + "hostNixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "nixpkgs" + ], + "iohkNix": "iohkNix_3", + "nix2container": "nix2container_4", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "haskellNix", + "nixpkgs-unstable" + ], + "ops-lib": "ops-lib_2", + "std": "std_3", + "utils": "utils_5" }, "locked": { - "lastModified": 1647522107, - "narHash": "sha256-Kti1zv+GXnbujkJ0ODB2ukq4Eb2RVOpudZ1xVDhhbes=", - "owner": "input-output-hk", - "repo": "cicero", - "rev": "0fd8642fe437f6129fe6914f032d3fdc7591d4fe", + "lastModified": 1702654749, + "narHash": "sha256-fIzSNSKWC7qMRjHUMHfrMnEzHiFu7ac/UUgfofXqaFY=", + "owner": "intersectmbo", + "repo": "cardano-node", + "rev": "a4a8119b59b1fbb9a69c79e1e6900e91292161e7", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "cicero", + "owner": "intersectmbo", + "ref": "8.7.3", + "repo": "cardano-node", "type": "github" } }, - "customConfig": { + "cardano-node-service": { + "flake": false, "locked": { - "lastModified": 1630400035, - "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "lastModified": 1690209950, + "narHash": "sha256-d0V8N+y/OarYv6GQycGXnbPly7GeJRBEeE1017qj9eI=", "owner": "input-output-hk", - "repo": "empty-flake", - "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", + "repo": "cardano-node", + "rev": "d2d90b48c5577b4412d5c9c9968b55f8ab4b9767", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "empty-flake", + "ref": "8.1.2", + "repo": "cardano-node", "type": "github" } }, - "customConfig_2": { + "cardano-node_2": { + "flake": false, "locked": { - "lastModified": 1630400035, - "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "lastModified": 1659625017, + "narHash": "sha256-4IrheFeoWfvkZQndEk4fGUkOiOjcVhcyXZ6IqmvkDgg=", "owner": "input-output-hk", - "repo": "empty-flake", - "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", + "repo": "cardano-node", + "rev": "950c4e222086fed5ca53564e642434ce9307b0b9", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "empty-flake", + "ref": "1.35.3", + "repo": "cardano-node", "type": "github" } }, - "customConfig_3": { - "locked": { - "lastModified": 1, - "narHash": "sha256-Zd5w1I1Dwt783Q4WuBuCpedcwG1DrIgQGqabyF87prM=", - "path": "./custom-config", - "type": "path" - }, - "original": { - "path": "./custom-config", - "type": "path" - } - }, - "data-merge": { + "cardano-parts": { "inputs": { - "nixlib": "nixlib", - "yants": "yants_2" + "auth-keys-hub": "auth-keys-hub", + "capkgs": "capkgs", + "cardano-db-sync-schema": "cardano-db-sync-schema", + "cardano-db-sync-schema-ng": "cardano-db-sync-schema-ng", + "cardano-db-sync-service": "cardano-db-sync-service", + "cardano-node-service": "cardano-node-service", + "cardano-wallet-service": "cardano-wallet-service", + "colmena": "colmena", + "empty-flake": "empty-flake", + "flake-parts": "flake-parts_3", + "haskell-nix": "haskell-nix", + "inputs-check": "inputs-check", + "iohk-nix": "iohk-nix", + "iohk-nix-ng": "iohk-nix-ng", + "nix": "nix_2", + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "nixpkgs" + ], + "nixpkgs-unstable": "nixpkgs-unstable_2", + "offchain-metadata-tools-service": "offchain-metadata-tools-service", + "sops-nix": "sops-nix", + "terraform-providers": "terraform-providers", + "terranix": "terranix", + "treefmt-nix": "treefmt-nix_2" }, "locked": { - "lastModified": 1648237091, - "narHash": "sha256-OtgcOt/CB0/9S0rh1eAog+AvAg9kF6GyAknyWOXiAZI=", - "owner": "divnix", - "repo": "data-merge", - "rev": "b21bcf7bd949ac92af3930ecb1d3df8786384722", + "lastModified": 1697147999, + "narHash": "sha256-mbSWIcmDnt2mlETCNL8MI97nDH1lkOxIxFHKXXfOV28=", + "owner": "input-output-hk", + "repo": "cardano-parts", + "rev": "af8993ee12f78ddfcc31eefe006391669cb11462", "type": "github" }, "original": { - "owner": "divnix", - "repo": "data-merge", + "owner": "input-output-hk", + "repo": "cardano-parts", "type": "github" } }, - "data-merge_2": { - "inputs": { - "nixlib": "nixlib_2" - }, + "cardano-shell": { + "flake": false, "locked": { - "lastModified": 1635967744, - "narHash": "sha256-01065dNad3BIepNzrpYuYInxq/ynqtGMSsIiNqjND7E=", - "owner": "divnix", - "repo": "data-merge", - "rev": "68bd71f980f75cf73bc5071982eddfe6bc089768", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "divnix", - "repo": "data-merge", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "data-merge_3": { - "inputs": { - "nixlib": "nixlib_3", - "yants": "yants_4" - }, + "cardano-shell_10": { + "flake": false, "locked": { - "lastModified": 1655854240, - "narHash": "sha256-j74ixD7Y0bF3h0fBJFKPR9botlrMu0fgG/YsiUKybko=", - "owner": "divnix", - "repo": "data-merge", - "rev": "0bbe0a68d4ee090b8bbad0c5e1e85060d2bdfe98", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "divnix", - "repo": "data-merge", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "db-sync": { - "inputs": { - "cardano-world": "cardano-world", - "customConfig": "customConfig_3", - "flake-compat": "flake-compat_10", - "haskellNix": "haskellNix_3", - "iohkNix": "iohkNix_3", - "nixpkgs": [ - "db-sync", - "haskellNix", - "nixpkgs-unstable" - ], - "utils": "utils_23" - }, + "cardano-shell_2": { + "flake": false, "locked": { - "lastModified": 1670313550, - "narHash": "sha256-Gkn/hyK0xiDJZY1O5JEwuosMzar+IskC9xxeBts+0H4=", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", "owner": "input-output-hk", - "repo": "cardano-db-sync", - "rev": "1040fa9ec85fd75ce9f02dae2006170136793d02", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "13.1.0.0", - "repo": "cardano-db-sync", + "repo": "cardano-shell", "type": "github" } }, - "deploy": { - "inputs": { - "fenix": "fenix", - "flake-compat": "flake-compat_4", - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte", - "capsules", - "bitte", - "deploy", - "fenix", - "nixpkgs" - ], - "utils": "utils_3" - }, + "cardano-shell_3": { + "flake": false, "locked": { - "lastModified": 1638318651, - "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", "owner": "input-output-hk", - "repo": "deploy-rs", - "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "deploy-rs", + "repo": "cardano-shell", "type": "github" } }, - "deploy_2": { - "inputs": { - "fenix": "fenix_3", - "flake-compat": "flake-compat_5", - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte", - "deploy", - "fenix", - "nixpkgs" - ], - "utils": "utils_9" - }, + "cardano-shell_4": { + "flake": false, "locked": { - "lastModified": 1638318651, - "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", "owner": "input-output-hk", - "repo": "deploy-rs", - "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "deploy-rs", + "repo": "cardano-shell", "type": "github" } }, - "deploy_3": { - "inputs": { - "fenix": "fenix_5", - "flake-compat": "flake-compat_6", - "nixpkgs": [ - "db-sync", - "cardano-world", - "capsules", - "bitte", - "deploy", - "fenix", - "nixpkgs" - ], - "utils": "utils_17" - }, + "cardano-shell_5": { + "flake": false, "locked": { - "lastModified": 1638318651, - "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", "owner": "input-output-hk", - "repo": "deploy-rs", - "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "deploy-rs", - "type": "github" - } - }, - "devshell": { - "inputs": { - "flake-utils": [ - "cardano-node", - "tullia", - "std", - "flake-utils" - ], - "nixpkgs": [ - "cardano-node", - "tullia", - "std", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1663445644, - "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", - "owner": "numtide", - "repo": "devshell", - "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" - } - }, - "devshell_10": { - "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "devshell", + "repo": "cardano-shell", "type": "github" } }, - "devshell_11": { + "cardano-shell_6": { + "flake": false, "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "devshell_12": { + "cardano-shell_7": { + "flake": false, "locked": { - "lastModified": 1632436039, - "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", - "owner": "numtide", - "repo": "devshell", - "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "devshell_13": { + "cardano-shell_8": { + "flake": false, "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "devshell_14": { + "cardano-shell_9": { + "flake": false, "locked": { - "lastModified": 1637098489, - "narHash": "sha256-IWBYLSNSENI/fTrXdYDhuCavxcgN9+RERrPM81f6DXY=", - "owner": "numtide", - "repo": "devshell", - "rev": "e8c2d4967b5c498b12551d1bb49352dcf9efa3e4", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "devshell_15": { + "cardano-wallet": { "inputs": { - "flake-utils": [ + "customConfig": "customConfig_4", + "ema": "ema", + "emanote": "emanote", + "flake-compat": "flake-compat_21", + "flake-utils": "flake-utils_40", + "haskellNix": "haskellNix_5", + "hostNixpkgs": [ "db-sync", "cardano-world", - "std", - "flake-utils" + "cardano-wallet", + "nixpkgs" ], + "iohkNix": "iohkNix_5", "nixpkgs": [ "db-sync", "cardano-world", - "std", - "nixpkgs" + "cardano-wallet", + "haskellNix", + "nixpkgs-unstable" ] }, "locked": { - "lastModified": 1658746384, - "narHash": "sha256-CCJcoMOcXyZFrV1ag4XMTpAPjLWb4Anbv+ktXFI1ry0=", - "owner": "numtide", - "repo": "devshell", - "rev": "0ffc7937bb5e8141af03d462b468bd071eb18e1b", + "lastModified": 1656674685, + "narHash": "sha256-Uq02O758v7U61a9Ol6VzSDyx3S/CVHn0l/OUM1UYJkY=", + "owner": "input-output-hk", + "repo": "cardano-wallet", + "rev": "c0ece6ad1868682b074708ffb810bdc2ea96934f", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "ref": "v2022-07-01", + "repo": "cardano-wallet", "type": "github" } }, - "devshell_16": { - "inputs": { - "flake-utils": "flake-utils_31", - "nixpkgs": [ - "db-sync", - "cardano-world", - "tullia", - "std", - "nixpkgs" - ] - }, + "cardano-wallet-service": { + "flake": false, "locked": { - "lastModified": 1650900878, - "narHash": "sha256-qhNncMBSa9STnhiLfELEQpYC1L4GrYHNIzyCZ/pilsI=", - "owner": "numtide", - "repo": "devshell", - "rev": "d97df53b5ddaa1cfbea7cddbd207eb2634304733", + "lastModified": 1689751896, + "narHash": "sha256-ijflgIw+1FpLoxM4Rksf4MJvNqnEPAv3gNWE8zMuefU=", + "owner": "cardano-foundation", + "repo": "cardano-wallet", + "rev": "3f0d2f3abe706958fab8cdc528184068bd0453c9", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "cardano-foundation", + "ref": "v2023-07-18", + "repo": "cardano-wallet", "type": "github" } }, - "devshell_2": { + "cardano-world": { + "inputs": { + "bitte": "bitte", + "bitte-cells": "bitte-cells", + "byron-chain": "byron-chain", + "capsules": "capsules_2", + "cardano-db-sync": [ + "db-sync" + ], + "cardano-explorer-app": "cardano-explorer-app", + "cardano-graphql": "cardano-graphql", + "cardano-node": "cardano-node_2", + "cardano-wallet": "cardano-wallet", + "data-merge": "data-merge_3", + "flake-compat": "flake-compat_22", + "hackage": "hackage_4", + "haskell-nix": "haskell-nix_3", + "iohk-nix": "iohk-nix_2", + "n2c": "n2c_6", + "nix-inclusive": "nix-inclusive", + "nixpkgs": "nixpkgs_92", + "nixpkgs-haskell": [ + "db-sync", + "cardano-world", + "haskell-nix", + "nixpkgs-unstable" + ], + "ogmios": "ogmios", + "std": "std_7", + "tullia": "tullia_4" + }, "locked": { - "lastModified": 1632436039, - "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", - "owner": "numtide", - "repo": "devshell", - "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", + "lastModified": 1662508244, + "narHash": "sha256-s8kroVd8VAZ/Lfv2gNt+RzIuSnWpQxAAL0y90tn1i0o=", + "owner": "input-output-hk", + "repo": "cardano-world", + "rev": "0b6dcb5b61a0f7a2c048cb757463cbc0dfa0fe24", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cardano-world", "type": "github" } }, - "devshell_3": { + "cicero": { + "inputs": { + "alejandra": "alejandra", + "data-merge": "data-merge_2", + "devshell": "devshell_12", + "driver": "driver", + "follower": "follower", + "haskell-nix": "haskell-nix_2", + "inclusive": "inclusive_9", + "nix": "nix_13", + "nix-cache-proxy": "nix-cache-proxy", + "nixpkgs": "nixpkgs_68", + "poetry2nix": "poetry2nix", + "utils": "utils_21" + }, "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", + "lastModified": 1647522107, + "narHash": "sha256-Kti1zv+GXnbujkJ0ODB2ukq4Eb2RVOpudZ1xVDhhbes=", + "owner": "input-output-hk", + "repo": "cicero", + "rev": "0fd8642fe437f6129fe6914f032d3fdc7591d4fe", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cicero", "type": "github" } }, - "devshell_4": { + "colmena": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "nixpkgs" + ], + "stable": "stable" + }, "locked": { - "lastModified": 1637098489, - "narHash": "sha256-IWBYLSNSENI/fTrXdYDhuCavxcgN9+RERrPM81f6DXY=", - "owner": "numtide", - "repo": "devshell", - "rev": "e8c2d4967b5c498b12551d1bb49352dcf9efa3e4", + "lastModified": 1684127108, + "narHash": "sha256-01bfuSY4gnshhtqA1EJCw2CMsKkAx+dHS+sEpQ2+EAQ=", + "owner": "zhaofengli", + "repo": "colmena", + "rev": "5fdd743a11e7291bd8ac1e169d62ba6156c99be4", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "zhaofengli", + "ref": "v0.4.0", + "repo": "colmena", "type": "github" } }, - "devshell_5": { + "crane": { + "inputs": { + "flake-compat": "flake-compat_12", + "flake-utils": "flake-utils_14", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "paisano-mdbook-preprocessor", + "nixpkgs" + ], + "rust-overlay": "rust-overlay" + }, "locked": { - "lastModified": 1632436039, - "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", - "owner": "numtide", - "repo": "devshell", - "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", + "lastModified": 1676162383, + "narHash": "sha256-krUCKdz7ebHlFYm/A7IbKDnj2ZmMMm3yIEQcooqm7+E=", + "owner": "ipetkov", + "repo": "crane", + "rev": "6fb400ec631b22ccdbc7090b38207f7fb5cfb5f2", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "ipetkov", + "repo": "crane", "type": "github" } }, - "devshell_6": { + "crystal": { + "inputs": { + "ameba-src": "ameba-src", + "bdwgc-src": "bdwgc-src", + "crystal-aarch64-darwin": "crystal-aarch64-darwin", + "crystal-src": "crystal-src", + "crystal-x86_64-darwin": "crystal-x86_64-darwin", + "crystal-x86_64-linux": "crystal-x86_64-linux", + "crystalline-src": "crystalline-src", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs_3" + }, "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", + "lastModified": 1683429373, + "narHash": "sha256-Mx5lwMyk2T40wFqOoYcJLs4srwO2UrsepTZhlHNuTrI=", + "owner": "manveru", + "repo": "crystal-flake", + "rev": "e7a443c20e2be6e5dd870586705dd27c91aa9c5c", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "manveru", + "repo": "crystal-flake", "type": "github" } }, - "devshell_7": { - "inputs": { - "flake-utils": [ - "db-sync", - "cardano-world", - "bitte", - "std", - "flake-utils" - ], - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte", - "std", - "nixpkgs" - ] + "crystal-aarch64-darwin": { + "flake": false, + "locked": { + "narHash": "sha256-NqYaZHM3kHAgYbO0RDJtA8eHqp4vVe4MBpisTOGrRVw=", + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-darwin-universal.tar.gz" }, + "original": { + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-darwin-universal.tar.gz" + } + }, + "crystal-src": { + "flake": false, "locked": { - "lastModified": 1658746384, - "narHash": "sha256-CCJcoMOcXyZFrV1ag4XMTpAPjLWb4Anbv+ktXFI1ry0=", - "owner": "numtide", - "repo": "devshell", - "rev": "0ffc7937bb5e8141af03d462b468bd071eb18e1b", + "lastModified": 1681995387, + "narHash": "sha256-t+1vM1m62UftCvfa90Dg6nqt6Zseh/GP/Gc1VfOa4+c=", + "owner": "crystal-lang", + "repo": "crystal", + "rev": "a59a3dbd738269d5aad6051c3834fc70f482f469", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "crystal-lang", + "ref": "1.8.1", + "repo": "crystal", "type": "github" } }, - "devshell_8": { - "inputs": { - "flake-utils": "flake-utils_15", - "nixpkgs": "nixpkgs_36" + "crystal-x86_64-darwin": { + "flake": false, + "locked": { + "narHash": "sha256-NqYaZHM3kHAgYbO0RDJtA8eHqp4vVe4MBpisTOGrRVw=", + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-darwin-universal.tar.gz" }, + "original": { + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-darwin-universal.tar.gz" + } + }, + "crystal-x86_64-linux": { + "flake": false, "locked": { - "lastModified": 1644227066, - "narHash": "sha256-FHcFZtpZEWnUh62xlyY3jfXAXHzJNEDLDzLsJxn+ve0=", - "owner": "numtide", - "repo": "devshell", - "rev": "7033f64dd9ef8d9d8644c5030c73913351d2b660", - "type": "github" + "narHash": "sha256-/Jk3uiglM/hzjygxmMUgVTvz+tuFFjBv8+uUIL05rXo=", + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-linux-x86_64.tar.gz" }, "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-linux-x86_64.tar.gz" } }, - "devshell_9": { + "crystalline-src": { + "flake": false, "locked": { - "lastModified": 1632436039, - "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", - "owner": "numtide", - "repo": "devshell", - "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", + "lastModified": 1681549124, + "narHash": "sha256-kx3rdGqIbrOaHY7V3uXLqIFEYzzsMKzNwZ6Neq8zM3c=", + "owner": "elbywan", + "repo": "crystalline", + "rev": "4ac0ae282c5f4172230fea1e93df51c2b380f475", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "elbywan", + "ref": "v0.9.0", + "repo": "crystalline", "type": "github" } }, - "dmerge": { - "inputs": { - "nixlib": [ - "cardano-node", - "tullia", - "std", - "nixpkgs" - ], - "yants": [ - "cardano-node", - "tullia", - "std", - "yants" - ] - }, + "customConfig": { "locked": { - "lastModified": 1659548052, - "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", - "owner": "divnix", - "repo": "data-merge", - "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "divnix", - "repo": "data-merge", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "dmerge_2": { - "inputs": { - "nixlib": [ - "db-sync", - "cardano-world", - "bitte", - "std", - "nixpkgs" - ], - "yants": [ - "db-sync", - "cardano-world", - "bitte", - "std", - "yants" - ] - }, + "customConfig_2": { "locked": { - "lastModified": 1659548052, - "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", - "owner": "divnix", - "repo": "data-merge", - "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "divnix", - "repo": "data-merge", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "dmerge_3": { - "inputs": { - "nixlib": [ - "db-sync", - "cardano-world", - "std", - "nixpkgs" - ], - "yants": [ - "db-sync", - "cardano-world", - "std", - "yants" - ] - }, + "customConfig_3": { "locked": { - "lastModified": 1659548052, - "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", - "owner": "divnix", - "repo": "data-merge", - "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "divnix", - "repo": "data-merge", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "driver": { - "inputs": { - "devshell": "devshell_9", - "inclusive": "inclusive_6", - "nix": "nix_7", - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "nixpkgs" - ], - "utils": "utils_13" - }, + "customConfig_4": { "locked": { - "lastModified": 1644418487, - "narHash": "sha256-nzFmmBYjNjWVy25bHLLmZECfwJm3nxcAr/mYVYxWggA=", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", "owner": "input-output-hk", - "repo": "nomad-driver-nix", - "rev": "7f7adb6814b4bf926597e4b810b803140176122c", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "nomad-driver-nix", + "repo": "empty-flake", "type": "github" } }, - "easy-purescript-nix": { - "flake": false, + "customConfig_5": { "locked": { - "lastModified": 1696584097, - "narHash": "sha256-a9Hhqf/Fi0FkjRTcQr3pYDhrO9A9tdOkaeVgD23Cdrk=", - "owner": "justinwoo", - "repo": "easy-purescript-nix", - "rev": "d5fe5f4b210a0e4bac42ae0c159596a49c5eb016", - "type": "github" + "lastModified": 1, + "narHash": "sha256-Zd5w1I1Dwt783Q4WuBuCpedcwG1DrIgQGqabyF87prM=", + "path": "./custom-config", + "type": "path" }, "original": { - "owner": "justinwoo", - "repo": "easy-purescript-nix", - "type": "github" + "path": "./custom-config", + "type": "path" } }, - "em": { - "flake": false, + "data-merge": { + "inputs": { + "nixlib": "nixlib", + "yants": "yants_6" + }, "locked": { - "lastModified": 1684791668, - "narHash": "sha256-JyPm0RiWCfy/8rs7wd/IRSWIz+bTkD78uxIMnKktU2g=", - "owner": "deepfire", - "repo": "em", - "rev": "302cdf6d654fb18baff0213bdfa41a653774585a", + "lastModified": 1648237091, + "narHash": "sha256-OtgcOt/CB0/9S0rh1eAog+AvAg9kF6GyAknyWOXiAZI=", + "owner": "divnix", + "repo": "data-merge", + "rev": "b21bcf7bd949ac92af3930ecb1d3df8786384722", "type": "github" }, "original": { - "owner": "deepfire", - "repo": "em", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "ema": { + "data-merge_2": { "inputs": { - "flake-compat": "flake-compat_7", - "flake-utils": "flake-utils_22", - "nixpkgs": "nixpkgs_54", - "pre-commit-hooks": "pre-commit-hooks" + "nixlib": "nixlib_2" }, "locked": { - "lastModified": 1646661767, - "narHash": "sha256-5zxUr3nO4r04K5WGrW/+nW84qbOW8wNJLt902yQmyF4=", - "owner": "srid", - "repo": "ema", - "rev": "bcabc170b7de9cdd83b4bbcf59130b54933602ea", + "lastModified": 1635967744, + "narHash": "sha256-01065dNad3BIepNzrpYuYInxq/ynqtGMSsIiNqjND7E=", + "owner": "divnix", + "repo": "data-merge", + "rev": "68bd71f980f75cf73bc5071982eddfe6bc089768", "type": "github" }, "original": { - "owner": "srid", - "repo": "ema", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "ema_2": { - "flake": false, + "data-merge_3": { + "inputs": { + "nixlib": "nixlib_3", + "yants": "yants_8" + }, "locked": { - "lastModified": 1655231448, - "narHash": "sha256-LmAnOFKiqOWW9cQNZCbqFF0N1Mx073908voXz+4Fzic=", - "owner": "srid", - "repo": "ema", - "rev": "da5b29f03c1edfb7f947666a5a818fb97cc3c229", + "lastModified": 1655854240, + "narHash": "sha256-j74ixD7Y0bF3h0fBJFKPR9botlrMu0fgG/YsiUKybko=", + "owner": "divnix", + "repo": "data-merge", + "rev": "0bbe0a68d4ee090b8bbad0c5e1e85060d2bdfe98", "type": "github" }, "original": { - "owner": "srid", - "ref": "multisite", - "repo": "ema", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "emanote": { + "db-sync": { "inputs": { - "ema": "ema_2", - "flake-parts": "flake-parts", - "haskell-flake": "haskell-flake", - "nixpkgs": "nixpkgs_57", - "tailwind-haskell": "tailwind-haskell" + "cardano-world": "cardano-world", + "customConfig": "customConfig_5", + "flake-compat": "flake-compat_23", + "haskellNix": "haskellNix_6", + "iohkNix": "iohkNix_6", + "nixpkgs": [ + "db-sync", + "haskellNix", + "nixpkgs-unstable" + ], + "utils": "utils_28" }, "locked": { - "lastModified": 1655823900, - "narHash": "sha256-YEDJxa2gPf2+GGyrkFz4EliCml1FyDualZtbbZEmljA=", - "owner": "srid", - "repo": "emanote", - "rev": "147528d9df81b881214652ce0cefec0b3d52965e", + "lastModified": 1670313550, + "narHash": "sha256-Gkn/hyK0xiDJZY1O5JEwuosMzar+IskC9xxeBts+0H4=", + "owner": "input-output-hk", + "repo": "cardano-db-sync", + "rev": "1040fa9ec85fd75ce9f02dae2006170136793d02", "type": "github" }, "original": { - "owner": "srid", - "repo": "emanote", + "owner": "input-output-hk", + "ref": "13.1.0.0", + "repo": "cardano-db-sync", "type": "github" } }, - "empty-flake": { + "deploy": { + "inputs": { + "fenix": "fenix_3", + "flake-compat": "flake-compat_17", + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte", + "capsules", + "bitte", + "deploy", + "fenix", + "nixpkgs" + ], + "utils": "utils_8" + }, "locked": { - "lastModified": 1630400035, - "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "lastModified": 1638318651, + "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", "owner": "input-output-hk", - "repo": "empty-flake", - "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", + "repo": "deploy-rs", + "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "empty-flake", + "repo": "deploy-rs", "type": "github" } }, - "fenix": { + "deploy_2": { "inputs": { - "nixpkgs": "nixpkgs_13", - "rust-analyzer-src": "rust-analyzer-src" + "fenix": "fenix_5", + "flake-compat": "flake-compat_18", + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte", + "deploy", + "fenix", + "nixpkgs" + ], + "utils": "utils_14" }, "locked": { - "lastModified": 1645165506, - "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", - "owner": "nix-community", - "repo": "fenix", - "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", + "lastModified": 1638318651, + "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "owner": "input-output-hk", + "repo": "deploy-rs", + "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "input-output-hk", + "repo": "deploy-rs", "type": "github" } }, - "fenix_2": { + "deploy_3": { "inputs": { + "fenix": "fenix_7", + "flake-compat": "flake-compat_19", "nixpkgs": [ "db-sync", "cardano-world", - "bitte", "capsules", "bitte", - "nixpkgs-unstable" + "deploy", + "fenix", + "nixpkgs" ], - "rust-analyzer-src": "rust-analyzer-src_2" + "utils": "utils_22" }, "locked": { - "lastModified": 1649226351, - "narHash": "sha256-5fQwF5kYpPC7w0SOfdbE9Z7o5/i/dyo1BxMLVCA2h3E=", - "owner": "nix-community", - "repo": "fenix", - "rev": "c7e184561fe843abb861cd7d22c23066987078e2", + "lastModified": 1638318651, + "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "owner": "input-output-hk", + "repo": "deploy-rs", + "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "input-output-hk", + "repo": "deploy-rs", "type": "github" } }, - "fenix_3": { - "inputs": { - "nixpkgs": "nixpkgs_26", - "rust-analyzer-src": "rust-analyzer-src_3" - }, + "devour-flake": { + "flake": false, "locked": { - "lastModified": 1645165506, - "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", - "owner": "nix-community", - "repo": "fenix", - "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", + "lastModified": 1694098737, + "narHash": "sha256-O51F4YFOzlaQAc9b6xjkAqpvrvCtw/Os2M7TU0y4SKQ=", + "owner": "srid", + "repo": "devour-flake", + "rev": "30a34036b29b0d12989ef6c8be77aa949d85aef5", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "srid", + "repo": "devour-flake", "type": "github" } }, - "fenix_4": { + "devshell": { "inputs": { - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte", - "nixpkgs-unstable" + "flake-utils": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "flake-utils" ], - "rust-analyzer-src": "rust-analyzer-src_4" + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1660631227, - "narHash": "sha256-LSXmaDhbPw+3ww63Rx5ewBNWwCQIrzQvzphCFm5BRbU=", - "owner": "nix-community", - "repo": "fenix", - "rev": "41731c1a7ba1441c7544e8a0387aaf58e48f26b8", + "lastModified": 1663445644, + "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", + "owner": "numtide", + "repo": "devshell", + "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "fenix_5": { - "inputs": { - "nixpkgs": "nixpkgs_42", - "rust-analyzer-src": "rust-analyzer-src_5" - }, + "devshell_10": { "locked": { - "lastModified": 1645165506, - "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", - "owner": "nix-community", - "repo": "fenix", - "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", + "owner": "numtide", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "fenix_6": { + "devshell_11": { "inputs": { - "nixpkgs": [ + "flake-utils": [ "db-sync", "cardano-world", - "capsules", "bitte", - "nixpkgs-unstable" + "std", + "flake-utils" ], - "rust-analyzer-src": "rust-analyzer-src_6" + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1649226351, - "narHash": "sha256-5fQwF5kYpPC7w0SOfdbE9Z7o5/i/dyo1BxMLVCA2h3E=", - "owner": "nix-community", - "repo": "fenix", - "rev": "c7e184561fe843abb861cd7d22c23066987078e2", + "lastModified": 1658746384, + "narHash": "sha256-CCJcoMOcXyZFrV1ag4XMTpAPjLWb4Anbv+ktXFI1ry0=", + "owner": "numtide", + "repo": "devshell", + "rev": "0ffc7937bb5e8141af03d462b468bd071eb18e1b", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat": { - "flake": false, + "devshell_12": { + "inputs": { + "flake-utils": "flake-utils_30", + "nixpkgs": "nixpkgs_65" + }, "locked": { - "lastModified": 1647532380, - "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "7da118186435255a30b5ffeabba9629c344c0bec", + "lastModified": 1644227066, + "narHash": "sha256-FHcFZtpZEWnUh62xlyY3jfXAXHzJNEDLDzLsJxn+ve0=", + "owner": "numtide", + "repo": "devshell", + "rev": "7033f64dd9ef8d9d8644c5030c73913351d2b660", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "fixes", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_10": { - "flake": false, + "devshell_13": { "locked": { - "lastModified": 1647532380, - "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "7da118186435255a30b5ffeabba9629c344c0bec", + "lastModified": 1632436039, + "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", + "owner": "numtide", + "repo": "devshell", + "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "fixes", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_11": { - "flake": false, + "devshell_14": { "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", + "owner": "numtide", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_12": { - "flake": false, + "devshell_15": { "locked": { - "lastModified": 1672831974, - "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", + "owner": "numtide", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "hkm/gitlab-fix", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_13": { - "flake": false, + "devshell_16": { "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "lastModified": 1632436039, + "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", + "owner": "numtide", + "repo": "devshell", + "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_14": { - "flake": false, + "devshell_17": { "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", + "owner": "numtide", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_2": { - "flake": false, + "devshell_18": { "locked": { - "lastModified": 1672831974, - "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", + "lastModified": 1637098489, + "narHash": "sha256-IWBYLSNSENI/fTrXdYDhuCavxcgN9+RERrPM81f6DXY=", + "owner": "numtide", + "repo": "devshell", + "rev": "e8c2d4967b5c498b12551d1bb49352dcf9efa3e4", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "hkm/gitlab-fix", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_3": { - "flake": false, + "devshell_19": { + "inputs": { + "flake-utils": [ + "db-sync", + "cardano-world", + "std", + "flake-utils" + ], + "nixpkgs": [ + "db-sync", + "cardano-world", + "std", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1658746384, + "narHash": "sha256-CCJcoMOcXyZFrV1ag4XMTpAPjLWb4Anbv+ktXFI1ry0=", + "owner": "numtide", + "repo": "devshell", + "rev": "0ffc7937bb5e8141af03d462b468bd071eb18e1b", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_4": { - "flake": false, + "devshell_2": { + "inputs": { + "flake-utils": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "flake-utils" + ], + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", + "lastModified": 1663445644, + "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", + "owner": "numtide", + "repo": "devshell", + "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_5": { - "flake": false, - "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_6": { - "flake": false, - "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", - "type": "github" + "devshell_20": { + "inputs": { + "flake-utils": "flake-utils_46", + "nixpkgs": [ + "db-sync", + "cardano-world", + "tullia", + "std", + "nixpkgs" + ] }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_7": { - "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1650900878, + "narHash": "sha256-qhNncMBSa9STnhiLfELEQpYC1L4GrYHNIzyCZ/pilsI=", + "owner": "numtide", + "repo": "devshell", + "rev": "d97df53b5ddaa1cfbea7cddbd207eb2634304733", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_8": { - "flake": false, - "locked": { - "lastModified": 1635892615, - "narHash": "sha256-harGbMZr4hzat2BWBU+Y5OYXlu+fVz7E4WeQzHi5o8A=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "eca47d3377946315596da653862d341ee5341318", - "type": "github" + "devshell_3": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" + ], + "systems": "systems_2" }, - "original": { - "owner": "input-output-hk", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_9": { - "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1686680692, + "narHash": "sha256-SsLZz3TDleraAiJq4EkmdyewSyiv5g0LZYc6vaLZOMQ=", + "owner": "numtide", + "repo": "devshell", + "rev": "fd6223370774dd9c33354e87a007004b5fd36442", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-parts": { + "devshell_4": { "inputs": { - "nixpkgs": "nixpkgs_56" + "nixpkgs": [ + "cardano-nix", + "nixpkgs" + ], + "systems": "systems_3" }, "locked": { - "lastModified": 1655570068, - "narHash": "sha256-KUSd2a6KgYTHd2l3Goee/P+DrAC6n1Tau+7V68czSZU=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "6dbc77b9c0477f8a9a6a9081077bb38c6a3dbb3a", + "lastModified": 1695973661, + "narHash": "sha256-BP2H4c42GThPIhERtTpV1yCtwQHYHEKdRu7pjrmQAwo=", + "owner": "numtide", + "repo": "devshell", + "rev": "cd4e2fda3150dd2f689caeac07b7f47df5197c31", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-parts_2": { + "devshell_5": { "inputs": { - "nixpkgs-lib": [ - "hercules-ci-effects", + "flake-utils": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "flake-utils" + ], + "nixpkgs": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", "nixpkgs" ] }, "locked": { - "lastModified": 1696343447, - "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", - "type": "github" - }, - "original": { - "id": "flake-parts", - "type": "indirect" - } - }, - "flake-utils": { - "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "lastModified": 1663445644, + "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", "owner": "numtide", - "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "repo": "devshell", + "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", "type": "github" }, "original": { "owner": "numtide", - "repo": "flake-utils", + "repo": "devshell", "type": "github" } }, - "flake-utils_10": { + "devshell_6": { "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "lastModified": 1632436039, + "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "repo": "devshell", + "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", "type": "github" }, "original": { "owner": "numtide", - "repo": "flake-utils", + "repo": "devshell", "type": "github" } }, - "flake-utils_11": { + "devshell_7": { "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { "owner": "numtide", - "repo": "flake-utils", + "repo": "devshell", "type": "github" } }, - "flake-utils_12": { + "devshell_8": { "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "lastModified": 1637098489, + "narHash": "sha256-IWBYLSNSENI/fTrXdYDhuCavxcgN9+RERrPM81f6DXY=", "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "repo": "devshell", + "rev": "e8c2d4967b5c498b12551d1bb49352dcf9efa3e4", "type": "github" }, "original": { "owner": "numtide", - "repo": "flake-utils", + "repo": "devshell", "type": "github" } }, - "flake-utils_13": { + "devshell_9": { "locked": { - "lastModified": 1656928814, - "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", + "lastModified": 1632436039, + "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", "owner": "numtide", - "repo": "flake-utils", - "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", + "repo": "devshell", + "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", "type": "github" }, "original": { "owner": "numtide", - "repo": "flake-utils", + "repo": "devshell", "type": "github" } }, - "flake-utils_14": { + "dmerge": { + "inputs": { + "nixlib": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "nixpkgs" + ], + "yants": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1634851050, - "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "flake-utils_15": { + "dmerge_2": { + "inputs": { + "nixlib": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ], + "yants": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "flake-utils_16": { - "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_17": { + "dmerge_3": { + "inputs": { + "haumea": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "haumea" + ], + "nixlib": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "haumea", + "nixpkgs" + ], + "yants": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1610051610, - "narHash": "sha256-U9rPz/usA1/Aohhk7Cmc2gBrEEKRzcW4nwPWMPwja4Y=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3982c9903e93927c2164caa727cd3f6a0e6d14cc", + "lastModified": 1686862774, + "narHash": "sha256-ojGtRQ9pIOUrxsQEuEPerUkqIJEuod9hIflfNkY+9CE=", + "owner": "divnix", + "repo": "dmerge", + "rev": "9f7f7a8349d33d7bd02e0f2b484b1f076e503a96", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "ref": "0.2.1", + "repo": "dmerge", "type": "github" } }, - "flake-utils_18": { + "dmerge_4": { + "inputs": { + "nixlib": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ], + "yants": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "flake-utils_19": { + "dmerge_5": { + "inputs": { + "haumea": [ + "cardano-node", + "std", + "haumea" + ], + "nixlib": [ + "cardano-node", + "std", + "lib" + ], + "yants": [ + "cardano-node", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1686862774, + "narHash": "sha256-ojGtRQ9pIOUrxsQEuEPerUkqIJEuod9hIflfNkY+9CE=", + "owner": "divnix", + "repo": "dmerge", + "rev": "9f7f7a8349d33d7bd02e0f2b484b1f076e503a96", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "ref": "0.2.1", + "repo": "dmerge", "type": "github" } }, - "flake-utils_2": { + "dmerge_6": { + "inputs": { + "nixlib": [ + "db-sync", + "cardano-world", + "bitte", + "std", + "nixpkgs" + ], + "yants": [ + "db-sync", + "cardano-world", + "bitte", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1679360468, - "narHash": "sha256-LGnza3cfXF10Biw3ZTg0u9o9t7s680Ww200t5KkHTh8=", - "owner": "hamishmack", - "repo": "flake-utils", - "rev": "e1ea268ff47ad475443dbabcd54744b4e5b9d4f5", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "owner": "hamishmack", - "ref": "hkm/nested-hydraJobs", - "repo": "flake-utils", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "flake-utils_20": { + "dmerge_7": { + "inputs": { + "nixlib": [ + "db-sync", + "cardano-world", + "std", + "nixpkgs" + ], + "yants": [ + "db-sync", + "cardano-world", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1634851050, - "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "flake-utils_21": { + "driver": { + "inputs": { + "devshell": "devshell_13", + "inclusive": "inclusive_7", + "nix": "nix_12", + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "nixpkgs" + ], + "utils": "utils_18" + }, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1644418487, + "narHash": "sha256-nzFmmBYjNjWVy25bHLLmZECfwJm3nxcAr/mYVYxWggA=", + "owner": "input-output-hk", + "repo": "nomad-driver-nix", + "rev": "7f7adb6814b4bf926597e4b810b803140176122c", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "nomad-driver-nix", "type": "github" } }, - "flake-utils_22": { + "easy-purescript-nix": { + "flake": false, "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "lastModified": 1710161569, + "narHash": "sha256-lcIRIOFCdIWEGyKyG/tB4KvxM9zoWuBRDxW+T+mvIb0=", + "owner": "justinwoo", + "repo": "easy-purescript-nix", + "rev": "117fd96acb69d7d1727df95b6fde9d8715e031fc", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "justinwoo", + "repo": "easy-purescript-nix", "type": "github" } }, - "flake-utils_23": { + "em": { + "flake": false, "locked": { - "lastModified": 1619345332, - "narHash": "sha256-qHnQkEp1uklKTpx3MvKtY6xzgcqXDsz5nLilbbuL+3A=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "2ebf2558e5bf978c7fb8ea927dfaed8fefab2e28", + "lastModified": 1684791668, + "narHash": "sha256-JyPm0RiWCfy/8rs7wd/IRSWIz+bTkD78uxIMnKktU2g=", + "owner": "deepfire", + "repo": "em", + "rev": "302cdf6d654fb18baff0213bdfa41a653774585a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "deepfire", + "repo": "em", "type": "github" } }, - "flake-utils_24": { + "em_2": { + "flake": false, "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1684791668, + "narHash": "sha256-JyPm0RiWCfy/8rs7wd/IRSWIz+bTkD78uxIMnKktU2g=", + "owner": "deepfire", + "repo": "em", + "rev": "302cdf6d654fb18baff0213bdfa41a653774585a", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "deepfire", + "repo": "em", "type": "github" } }, - "flake-utils_25": { + "em_3": { + "flake": false, "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "lastModified": 1685015066, + "narHash": "sha256-etAdEoYhtvjTw1ITh28WPNfwvvb5t/fpwCP6s7odSiQ=", + "owner": "deepfire", + "repo": "em", + "rev": "af69bb5c2ac2161434d8fea45f920f8f359587ce", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "deepfire", + "repo": "em", "type": "github" } }, - "flake-utils_26": { + "ema": { + "inputs": { + "flake-compat": "flake-compat_20", + "flake-utils": "flake-utils_37", + "nixpkgs": "nixpkgs_83", + "pre-commit-hooks": "pre-commit-hooks" + }, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1646661767, + "narHash": "sha256-5zxUr3nO4r04K5WGrW/+nW84qbOW8wNJLt902yQmyF4=", + "owner": "srid", + "repo": "ema", + "rev": "bcabc170b7de9cdd83b4bbcf59130b54933602ea", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "srid", + "repo": "ema", "type": "github" } }, - "flake-utils_27": { + "ema_2": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1655231448, + "narHash": "sha256-LmAnOFKiqOWW9cQNZCbqFF0N1Mx073908voXz+4Fzic=", + "owner": "srid", + "repo": "ema", + "rev": "da5b29f03c1edfb7f947666a5a818fb97cc3c229", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "srid", + "ref": "multisite", + "repo": "ema", "type": "github" } }, - "flake-utils_28": { - "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", - "type": "github" + "emanote": { + "inputs": { + "ema": "ema_2", + "flake-parts": "flake-parts_6", + "haskell-flake": "haskell-flake", + "nixpkgs": "nixpkgs_86", + "tailwind-haskell": "tailwind-haskell" }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_29": { "locked": { - "lastModified": 1656928814, - "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", + "lastModified": 1655823900, + "narHash": "sha256-YEDJxa2gPf2+GGyrkFz4EliCml1FyDualZtbbZEmljA=", + "owner": "srid", + "repo": "emanote", + "rev": "147528d9df81b881214652ce0cefec0b3d52965e", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "srid", + "repo": "emanote", "type": "github" } }, - "flake-utils_3": { + "empty-flake": { "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "flake-utils_30": { + "empty-flake_2": { "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "flake-utils_31": { + "empty-flake_3": { "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "flake-utils_32": { + "empty-flake_4": { "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "flake-utils_33": { + "fenix": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "auth-keys-hub", + "statix", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1645251813, + "narHash": "sha256-cQ66tGjnZclBCS3nD26mZ5fUH+3/HnysGffBiWXUSHk=", + "owner": "nix-community", + "repo": "fenix", + "rev": "9892337b588c38ec59466a1c89befce464aae7f8", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_4": { + "fenix_2": { + "inputs": { + "nixpkgs": "nixpkgs_30", + "rust-analyzer-src": "rust-analyzer-src_2" + }, "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "lastModified": 1677306201, + "narHash": "sha256-VZ9x7qdTosFvVsrpgFHrtYfT6PU3yMIs7NRYn9ELapI=", + "owner": "nix-community", + "repo": "fenix", + "rev": "0923f0c162f65ae40261ec940406049726cfeab4", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_5": { + "fenix_3": { + "inputs": { + "nixpkgs": "nixpkgs_42", + "rust-analyzer-src": "rust-analyzer-src_3" + }, "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "lastModified": 1645165506, + "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", + "owner": "nix-community", + "repo": "fenix", + "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_6": { + "fenix_4": { + "inputs": { + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte", + "capsules", + "bitte", + "nixpkgs-unstable" + ], + "rust-analyzer-src": "rust-analyzer-src_4" + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1649226351, + "narHash": "sha256-5fQwF5kYpPC7w0SOfdbE9Z7o5/i/dyo1BxMLVCA2h3E=", + "owner": "nix-community", + "repo": "fenix", + "rev": "c7e184561fe843abb861cd7d22c23066987078e2", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_7": { + "fenix_5": { + "inputs": { + "nixpkgs": "nixpkgs_55", + "rust-analyzer-src": "rust-analyzer-src_5" + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1645165506, + "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", + "owner": "nix-community", + "repo": "fenix", + "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_8": { + "fenix_6": { + "inputs": { + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte", + "nixpkgs-unstable" + ], + "rust-analyzer-src": "rust-analyzer-src_6" + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1660631227, + "narHash": "sha256-LSXmaDhbPw+3ww63Rx5ewBNWwCQIrzQvzphCFm5BRbU=", + "owner": "nix-community", + "repo": "fenix", + "rev": "41731c1a7ba1441c7544e8a0387aaf58e48f26b8", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_9": { + "fenix_7": { + "inputs": { + "nixpkgs": "nixpkgs_71", + "rust-analyzer-src": "rust-analyzer-src_7" + }, "locked": { - "lastModified": 1634851050, - "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "lastModified": 1645165506, + "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", + "owner": "nix-community", + "repo": "fenix", + "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flakeCompat": { - "flake": false, - "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "follower": { + "fenix_8": { "inputs": { - "devshell": "devshell_10", - "inclusive": "inclusive_7", "nixpkgs": [ "db-sync", "cardano-world", - "bitte-cells", - "cicero", - "nixpkgs" + "capsules", + "bitte", + "nixpkgs-unstable" ], - "utils": "utils_14" + "rust-analyzer-src": "rust-analyzer-src_8" }, "locked": { - "lastModified": 1642008295, - "narHash": "sha256-yx3lLN/hlvEeKItHJ5jH0KSm84IruTWMo78IItVPji4=", - "owner": "input-output-hk", - "repo": "nomad-follower", - "rev": "b1b0b00e940026f72d16bdf13e36ad20f1826e8a", + "lastModified": 1649226351, + "narHash": "sha256-5fQwF5kYpPC7w0SOfdbE9Z7o5/i/dyo1BxMLVCA2h3E=", + "owner": "nix-community", + "repo": "fenix", + "rev": "c7e184561fe843abb861cd7d22c23066987078e2", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nomad-follower", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "ghc-8.6.5-iohk": { + "flake-compat": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", - "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_2": { + "flake-compat_10": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_3": { + "flake-compat_11": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_4": { + "flake-compat_12": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", - "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_5": { + "flake-compat_13": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", - "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_6": { + "flake-compat_14": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", - "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_7": { + "flake-compat_15": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "ghc98X": { + "flake-compat_16": { "flake": false, "locked": { - "lastModified": 1696643148, - "narHash": "sha256-E02DfgISH7EvvNAu0BHiPvl1E5FGMDi0pWdNZtIBC9I=", - "ref": "ghc-9.8", - "rev": "443e870d977b1ab6fc05f47a9a17bc49296adbd6", - "revCount": 61642, - "submodules": true, - "type": "git", - "url": "https://gitlab.haskell.org/ghc/ghc" + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", + "owner": "input-output-hk", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", + "type": "github" }, "original": { - "ref": "ghc-9.8", - "submodules": true, - "type": "git", - "url": "https://gitlab.haskell.org/ghc/ghc" + "owner": "input-output-hk", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", + "type": "github" } }, - "ghc99": { + "flake-compat_17": { "flake": false, "locked": { - "lastModified": 1701580282, - "narHash": "sha256-drA01r3JrXnkKyzI+owMZGxX0JameMzjK0W5jJE/+V4=", - "ref": "refs/heads/master", - "rev": "f5eb0f2982e9cf27515e892c4bdf634bcfb28459", - "revCount": 62197, - "submodules": true, - "type": "git", - "url": "https://gitlab.haskell.org/ghc/ghc" + "lastModified": 1627913399, + "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", + "type": "github" }, "original": { - "submodules": true, - "type": "git", - "url": "https://gitlab.haskell.org/ghc/ghc" + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" } }, - "gomod2nix": { - "inputs": { - "nixpkgs": "nixpkgs_5", - "utils": "utils" - }, + "flake-compat_18": { + "flake": false, "locked": { - "lastModified": 1655245309, - "narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=", - "owner": "tweag", - "repo": "gomod2nix", - "rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58", + "lastModified": 1627913399, + "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", "type": "github" }, "original": { - "owner": "tweag", - "repo": "gomod2nix", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "hackage": { + "flake-compat_19": { "flake": false, "locked": { - "lastModified": 1646097829, - "narHash": "sha256-PcHDDV8NuUxZhPV/p++IkZC+SDZ1Db7m7K+9HN4/0S4=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "283f096976b48e54183905e7bdde7f213c6ee5cd", + "lastModified": 1627913399, + "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "hackage-nix": { + "flake-compat_2": { "flake": false, "locked": { - "lastModified": 1702772694, - "narHash": "sha256-KL6ZjbhPBCco1ho0lmh0/dfPSNxjF8qtrTlzQcTN3iw=", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "20bd4b5f667f892230d4a28ea4607e85ce9bc44e", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "hackage.nix", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "hackageNix": { + "flake-compat_20": { "flake": false, "locked": { - "lastModified": 1685492843, - "narHash": "sha256-X8dNs5Gfc2ucfaWAgZ1VmkpBB4Cb44EQZu0b7tkvz2Y=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "e7407bab324eb2445bda58c5ffac393e80dda1e4", + "lastModified": 1641205782, + "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "hackage_2": { + "flake-compat_21": { "flake": false, "locked": { - "lastModified": 1655342080, - "narHash": "sha256-mF/clPxSJJkKAq6Y+0oYXrU3rGOuQXFN9btSde3uvvE=", + "lastModified": 1635892615, + "narHash": "sha256-harGbMZr4hzat2BWBU+Y5OYXlu+fVz7E4WeQzHi5o8A=", "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "567e2e865d42d8e5cfe796bf03b6b38e42bc00ab", + "repo": "flake-compat", + "rev": "eca47d3377946315596da653862d341ee5341318", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "hackage.nix", + "repo": "flake-compat", "type": "github" } }, - "hackage_3": { + "flake-compat_22": { "flake": false, "locked": { - "lastModified": 1659489414, - "narHash": "sha256-AghgUkUv0hIBh+PvODngYL+ejwhCn2O2OUkVaAZYkCU=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "056c6ce7014adaf887b8e4cad15ef6fd926ea568", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "hackage_4": { + "flake-compat_23": { "flake": false, "locked": { - "lastModified": 1650935983, - "narHash": "sha256-wZTCKzA4f7nk5sIdP2BhGz5qkt6ex5VTC/53U2Y4i9Y=", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "b65addc81b03406b3ee8b139549980591ed15be5", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "hackage.nix", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "hackage_5": { + "flake-compat_24": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_25": { "flake": false, "locked": { - "lastModified": 1654219082, - "narHash": "sha256-sm59eg5wSrfIAjNXfBaaOBQ8daghF3g1NiGazYfj+no=", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "fc90e7c5dea0483bacb01fc00bd2ab8f8e72500d", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "hackage.nix", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "haskell-flake": { + "flake-compat_3": { + "flake": false, "locked": { - "lastModified": 1654001497, - "narHash": "sha256-GfrpyoQrVT9Z/j9its8BQs3I5O5X5Lc2IkK922bz7zg=", - "owner": "srid", - "repo": "haskell-flake", - "rev": "4c0b0ff295f0b97238a600d2381c37ee46b67f9c", + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "type": "github" }, "original": { - "owner": "srid", - "repo": "haskell-flake", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "haskell-nix": { - "inputs": { - "HTTP": "HTTP_2", - "cabal-32": "cabal-32_2", - "cabal-34": "cabal-34_2", - "cabal-36": "cabal-36_2", - "cardano-shell": "cardano-shell_2", - "flake-utils": "flake-utils_16", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_2", - "hackage": "hackage", - "hpc-coveralls": "hpc-coveralls_2", - "nix-tools": "nix-tools", - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "haskell-nix", - "nixpkgs-unstable" - ], - "nixpkgs-2003": "nixpkgs-2003_2", - "nixpkgs-2105": "nixpkgs-2105_2", - "nixpkgs-2111": "nixpkgs-2111_2", - "nixpkgs-unstable": [ - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "nixpkgs" - ], - "old-ghc-nix": "old-ghc-nix_2", - "stackage": "stackage_2" - }, + "flake-compat_4": { + "flake": false, "locked": { - "lastModified": 1646097976, - "narHash": "sha256-EiyrBqayw67dw8pr1XCVU9tIZ+/jzXCQycW1S9a+KFA=", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "f0308ed1df3ce9f10f9da1a7c0c8591921d0b4e5", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "haskell.nix", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "haskell-nix_2": { - "inputs": { - "HTTP": "HTTP_4", - "cabal-32": "cabal-32_4", - "cabal-34": "cabal-34_4", - "cabal-36": "cabal-36_4", - "cardano-shell": "cardano-shell_4", - "flake-utils": "flake-utils_27", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_4", - "hackage": [ - "db-sync", - "cardano-world", - "hackage" - ], - "hpc-coveralls": "hpc-coveralls_4", - "hydra": "hydra_6", - "nix-tools": "nix-tools_3", - "nixpkgs": [ - "db-sync", - "cardano-world", - "haskell-nix", - "nixpkgs-unstable" - ], - "nixpkgs-2003": "nixpkgs-2003_4", - "nixpkgs-2105": "nixpkgs-2105_4", - "nixpkgs-2111": "nixpkgs-2111_4", - "nixpkgs-2205": "nixpkgs-2205_2", - "nixpkgs-unstable": "nixpkgs-unstable_6", - "old-ghc-nix": "old-ghc-nix_4", - "stackage": "stackage_4" - }, + "flake-compat_5": { + "flake": false, "locked": { - "lastModified": 1659439444, - "narHash": "sha256-qUK7OVpM8/piOImpPgzSUvOFHQq19sQpvOSns2nW8es=", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "ee6a6559e16a603677d7cbef7c4fe18ca801b48e", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "haskell.nix", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "haskell-nix_3": { - "inputs": { - "HTTP": "HTTP_6", - "cabal-32": "cabal-32_6", - "cabal-34": "cabal-34_6", - "cabal-36": "cabal-36_6", - "cardano-shell": "cardano-shell_6", - "flake-compat": "flake-compat_12", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_6", - "ghc98X": "ghc98X", - "ghc99": "ghc99", - "hackage": [ - "hackage-nix" - ], - "hls-1.10": "hls-1.10_2", - "hls-2.0": "hls-2.0", - "hls-2.2": "hls-2.2", - "hls-2.3": "hls-2.3", - "hls-2.4": "hls-2.4", - "hpc-coveralls": "hpc-coveralls_6", - "hydra": "hydra_8", - "iserv-proxy": "iserv-proxy_2", - "nixpkgs": [ - "nixpkgs" - ], - "nixpkgs-2003": "nixpkgs-2003_6", - "nixpkgs-2105": "nixpkgs-2105_6", - "nixpkgs-2111": "nixpkgs-2111_6", - "nixpkgs-2205": "nixpkgs-2205_3", - "nixpkgs-2211": "nixpkgs-2211_2", - "nixpkgs-2305": "nixpkgs-2305", - "nixpkgs-2311": "nixpkgs-2311", - "nixpkgs-unstable": "nixpkgs-unstable_8", - "old-ghc-nix": "old-ghc-nix_6", - "stackage": "stackage_6" - }, + "flake-compat_6": { + "flake": false, "locked": { - "lastModified": 1702774226, - "narHash": "sha256-QUQBV05VimFU0pasJlialCcL/jlCumzaTmCM9+6Ncpk=", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "6ce1c8ab2a6d4af5721b22bd95968439b8c3c307", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "haskell.nix", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "haskell-nix_4": { - "inputs": { - "HTTP": "HTTP_7", - "cabal-32": "cabal-32_7", - "cabal-34": "cabal-34_7", - "cabal-36": "cabal-36_7", - "cardano-shell": "cardano-shell_7", - "flake-utils": "flake-utils_33", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_7", - "hackage": "hackage_5", - "hpc-coveralls": "hpc-coveralls_7", - "hydra": "hydra_9", - "nix-tools": "nix-tools_5", - "nixpkgs": [ - "kupo-nixos", - "haskell-nix", - "nixpkgs-unstable" - ], - "nixpkgs-2003": "nixpkgs-2003_7", - "nixpkgs-2105": "nixpkgs-2105_7", - "nixpkgs-2111": "nixpkgs-2111_7", - "nixpkgs-unstable": "nixpkgs-unstable_9", - "old-ghc-nix": "old-ghc-nix_7", - "stackage": "stackage_7" - }, + "flake-compat_7": { + "flake": false, "locked": { - "lastModified": 1654219238, - "narHash": "sha256-PMS7uSQjYCjsjUfVidTdKcuNtKNu5VPmeNvxruT72go=", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "974a61451bb1d41b32090eb51efd7ada026d16d9", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "974a61451bb1d41b32090eb51efd7ada026d16d9", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "haskellNix": { - "inputs": { - "HTTP": "HTTP", - "cabal-32": "cabal-32", - "cabal-34": "cabal-34", - "cabal-36": "cabal-36", - "cardano-shell": "cardano-shell", - "flake-compat": "flake-compat_2", - "flake-utils": "flake-utils_2", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", - "hackage": [ - "cardano-node", - "hackageNix" - ], - "hls-1.10": "hls-1.10", - "hpc-coveralls": "hpc-coveralls", - "hydra": "hydra", - "iserv-proxy": "iserv-proxy", - "nixpkgs": [ - "cardano-node", - "nixpkgs" - ], - "nixpkgs-2003": "nixpkgs-2003", - "nixpkgs-2105": "nixpkgs-2105", - "nixpkgs-2111": "nixpkgs-2111", - "nixpkgs-2205": "nixpkgs-2205", - "nixpkgs-2211": "nixpkgs-2211", - "nixpkgs-unstable": "nixpkgs-unstable", - "old-ghc-nix": "old-ghc-nix", - "stackage": "stackage" - }, + "flake-compat_8": { + "flake": false, "locked": { - "lastModified": 1685495397, - "narHash": "sha256-BwbWroS1Qm8BiHatG5+iHMHN5U6kqOccewBROUYuMKw=", - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "d07c42cdb1cf88d0cab27d3090b00cb3899643c9", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "haskell.nix", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "haskellNix_2": { - "inputs": { - "HTTP": "HTTP_3", - "cabal-32": "cabal-32_3", - "cabal-34": "cabal-34_3", - "cabal-36": "cabal-36_3", - "cardano-shell": "cardano-shell_3", - "flake-utils": "flake-utils_26", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_3", - "hackage": "hackage_2", - "hpc-coveralls": "hpc-coveralls_3", - "hydra": "hydra_5", - "nix-tools": "nix-tools_2", - "nixpkgs": [ - "db-sync", - "cardano-world", - "cardano-wallet", - "nixpkgs" - ], - "nixpkgs-2003": "nixpkgs-2003_3", - "nixpkgs-2105": "nixpkgs-2105_3", - "nixpkgs-2111": "nixpkgs-2111_3", - "nixpkgs-unstable": "nixpkgs-unstable_5", - "old-ghc-nix": "old-ghc-nix_3", - "stackage": "stackage_3" - }, + "flake-compat_9": { + "flake": false, "locked": { - "lastModified": 1655369909, - "narHash": "sha256-Z3d17WvaXY2kWdfsOE6yPKViQ1RBfGi4d7XZgXA/j2I=", - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "5a310b0b3904d9b90239390eb2dfb59e4dcb0d96", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "haskell.nix", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "haskellNix_3": { + "flake-parts": { "inputs": { - "HTTP": "HTTP_5", - "cabal-32": "cabal-32_5", - "cabal-34": "cabal-34_5", - "cabal-36": "cabal-36_5", - "cardano-shell": "cardano-shell_5", - "flake-utils": "flake-utils_32", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_5", - "hackage": "hackage_4", - "hpc-coveralls": "hpc-coveralls_5", - "hydra": "hydra_7", - "nix-tools": "nix-tools_4", - "nixpkgs": [ - "db-sync", - "haskellNix", - "nixpkgs-unstable" - ], - "nixpkgs-2003": "nixpkgs-2003_5", - "nixpkgs-2105": "nixpkgs-2105_5", - "nixpkgs-2111": "nixpkgs-2111_5", - "nixpkgs-unstable": "nixpkgs-unstable_7", - "old-ghc-nix": "old-ghc-nix_5", - "stackage": "stackage_5" + "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1650936156, - "narHash": "sha256-B58b4OCSc6ohRjGEdbQ78r+TK/OZYsBXION90kfQDC4=", - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "9a502b8c8aac4d7b8033bc9affb87fd03d4740fc", + "lastModified": 1672152762, + "narHash": "sha256-U8iWWHgabN07zfbgedogMVWrEP1Zywyf3Yx3OYHSSgE=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "19e0f88324d90509141e192664ded98bb88ef9b2", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "haskell.nix", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "hercules-ci-effects": { + "flake-parts_2": { "inputs": { - "flake-parts": "flake-parts_2", - "nixpkgs": "nixpkgs_70" + "nixpkgs-lib": "nixpkgs-lib_2" }, "locked": { - "lastModified": 1701009247, - "narHash": "sha256-GuX16rzRze2y7CsewJLTV6qXkXWyEwp6VCZXi8HLruU=", + "lastModified": 1682984683, + "narHash": "sha256-fSMthG+tp60AHhNmaHc4StT3ltfHkQsJtN8GhfLWmtI=", "owner": "hercules-ci", - "repo": "hercules-ci-effects", - "rev": "31b6cd7569191bfcd0a548575b0e2ef953ed7d09", + "repo": "flake-parts", + "rev": "86684881e184f41aa322e653880e497b66429f3e", "type": "github" }, "original": { "owner": "hercules-ci", - "repo": "hercules-ci-effects", + "repo": "flake-parts", "type": "github" } }, - "hls-1.10": { - "flake": false, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_3" + }, "locked": { - "lastModified": 1680000865, - "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "lastModified": 1690933134, + "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.10.0.0", - "repo": "haskell-language-server", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "hls-1.10_2": { - "flake": false, + "flake-parts_4": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_4" + }, "locked": { - "lastModified": 1680000865, - "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "lastModified": 1690933134, + "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.10.0.0", - "repo": "haskell-language-server", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "hls-2.0": { - "flake": false, + "flake-parts_5": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_5" + }, "locked": { - "lastModified": 1687698105, - "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "783905f211ac63edf982dd1889c671653327e441", + "lastModified": 1696343447, + "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", "type": "github" }, "original": { - "owner": "haskell", - "ref": "2.0.0.1", - "repo": "haskell-language-server", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "hls-2.2": { - "flake": false, + "flake-parts_6": { + "inputs": { + "nixpkgs": "nixpkgs_85" + }, "locked": { - "lastModified": 1693064058, - "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "lastModified": 1655570068, + "narHash": "sha256-KUSd2a6KgYTHd2l3Goee/P+DrAC6n1Tau+7V68czSZU=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "6dbc77b9c0477f8a9a6a9081077bb38c6a3dbb3a", "type": "github" }, "original": { - "owner": "haskell", - "ref": "2.2.0.0", - "repo": "haskell-language-server", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "hls-2.3": { - "flake": false, + "flake-parts_7": { + "inputs": { + "nixpkgs-lib": [ + "hercules-ci-effects", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1695910642, - "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", "type": "github" }, "original": { - "owner": "haskell", - "ref": "2.3.0.0", - "repo": "haskell-language-server", - "type": "github" + "id": "flake-parts", + "type": "indirect" } }, - "hls-2.4": { - "flake": false, + "flake-root": { "locked": { - "lastModified": 1696939266, - "narHash": "sha256-VOMf5+kyOeOmfXTHlv4LNFJuDGa7G3pDnOxtzYR40IU=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "362fdd1293efb4b82410b676ab1273479f6d17ee", + "lastModified": 1692742795, + "narHash": "sha256-f+Y0YhVCIJ06LemO+3Xx00lIcqQxSKJHXT/yk1RTKxw=", + "owner": "srid", + "repo": "flake-root", + "rev": "d9a70d9c7a5fd7f3258ccf48da9335e9b47c3937", "type": "github" }, "original": { - "owner": "haskell", - "ref": "2.4.0.0", - "repo": "haskell-language-server", + "owner": "srid", + "repo": "flake-root", "type": "github" } }, - "hpc-coveralls": { - "flake": false, + "flake-utils": { "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hpc-coveralls_2": { - "flake": false, + "flake-utils_10": { "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hpc-coveralls_3": { - "flake": false, + "flake-utils_11": { "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hpc-coveralls_4": { - "flake": false, + "flake-utils_12": { "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hpc-coveralls_5": { - "flake": false, + "flake-utils_13": { "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hpc-coveralls_6": { - "flake": false, + "flake-utils_14": { "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hpc-coveralls_7": { - "flake": false, + "flake-utils_15": { + "inputs": { + "systems": "systems_4" + }, "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hydra": { - "inputs": { - "nix": "nix", - "nixpkgs": [ - "cardano-node", - "haskellNix", - "hydra", - "nix", - "nixpkgs" - ] - }, + "flake-utils_16": { "locked": { - "lastModified": 1671755331, - "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", - "owner": "NixOS", - "repo": "hydra", - "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "numtide", + "repo": "flake-utils", + "type": "github" } }, - "hydra_2": { - "inputs": { - "nix": [ - "db-sync", - "cardano-world", - "bitte", - "capsules", - "bitte", - "nix" - ], - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte", - "capsules", - "bitte", - "nixpkgs" - ] - }, + "flake-utils_17": { "locked": { - "lastModified": 1631062883, - "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", - "owner": "kreisys", - "repo": "hydra", - "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "hydra-server-includes", - "repo": "hydra", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hydra_3": { - "inputs": { - "nix": [ - "db-sync", - "cardano-world", - "bitte", - "nix" - ], - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte", - "nixpkgs" - ] - }, + "flake-utils_18": { "locked": { - "lastModified": 1631062883, - "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", - "owner": "kreisys", - "repo": "hydra", - "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "hydra-server-includes", - "repo": "hydra", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hydra_4": { - "inputs": { - "nix": [ - "db-sync", - "cardano-world", - "capsules", - "bitte", - "nix" - ], - "nixpkgs": [ - "db-sync", - "cardano-world", - "capsules", - "bitte", - "nixpkgs" - ] - }, + "flake-utils_19": { "locked": { - "lastModified": 1631062883, - "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", - "owner": "kreisys", - "repo": "hydra", - "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "hydra-server-includes", - "repo": "hydra", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "hydra_5": { - "inputs": { - "nix": "nix_12", - "nixpkgs": [ - "db-sync", - "cardano-world", - "cardano-wallet", - "haskellNix", - "hydra", - "nix", - "nixpkgs" - ] - }, + "flake-utils_2": { "locked": { - "lastModified": 1646878427, - "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", - "owner": "NixOS", - "repo": "hydra", - "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "lastModified": 1679360468, + "narHash": "sha256-LGnza3cfXF10Biw3ZTg0u9o9t7s680Ww200t5KkHTh8=", + "owner": "hamishmack", + "repo": "flake-utils", + "rev": "e1ea268ff47ad475443dbabcd54744b4e5b9d4f5", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "hamishmack", + "ref": "hkm/nested-hydraJobs", + "repo": "flake-utils", + "type": "github" } }, - "hydra_6": { + "flake-utils_20": { "inputs": { - "nix": "nix_13", - "nixpkgs": [ - "db-sync", - "cardano-world", - "haskell-nix", - "hydra", - "nix", - "nixpkgs" - ] + "systems": "systems_5" }, "locked": { - "lastModified": 1646878427, - "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", - "owner": "NixOS", - "repo": "hydra", - "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" - } - }, - "hydra_7": { - "inputs": { - "nix": "nix_14", - "nixpkgs": [ - "db-sync", - "haskellNix", - "hydra", - "nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1646878427, - "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", - "owner": "NixOS", - "repo": "hydra", - "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "owner": "numtide", + "repo": "flake-utils", "type": "github" - }, - "original": { - "id": "hydra", - "type": "indirect" } }, - "hydra_8": { - "inputs": { - "nix": "nix_15", - "nixpkgs": [ - "haskell-nix", - "hydra", - "nix", - "nixpkgs" - ] - }, + "flake-utils_21": { "locked": { - "lastModified": 1671755331, - "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", - "owner": "NixOS", - "repo": "hydra", - "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "numtide", + "repo": "flake-utils", + "type": "github" } }, - "hydra_9": { - "inputs": { - "nix": "nix_16", - "nixpkgs": [ - "kupo-nixos", - "haskell-nix", - "hydra", - "nix", - "nixpkgs" - ] - }, + "flake-utils_22": { "locked": { - "lastModified": 1646878427, - "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", - "owner": "NixOS", - "repo": "hydra", - "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "numtide", + "repo": "flake-utils", + "type": "github" } }, - "incl": { - "inputs": { - "nixlib": [ - "cardano-node", - "tullia", - "std", - "nixpkgs" - ] - }, + "flake-utils_23": { "locked": { - "lastModified": 1669263024, - "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", - "owner": "divnix", - "repo": "incl", - "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "owner": "divnix", - "repo": "incl", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive": { - "inputs": { - "stdlib": "stdlib" - }, + "flake-utils_24": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_10": { - "inputs": { - "stdlib": "stdlib_10" - }, + "flake-utils_25": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_11": { - "inputs": { - "stdlib": "stdlib_11" - }, + "flake-utils_26": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_2": { - "inputs": { - "stdlib": "stdlib_2" - }, + "flake-utils_27": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_3": { - "inputs": { - "stdlib": "stdlib_3" - }, + "flake-utils_28": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1656928814, + "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_4": { - "inputs": { - "stdlib": "stdlib_4" - }, + "flake-utils_29": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_5": { - "inputs": { - "stdlib": "stdlib_5" - }, + "flake-utils_3": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_6": { - "inputs": { - "stdlib": "stdlib_6" - }, + "flake-utils_30": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1642700792, + "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_7": { - "inputs": { - "stdlib": "stdlib_7" - }, + "flake-utils_31": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_8": { - "inputs": { - "stdlib": "stdlib_8" - }, + "flake-utils_32": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1610051610, + "narHash": "sha256-U9rPz/usA1/Aohhk7Cmc2gBrEEKRzcW4nwPWMPwja4Y=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3982c9903e93927c2164caa727cd3f6a0e6d14cc", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "inclusive_9": { - "inputs": { - "stdlib": "stdlib_9" - }, + "flake-utils_33": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "iogo": { - "inputs": { - "devshell": "devshell_4", - "inclusive": "inclusive_3", - "nixpkgs": "nixpkgs_22", - "utils": "utils_8" - }, + "flake-utils_34": { "locked": { - "lastModified": 1652212694, - "narHash": "sha256-baAY5wKzccNsm7OCEYuySrkXRmlshokCHQjs4EdYShM=", - "owner": "input-output-hk", - "repo": "bitte-iogo", - "rev": "e465975aa368b2d919e865f71eeed02828e55471", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "bitte-iogo", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "iogo_2": { - "inputs": { - "devshell": "devshell_14", - "inclusive": "inclusive_11", - "nixpkgs": "nixpkgs_51", - "utils": "utils_22" - }, + "flake-utils_35": { "locked": { - "lastModified": 1658302707, - "narHash": "sha256-E0FA1CEMQlfAsmtLBRoQE7IY4ItKlBdxZ44YX0tK5Hg=", - "owner": "input-output-hk", - "repo": "bitte-iogo", - "rev": "8751660009202bc95ea3a29e304c393c140a4231", + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "bitte-iogo", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "iohk-nix": { - "inputs": { - "nixpkgs": [ - "db-sync", - "cardano-world", - "nixpkgs" - ] - }, + "flake-utils_36": { "locked": { - "lastModified": 1658222743, - "narHash": "sha256-yFH01psqx30y5Ws4dBElLkxYpIxxqZx4G+jCVhsXpnA=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "9a604d01bd4420ab7f396f14d1947fbe2ce7db8b", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "iohk-nix_2": { - "inputs": { - "blst": "blst_2", - "nixpkgs": [ - "nixpkgs" - ], - "secp256k1": "secp256k1_2", - "sodium": "sodium_2" - }, + "flake-utils_37": { "locked": { - "lastModified": 1702362799, - "narHash": "sha256-cU8cZXNuo5GRwrSvWqdaqoW5tJ2HWwDEOvWwIVPDPmo=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "b426fb9e0b109a9d1dd2e1476f9e0bd8bb715142", + "lastModified": 1642700792, + "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "iohk-nix_3": { - "inputs": { - "nixpkgs": [ - "kupo-nixos", - "haskell-nix", - "nixpkgs" - ] - }, + "flake-utils_38": { "locked": { - "lastModified": 1653579289, - "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", + "lastModified": 1619345332, + "narHash": "sha256-qHnQkEp1uklKTpx3MvKtY6xzgcqXDsz5nLilbbuL+3A=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "2ebf2558e5bf978c7fb8ea927dfaed8fefab2e28", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "iohkNix": { - "inputs": { - "blst": "blst", - "nixpkgs": [ - "cardano-node", - "nixpkgs" - ], - "secp256k1": "secp256k1", - "sodium": "sodium" - }, + "flake-utils_39": { "locked": { - "lastModified": 1684223806, - "narHash": "sha256-IyLoP+zhuyygLtr83XXsrvKyqqLQ8FHXTiySFf4FJOI=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "86421fdd89b3af43fa716ccd07638f96c6ecd1e4", + "lastModified": 1652776076, + "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "numtide", + "ref": "v1.0.0", + "repo": "flake-utils", "type": "github" } }, - "iohkNix_2": { - "inputs": { - "nixpkgs": [ - "db-sync", - "cardano-world", - "cardano-wallet", - "nixpkgs" - ] - }, + "flake-utils_4": { "locked": { - "lastModified": 1653579289, - "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "iohkNix_3": { - "inputs": { - "nixpkgs": [ - "db-sync", - "nixpkgs" - ] - }, + "flake-utils_40": { "locked": { - "lastModified": 1667394105, - "narHash": "sha256-YhS7zGd6jK/QM/+wWyj0zUBZmE3HOXAL/kpJptGYIWg=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "7fc7625a9ab2ba137bc70ddbc89a13d3fdb78c8b", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "iserv-proxy": { - "flake": false, + "flake-utils_41": { "locked": { - "lastModified": 1670983692, - "narHash": "sha256-avLo34JnI9HNyOuauK5R69usJm+GfW3MlyGlYxZhTgY=", - "ref": "hkm/remote-iserv", - "rev": "50d0abb3317ac439a4e7495b185a64af9b7b9300", - "revCount": 10, - "type": "git", - "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" }, "original": { - "ref": "hkm/remote-iserv", - "type": "git", - "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + "owner": "numtide", + "repo": "flake-utils", + "type": "github" } }, - "iserv-proxy_2": { - "flake": false, + "flake-utils_42": { "locked": { - "lastModified": 1691634696, - "narHash": "sha256-MZH2NznKC/gbgBu8NgIibtSUZeJ00HTLJ0PlWKCBHb0=", - "ref": "hkm/remote-iserv", - "rev": "43a979272d9addc29fbffc2e8542c5d96e993d73", - "revCount": 14, - "type": "git", - "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" }, "original": { - "ref": "hkm/remote-iserv", - "type": "git", - "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + "owner": "numtide", + "repo": "flake-utils", + "type": "github" } }, - "kupo": { - "flake": false, + "flake-utils_43": { "locked": { - "lastModified": 1668678914, - "narHash": "sha256-XsbAFyUPmevGuoShEFlOVHt/7fFIpyCQuhulIrNzv80=", - "owner": "CardanoSolutions", - "repo": "kupo", - "rev": "c9bc18d99f9e8af1840a265907db82b180d5a4d8", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "CardanoSolutions", - "ref": "v2.2.0", - "repo": "kupo", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "kupo-nixos": { - "inputs": { - "haskell-nix": "haskell-nix_4", - "iohk-nix": "iohk-nix_3", - "kupo": [ - "kupo" - ], - "nixpkgs": [ - "kupo-nixos", - "haskell-nix", - "nixpkgs" - ] - }, + "flake-utils_44": { "locked": { - "lastModified": 1672905539, - "narHash": "sha256-B4vryG94L7WWn/tuIQdtg9eZHAH+FaFzv35Mancd2l8=", - "owner": "mlabs-haskell", - "repo": "kupo-nixos", - "rev": "6f89cbcc359893a2aea14dd380f9a45e04c6aa67", + "lastModified": 1656928814, + "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "kupo-nixos", - "rev": "6f89cbcc359893a2aea14dd380f9a45e04c6aa67", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "lowdown-src": { - "flake": false, + "flake-utils_45": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "lowdown-src_10": { - "flake": false, + "flake-utils_46": { "locked": { - "lastModified": 1598695561, - "narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f", + "lastModified": 1642700792, + "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "lowdown-src_11": { - "flake": false, + "flake-utils_47": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "lowdown-src_12": { - "flake": false, + "flake-utils_5": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1679360468, + "narHash": "sha256-LGnza3cfXF10Biw3ZTg0u9o9t7s680Ww200t5KkHTh8=", + "owner": "hamishmack", + "repo": "flake-utils", + "rev": "e1ea268ff47ad475443dbabcd54744b4e5b9d4f5", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "hamishmack", + "ref": "hkm/nested-hydraJobs", + "repo": "flake-utils", "type": "github" } }, - "lowdown-src_13": { - "flake": false, + "flake-utils_6": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "lowdown-src_14": { - "flake": false, + "flake-utils_7": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "lowdown-src_15": { - "flake": false, + "flake-utils_8": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "lowdown-src_16": { - "flake": false, + "flake-utils_9": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "lowdown-src_2": { + "flakeCompat": { "flake": false, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1641205782, + "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "lowdown-src_3": { - "flake": false, + "follower": { + "inputs": { + "devshell": "devshell_14", + "inclusive": "inclusive_8", + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "nixpkgs" + ], + "utils": "utils_19" + }, "locked": { - "lastModified": 1598695561, - "narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f", + "lastModified": 1642008295, + "narHash": "sha256-yx3lLN/hlvEeKItHJ5jH0KSm84IruTWMo78IItVPji4=", + "owner": "input-output-hk", + "repo": "nomad-follower", + "rev": "b1b0b00e940026f72d16bdf13e36ad20f1826e8a", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "input-output-hk", + "repo": "nomad-follower", "type": "github" } }, - "lowdown-src_4": { + "ghc-8.6.5-iohk": { "flake": false, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "lowdown-src_5": { + "ghc-8.6.5-iohk_10": { "flake": false, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "lowdown-src_6": { + "ghc-8.6.5-iohk_2": { "flake": false, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "lowdown-src_7": { + "ghc-8.6.5-iohk_3": { "flake": false, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "lowdown-src_8": { + "ghc-8.6.5-iohk_4": { "flake": false, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "lowdown-src_9": { + "ghc-8.6.5-iohk_5": { "flake": false, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "mdbook-kroki-preprocessor": { + "ghc-8.6.5-iohk_6": { "flake": false, "locked": { - "lastModified": 1655670640, - "narHash": "sha256-JjqdxftHBjABTkOpFl3cWUJtc/KGwkQ3NRWGLjH2oUs=", - "owner": "JoelCourtney", - "repo": "mdbook-kroki-preprocessor", - "rev": "bb6e607437ecc3f22fd9036acee6b797a5b45dbc", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "JoelCourtney", - "repo": "mdbook-kroki-preprocessor", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "mdbook-kroki-preprocessor_2": { + "ghc-8.6.5-iohk_7": { "flake": false, "locked": { - "lastModified": 1655670640, - "narHash": "sha256-JjqdxftHBjABTkOpFl3cWUJtc/KGwkQ3NRWGLjH2oUs=", - "owner": "JoelCourtney", - "repo": "mdbook-kroki-preprocessor", - "rev": "bb6e607437ecc3f22fd9036acee6b797a5b45dbc", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "JoelCourtney", - "repo": "mdbook-kroki-preprocessor", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "n2c": { - "inputs": { - "flake-utils": [ - "cardano-node", - "tullia", - "std", - "flake-utils" - ], - "nixpkgs": [ - "cardano-node", - "tullia", - "std", - "nixpkgs" - ] - }, + "ghc-8.6.5-iohk_8": { + "flake": false, "locked": { - "lastModified": 1665039323, - "narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "nlewo", - "repo": "nix2container", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "n2c_2": { - "inputs": { - "flake-utils": "flake-utils_11", - "nixpkgs": "nixpkgs_27" - }, + "ghc-8.6.5-iohk_9": { + "flake": false, "locked": { - "lastModified": 1650568002, - "narHash": "sha256-CciO5C3k/a7sbA+lW4jeiU6WGletujMjWcRzc1513tI=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "2cd391fc65847ea54e3657a491c379854b556262", + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", "type": "github" }, "original": { - "owner": "nlewo", - "repo": "nix2container", + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", "type": "github" } }, - "n2c_3": { - "inputs": { - "flake-utils": "flake-utils_28", - "nixpkgs": "nixpkgs_62" - }, + "ghc910X": { + "flake": false, "locked": { - "lastModified": 1655533513, - "narHash": "sha256-MAqvv2AZbyNYGJMpV5l9ydN7k66jDErFpaKOvZ1Y7f8=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "2d47dbe633a059d75c7878f554420158712481cb", - "type": "github" + "lastModified": 1714520650, + "narHash": "sha256-4uz6RA1hRr0RheGNDM49a/B3jszqNNU8iHIow4mSyso=", + "ref": "ghc-9.10", + "rev": "2c6375b9a804ac7fca1e82eb6fcfc8594c67c5f5", + "revCount": 62663, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" }, "original": { - "owner": "nlewo", - "repo": "nix2container", - "type": "github" + "ref": "ghc-9.10", + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" } }, - "nix": { - "inputs": { - "lowdown-src": "lowdown-src", - "nixpkgs": "nixpkgs_3", - "nixpkgs-regression": "nixpkgs-regression" - }, + "ghc911": { + "flake": false, "locked": { - "lastModified": 1661606874, - "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", - "owner": "NixOS", - "repo": "nix", - "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", - "type": "github" + "lastModified": 1714817013, + "narHash": "sha256-m2je4UvWfkgepMeUIiXHMwE6W+iVfUY38VDGkMzjCcc=", + "ref": "refs/heads/master", + "rev": "fc24c5cf6c62ca9e3c8d236656e139676df65034", + "revCount": 62816, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" }, "original": { - "owner": "NixOS", - "ref": "2.11.0", - "repo": "nix", - "type": "github" + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" } }, - "nix-cache-proxy": { - "inputs": { - "devshell": "devshell_11", - "inclusive": [ - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "inclusive" - ], - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "nixpkgs" - ], - "utils": "utils_15" - }, + "ghc98X": { + "flake": false, "locked": { - "lastModified": 1644317729, - "narHash": "sha256-R9R1XHv69VvZ/c7lXYs18PHcnEBXS+hDfhjdkZ96lgw=", - "owner": "input-output-hk", - "repo": "nix-cache-proxy", - "rev": "378617d6b9865be96f7dfa16e0ce3f329da844ec", - "type": "github" + "lastModified": 1696643148, + "narHash": "sha256-E02DfgISH7EvvNAu0BHiPvl1E5FGMDi0pWdNZtIBC9I=", + "ref": "ghc-9.8", + "rev": "443e870d977b1ab6fc05f47a9a17bc49296adbd6", + "revCount": 61642, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" }, "original": { - "owner": "input-output-hk", - "repo": "nix-cache-proxy", - "type": "github" + "ref": "ghc-9.8", + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" } }, - "nix-inclusive": { - "inputs": { - "stdlib": "stdlib_12" - }, + "ghc98X_2": { + "flake": false, "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", - "type": "github" + "lastModified": 1696643148, + "narHash": "sha256-E02DfgISH7EvvNAu0BHiPvl1E5FGMDi0pWdNZtIBC9I=", + "ref": "ghc-9.8", + "rev": "443e870d977b1ab6fc05f47a9a17bc49296adbd6", + "revCount": 61642, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", - "type": "github" + "ref": "ghc-9.8", + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" } }, - "nix-nomad": { + "ghc99": { + "flake": false, + "locked": { + "lastModified": 1697054644, + "narHash": "sha256-kKarOuXUaAH3QWv7ASx+gGFMHaHKe0pK5Zu37ky2AL4=", + "ref": "refs/heads/master", + "rev": "f383a242c76f90bcca8a4d7ee001dcb49c172a9a", + "revCount": 62040, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + }, + "original": { + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + } + }, + "ghc99_2": { + "flake": false, + "locked": { + "lastModified": 1697054644, + "narHash": "sha256-kKarOuXUaAH3QWv7ASx+gGFMHaHKe0pK5Zu37ky2AL4=", + "ref": "refs/heads/master", + "rev": "f383a242c76f90bcca8a4d7ee001dcb49c172a9a", + "revCount": 62040, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + }, + "original": { + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + } + }, + "gitignore": { "inputs": { - "flake-compat": "flake-compat_3", - "flake-utils": [ - "cardano-node", - "tullia", - "nix2container", - "flake-utils" - ], - "gomod2nix": "gomod2nix", "nixpkgs": [ - "cardano-node", - "tullia", - "nixpkgs" - ], - "nixpkgs-lib": [ - "cardano-node", - "tullia", + "cardano-nix", + "pre-commit-hooks-nix", "nixpkgs" ] }, "locked": { - "lastModified": 1658277770, - "narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=", - "owner": "tristanpemble", - "repo": "nix-nomad", - "rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70", + "lastModified": 1703887061, + "narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5", "type": "github" }, "original": { - "owner": "tristanpemble", - "repo": "nix-nomad", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, - "nix-tools": { - "flake": false, + "gomod2nix": { + "inputs": { + "nixpkgs": "nixpkgs_18", + "utils": "utils_2" + }, "locked": { - "lastModified": 1644395812, - "narHash": "sha256-BVFk/BEsTLq5MMZvdy3ZYHKfaS3dHrsKh4+tb5t5b58=", - "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "d847c63b99bbec78bf83be2a61dc9f09b8a9ccc1", + "lastModified": 1655245309, + "narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-tools", + "owner": "tweag", + "repo": "gomod2nix", "type": "github" } }, - "nix-tools_2": { - "flake": false, + "gomod2nix_2": { + "inputs": { + "nixpkgs": "nixpkgs_22", + "utils": "utils_4" + }, "locked": { - "lastModified": 1649424170, - "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", - "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "lastModified": 1655245309, + "narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-tools", + "owner": "tweag", + "repo": "gomod2nix", "type": "github" } }, - "nix-tools_3": { - "flake": false, + "gomod2nix_3": { + "inputs": { + "nixpkgs": "nixpkgs_31", + "utils": "utils_6" + }, "locked": { - "lastModified": 1658968505, - "narHash": "sha256-UnbQ/Ig/23e9hUdDOBwYHwHgHmQawZ2uazpJ8DLIJgE=", - "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "8a754bdcf20b20e116409c2341cf69065d083053", + "lastModified": 1655245309, + "narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-tools", + "owner": "tweag", + "repo": "gomod2nix", "type": "github" } }, - "nix-tools_4": { + "hackage": { "flake": false, "locked": { - "lastModified": 1649424170, - "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", + "lastModified": 1692145451, + "narHash": "sha256-kqfyD3Mu5kgiH5W2ZshUhzO46H0zYDpwD1SWz+POMrk=", "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "repo": "hackage.nix", + "rev": "9d2daeca0e09002bc6fb552a097a1802a2f3a4e3", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "nix-tools", + "repo": "hackage.nix", "type": "github" } }, - "nix-tools_5": { + "hackage-nix": { "flake": false, "locked": { - "lastModified": 1649424170, - "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", + "lastModified": 1721953589, + "narHash": "sha256-ctYOxCvXQS5MPILV8YPyUhylKhgIhOM4Dc5g0vGNFbM=", "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "repo": "hackage.nix", + "rev": "3f0675337984f15834fcd52b97fc766e30f4d684", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "nix-tools", + "repo": "hackage.nix", "type": "github" } }, - "nix2container": { - "inputs": { - "flake-utils": "flake-utils_3", - "nixpkgs": "nixpkgs_4" - }, + "hackageNix": { + "flake": false, "locked": { - "lastModified": 1671269339, - "narHash": "sha256-KR2SXh4c2Y+bgbCfXjTGJ74O9/u4CAPFA0KYZHhKf5Q=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "6800fff45afecc7e47c334d14cf2b2f4f25601a0", + "lastModified": 1702945378, + "narHash": "sha256-mo1MlOphO4bRwZ8T3mDwU5LOtdQcWSA+93lT1HkCcyw=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "e59b9616a744727e8e64f605f9f216464f12f89b", "type": "github" }, "original": { - "owner": "nlewo", - "repo": "nix2container", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "nix2container_2": { - "inputs": { - "flake-utils": "flake-utils_4", - "nixpkgs": "nixpkgs_6" - }, + "hackageNix_2": { + "flake": false, "locked": { - "lastModified": 1658567952, - "narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "60bb43d405991c1378baf15a40b5811a53e32ffa", + "lastModified": 1685492843, + "narHash": "sha256-X8dNs5Gfc2ucfaWAgZ1VmkpBB4Cb44EQZu0b7tkvz2Y=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "e7407bab324eb2445bda58c5ffac393e80dda1e4", "type": "github" }, "original": { - "owner": "nlewo", - "repo": "nix2container", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "nix2container_3": { - "inputs": { - "flake-utils": "flake-utils_30", - "nixpkgs": "nixpkgs_65" - }, + "hackageNix_3": { + "flake": false, "locked": { - "lastModified": 1653427219, - "narHash": "sha256-q6MzrIZq1BBFxYN+UQjW60LpQJXV6RIIUmO8gKRyMqg=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "11a0e14c2468720f42ca8dec3b82862abf96c837", + "lastModified": 1701303758, + "narHash": "sha256-8XqVEQwmJBxRPFa7SizJuZxbG+NFEZKWdhtYPTQ7ZKM=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "8a0e3ae9295b7ef8431b9be208dd06aa2789be53", "type": "github" }, "original": { - "owner": "nlewo", - "ref": "init-nix-db", - "repo": "nix2container", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "nix_10": { - "inputs": { - "lowdown-src": "lowdown-src_10", - "nixpkgs": "nixpkgs_45" - }, + "hackageNix_4": { + "flake": false, "locked": { - "lastModified": 1604400356, - "narHash": "sha256-PX1cSYv0Y6I2tidcuEwJTo8X5vAvf9vjdfHO51LD/J0=", - "owner": "NixOS", - "repo": "nix", - "rev": "cf82e14712b3be881b7c880468cd5486e8934638", + "lastModified": 1719794527, + "narHash": "sha256-qHo/KumtwAzPkfLWODu/6EFY/LeK+C7iPJyAUdT8tGA=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "da2a3bc9bd1b3dd41bb147279529c471c615fd3e", "type": "github" }, "original": { - "owner": "NixOS", - "repo": "nix", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "nix_11": { - "inputs": { - "lowdown-src": "lowdown-src_11", - "nixpkgs": "nixpkgs_47", - "nixpkgs-regression": "nixpkgs-regression_9" - }, + "hackage_2": { + "flake": false, "locked": { - "lastModified": 1645189081, - "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", - "owner": "nixos", - "repo": "nix", - "rev": "9bc03adbba5334663901c1136203bc07e4776be9", + "lastModified": 1646097829, + "narHash": "sha256-PcHDDV8NuUxZhPV/p++IkZC+SDZ1Db7m7K+9HN4/0S4=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "283f096976b48e54183905e7bdde7f213c6ee5cd", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nix", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "nix_12": { - "inputs": { - "lowdown-src": "lowdown-src_12", - "nixpkgs": "nixpkgs_59", - "nixpkgs-regression": "nixpkgs-regression_10" - }, + "hackage_3": { + "flake": false, "locked": { - "lastModified": 1643066034, - "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", - "owner": "NixOS", - "repo": "nix", - "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "lastModified": 1655342080, + "narHash": "sha256-mF/clPxSJJkKAq6Y+0oYXrU3rGOuQXFN9btSde3uvvE=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "567e2e865d42d8e5cfe796bf03b6b38e42bc00ab", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "2.6.0", - "repo": "nix", + "owner": "input-output-hk", + "repo": "hackage.nix", "type": "github" } }, - "nix_13": { - "inputs": { - "lowdown-src": "lowdown-src_13", - "nixpkgs": "nixpkgs_61", + "hackage_4": { + "flake": false, + "locked": { + "lastModified": 1659489414, + "narHash": "sha256-AghgUkUv0hIBh+PvODngYL+ejwhCn2O2OUkVaAZYkCU=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "056c6ce7014adaf887b8e4cad15ef6fd926ea568", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackage_5": { + "flake": false, + "locked": { + "lastModified": 1650935983, + "narHash": "sha256-wZTCKzA4f7nk5sIdP2BhGz5qkt6ex5VTC/53U2Y4i9Y=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "b65addc81b03406b3ee8b139549980591ed15be5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "haskell-flake": { + "locked": { + "lastModified": 1654001497, + "narHash": "sha256-GfrpyoQrVT9Z/j9its8BQs3I5O5X5Lc2IkK922bz7zg=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "4c0b0ff295f0b97238a600d2381c37ee46b67f9c", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "haskell-flake", + "type": "github" + } + }, + "haskell-nix": { + "inputs": { + "HTTP": "HTTP", + "cabal-32": "cabal-32", + "cabal-34": "cabal-34", + "cabal-36": "cabal-36", + "cardano-shell": "cardano-shell", + "flake-compat": "flake-compat_2", + "flake-utils": "flake-utils_2", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", + "hackage": "hackage", + "hls-1.10": "hls-1.10", + "hls-2.0": "hls-2.0", + "hpc-coveralls": "hpc-coveralls", + "hydra": "hydra", + "iserv-proxy": "iserv-proxy", + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003", + "nixpkgs-2105": "nixpkgs-2105", + "nixpkgs-2111": "nixpkgs-2111", + "nixpkgs-2205": "nixpkgs-2205", + "nixpkgs-2211": "nixpkgs-2211", + "nixpkgs-2305": "nixpkgs-2305", + "nixpkgs-unstable": "nixpkgs-unstable", + "old-ghc-nix": "old-ghc-nix", + "stackage": [ + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "empty-flake" + ] + }, + "locked": { + "lastModified": 1692147008, + "narHash": "sha256-ZiRaryaboJbNZ7y7XKZs2xuSfydZyGeupJNOfYpgQSw=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "1970bb2d5b0eb8152f89b305f32d055dbd6857d9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskell-nix_2": { + "inputs": { + "HTTP": "HTTP_6", + "cabal-32": "cabal-32_6", + "cabal-34": "cabal-34_6", + "cabal-36": "cabal-36_6", + "cardano-shell": "cardano-shell_6", + "flake-utils": "flake-utils_31", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_6", + "hackage": "hackage_2", + "hpc-coveralls": "hpc-coveralls_6", + "nix-tools": "nix-tools", + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_6", + "nixpkgs-2105": "nixpkgs-2105_6", + "nixpkgs-2111": "nixpkgs-2111_6", + "nixpkgs-unstable": [ + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "nixpkgs" + ], + "old-ghc-nix": "old-ghc-nix_6", + "stackage": "stackage_5" + }, + "locked": { + "lastModified": 1646097976, + "narHash": "sha256-EiyrBqayw67dw8pr1XCVU9tIZ+/jzXCQycW1S9a+KFA=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f0308ed1df3ce9f10f9da1a7c0c8591921d0b4e5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskell-nix_3": { + "inputs": { + "HTTP": "HTTP_8", + "cabal-32": "cabal-32_8", + "cabal-34": "cabal-34_8", + "cabal-36": "cabal-36_8", + "cardano-shell": "cardano-shell_8", + "flake-utils": "flake-utils_42", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_8", + "hackage": [ + "db-sync", + "cardano-world", + "hackage" + ], + "hpc-coveralls": "hpc-coveralls_8", + "hydra": "hydra_10", + "nix-tools": "nix-tools_3", + "nixpkgs": [ + "db-sync", + "cardano-world", + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_8", + "nixpkgs-2105": "nixpkgs-2105_8", + "nixpkgs-2111": "nixpkgs-2111_8", + "nixpkgs-2205": "nixpkgs-2205_6", + "nixpkgs-unstable": "nixpkgs-unstable_11", + "old-ghc-nix": "old-ghc-nix_8", + "stackage": "stackage_7" + }, + "locked": { + "lastModified": 1659439444, + "narHash": "sha256-qUK7OVpM8/piOImpPgzSUvOFHQq19sQpvOSns2nW8es=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "ee6a6559e16a603677d7cbef7c4fe18ca801b48e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskell-nix_4": { + "inputs": { + "HTTP": "HTTP_10", + "cabal-32": "cabal-32_10", + "cabal-34": "cabal-34_10", + "cabal-36": "cabal-36_10", + "cardano-shell": "cardano-shell_10", + "flake-compat": "flake-compat_25", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_10", + "hackage": [ + "hackage-nix" + ], + "hls-1.10": "hls-1.10_6", + "hls-2.0": "hls-2.0_5", + "hls-2.2": "hls-2.2_4", + "hls-2.3": "hls-2.3_4", + "hls-2.4": "hls-2.4_4", + "hls-2.5": "hls-2.5_2", + "hls-2.6": "hls-2.6_2", + "hls-2.7": "hls-2.7_2", + "hls-2.8": "hls-2.8_2", + "hls-2.9": "hls-2.9", + "hpc-coveralls": "hpc-coveralls_10", + "hydra": "hydra_12", + "iserv-proxy": "iserv-proxy_6", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_10", + "nixpkgs-2105": "nixpkgs-2105_10", + "nixpkgs-2111": "nixpkgs-2111_10", + "nixpkgs-2205": "nixpkgs-2205_7", + "nixpkgs-2211": "nixpkgs-2211_6", + "nixpkgs-2305": "nixpkgs-2305_5", + "nixpkgs-2311": "nixpkgs-2311_2", + "nixpkgs-2405": "nixpkgs-2405", + "nixpkgs-unstable": "nixpkgs-unstable_13", + "old-ghc-nix": "old-ghc-nix_10", + "stackage": "stackage_9" + }, + "locked": { + "lastModified": 1721956799, + "narHash": "sha256-FU09PlekhkuocxDO2UN2aARdUflIGA36VP1EUra4b7c=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "ccbd8ed7d4aff11e0507d19dc7c40601487c0bea", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix": { + "inputs": { + "HTTP": "HTTP_2", + "cabal-32": "cabal-32_2", + "cabal-34": "cabal-34_2", + "cabal-36": "cabal-36_2", + "cardano-shell": "cardano-shell_2", + "flake-compat": "flake-compat_5", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_2", + "ghc98X": "ghc98X", + "ghc99": "ghc99", + "hackage": [ + "cardano-nix", + "cardano-db-sync", + "hackageNix" + ], + "hls-1.10": "hls-1.10_2", + "hls-2.0": "hls-2.0_2", + "hls-2.2": "hls-2.2", + "hls-2.3": "hls-2.3", + "hls-2.4": "hls-2.4", + "hpc-coveralls": "hpc-coveralls_2", + "hydra": "hydra_2", + "iserv-proxy": "iserv-proxy_2", + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "haskellNix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_2", + "nixpkgs-2105": "nixpkgs-2105_2", + "nixpkgs-2111": "nixpkgs-2111_2", + "nixpkgs-2205": "nixpkgs-2205_2", + "nixpkgs-2211": "nixpkgs-2211_2", + "nixpkgs-2305": "nixpkgs-2305_2", + "nixpkgs-unstable": "nixpkgs-unstable_3", + "old-ghc-nix": "old-ghc-nix_2", + "stackage": "stackage" + }, + "locked": { + "lastModified": 1701053834, + "narHash": "sha256-4sH4//POARjeKJv1mu8aU4W4A28GYqrj9KB3PqusHis=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "7c491c55157208575c70c7b8434e9d4a1cf173a6", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_2": { + "inputs": { + "HTTP": "HTTP_3", + "cabal-32": "cabal-32_3", + "cabal-34": "cabal-34_3", + "cabal-36": "cabal-36_3", + "cardano-shell": "cardano-shell_3", + "flake-compat": "flake-compat_7", + "flake-utils": "flake-utils_5", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_3", + "hackage": [ + "cardano-nix", + "cardano-node-8.1.1", + "hackageNix" + ], + "hls-1.10": "hls-1.10_3", + "hpc-coveralls": "hpc-coveralls_3", + "hydra": "hydra_3", + "iserv-proxy": "iserv-proxy_3", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.1.1", + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_3", + "nixpkgs-2105": "nixpkgs-2105_3", + "nixpkgs-2111": "nixpkgs-2111_3", + "nixpkgs-2205": "nixpkgs-2205_3", + "nixpkgs-2211": "nixpkgs-2211_3", + "nixpkgs-unstable": "nixpkgs-unstable_4", + "old-ghc-nix": "old-ghc-nix_3", + "stackage": "stackage_2" + }, + "locked": { + "lastModified": 1685495397, + "narHash": "sha256-BwbWroS1Qm8BiHatG5+iHMHN5U6kqOccewBROUYuMKw=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "d07c42cdb1cf88d0cab27d3090b00cb3899643c9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_3": { + "inputs": { + "HTTP": "HTTP_4", + "cabal-32": "cabal-32_4", + "cabal-34": "cabal-34_4", + "cabal-36": "cabal-36_4", + "cardano-shell": "cardano-shell_4", + "flake-compat": "flake-compat_11", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_4", + "ghc98X": "ghc98X_2", + "ghc99": "ghc99_2", + "hackage": [ + "cardano-nix", + "cardano-node-8.7.3", + "hackageNix" + ], + "hls-1.10": "hls-1.10_4", + "hls-2.0": "hls-2.0_3", + "hls-2.2": "hls-2.2_2", + "hls-2.3": "hls-2.3_2", + "hls-2.4": "hls-2.4_2", + "hpc-coveralls": "hpc-coveralls_4", + "hydra": "hydra_4", + "iserv-proxy": "iserv-proxy_4", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_4", + "nixpkgs-2105": "nixpkgs-2105_4", + "nixpkgs-2111": "nixpkgs-2111_4", + "nixpkgs-2205": "nixpkgs-2205_4", + "nixpkgs-2211": "nixpkgs-2211_4", + "nixpkgs-2305": "nixpkgs-2305_3", + "nixpkgs-unstable": "nixpkgs-unstable_5", + "old-ghc-nix": "old-ghc-nix_4", + "stackage": "stackage_3" + }, + "locked": { + "lastModified": 1700441391, + "narHash": "sha256-oJqP1AUskUvr3GNUH97eKwaIUHdYgENS2kQ7GI9RI+c=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "3b6056f3866f88d1d16eaeb2e810d3ac0df0e7cd", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_4": { + "inputs": { + "HTTP": "HTTP_5", + "cabal-32": "cabal-32_5", + "cabal-34": "cabal-34_5", + "cabal-36": "cabal-36_5", + "cardano-shell": "cardano-shell_5", + "flake-compat": "flake-compat_16", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_5", + "ghc910X": "ghc910X", + "ghc911": "ghc911", + "hackage": [ + "cardano-node", + "hackageNix" + ], + "hls-1.10": "hls-1.10_5", + "hls-2.0": "hls-2.0_4", + "hls-2.2": "hls-2.2_3", + "hls-2.3": "hls-2.3_3", + "hls-2.4": "hls-2.4_3", + "hls-2.5": "hls-2.5", + "hls-2.6": "hls-2.6", + "hls-2.7": "hls-2.7", + "hls-2.8": "hls-2.8", + "hpc-coveralls": "hpc-coveralls_5", + "hydra": "hydra_5", + "iserv-proxy": "iserv-proxy_5", + "nixpkgs": [ + "cardano-node", + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_5", + "nixpkgs-2105": "nixpkgs-2105_5", + "nixpkgs-2111": "nixpkgs-2111_5", + "nixpkgs-2205": "nixpkgs-2205_5", + "nixpkgs-2211": "nixpkgs-2211_5", + "nixpkgs-2305": "nixpkgs-2305_4", + "nixpkgs-2311": "nixpkgs-2311", + "nixpkgs-unstable": "nixpkgs-unstable_6", + "old-ghc-nix": "old-ghc-nix_5", + "stackage": "stackage_4" + }, + "locked": { + "lastModified": 1718797200, + "narHash": "sha256-ueFxTuZrQ3ZT/Fj5sSeUWlqKa4+OkUU1xW0E+q/XTfw=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "cb139fa956158397aa398186bb32dd26f7318784", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_5": { + "inputs": { + "HTTP": "HTTP_7", + "cabal-32": "cabal-32_7", + "cabal-34": "cabal-34_7", + "cabal-36": "cabal-36_7", + "cardano-shell": "cardano-shell_7", + "flake-utils": "flake-utils_41", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_7", + "hackage": "hackage_3", + "hpc-coveralls": "hpc-coveralls_7", + "hydra": "hydra_9", + "nix-tools": "nix-tools_2", + "nixpkgs": [ + "db-sync", + "cardano-world", + "cardano-wallet", + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_7", + "nixpkgs-2105": "nixpkgs-2105_7", + "nixpkgs-2111": "nixpkgs-2111_7", + "nixpkgs-unstable": "nixpkgs-unstable_10", + "old-ghc-nix": "old-ghc-nix_7", + "stackage": "stackage_6" + }, + "locked": { + "lastModified": 1655369909, + "narHash": "sha256-Z3d17WvaXY2kWdfsOE6yPKViQ1RBfGi4d7XZgXA/j2I=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "5a310b0b3904d9b90239390eb2dfb59e4dcb0d96", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_6": { + "inputs": { + "HTTP": "HTTP_9", + "cabal-32": "cabal-32_9", + "cabal-34": "cabal-34_9", + "cabal-36": "cabal-36_9", + "cardano-shell": "cardano-shell_9", + "flake-utils": "flake-utils_47", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_9", + "hackage": "hackage_5", + "hpc-coveralls": "hpc-coveralls_9", + "hydra": "hydra_11", + "nix-tools": "nix-tools_4", + "nixpkgs": [ + "db-sync", + "haskellNix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_9", + "nixpkgs-2105": "nixpkgs-2105_9", + "nixpkgs-2111": "nixpkgs-2111_9", + "nixpkgs-unstable": "nixpkgs-unstable_12", + "old-ghc-nix": "old-ghc-nix_9", + "stackage": "stackage_8" + }, + "locked": { + "lastModified": 1650936156, + "narHash": "sha256-B58b4OCSc6ohRjGEdbQ78r+TK/OZYsBXION90kfQDC4=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "9a502b8c8aac4d7b8033bc9affb87fd03d4740fc", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haumea": { + "inputs": { + "nixpkgs": "nixpkgs_28" + }, + "locked": { + "lastModified": 1685133229, + "narHash": "sha256-FePm/Gi9PBSNwiDFq3N+DWdfxFq0UKsVVTJS3cQPn94=", + "owner": "nix-community", + "repo": "haumea", + "rev": "34dd58385092a23018748b50f9b23de6266dffc2", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "v0.2.2", + "repo": "haumea", + "type": "github" + } + }, + "haumea_2": { + "inputs": { + "nixpkgs": [ + "cardano-node", + "std", + "lib" + ] + }, + "locked": { + "lastModified": 1685133229, + "narHash": "sha256-FePm/Gi9PBSNwiDFq3N+DWdfxFq0UKsVVTJS3cQPn94=", + "owner": "nix-community", + "repo": "haumea", + "rev": "34dd58385092a23018748b50f9b23de6266dffc2", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "v0.2.2", + "repo": "haumea", + "type": "github" + } + }, + "hercules-ci-effects": { + "inputs": { + "flake-parts": [ + "cardano-nix", + "flake-parts" + ], + "nixpkgs": [ + "cardano-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1710396488, + "narHash": "sha256-yniBB5i1un44uzR4+luTWvZ6uGvsHSYIBiDZ8Xox4nQ=", + "owner": "mlabs-haskell", + "repo": "hercules-ci-effects", + "rev": "f5ed263ab0585dfb7b067301419fb80d64e8c021", + "type": "github" + }, + "original": { + "owner": "mlabs-haskell", + "ref": "push-cache-effect", + "repo": "hercules-ci-effects", + "type": "github" + } + }, + "hercules-ci-effects_2": { + "inputs": { + "flake-parts": "flake-parts_7", + "nixpkgs": "nixpkgs_99" + }, + "locked": { + "lastModified": 1719226092, + "narHash": "sha256-YNkUMcCUCpnULp40g+svYsaH1RbSEj6s4WdZY/SHe38=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "11e4b8dc112e2f485d7c97e1cee77f9958f498f5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "type": "github" + } + }, + "hls-1.10": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_2": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_3": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_4": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_5": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_6": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0_2": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0_3": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0_4": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0_5": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.2": { + "flake": false, + "locked": { + "lastModified": 1693064058, + "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.2.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.2_2": { + "flake": false, + "locked": { + "lastModified": 1693064058, + "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.2.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.2_3": { + "flake": false, + "locked": { + "lastModified": 1693064058, + "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.2.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.2_4": { + "flake": false, + "locked": { + "lastModified": 1693064058, + "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.2.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.3": { + "flake": false, + "locked": { + "lastModified": 1695910642, + "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.3.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.3_2": { + "flake": false, + "locked": { + "lastModified": 1695910642, + "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.3.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.3_3": { + "flake": false, + "locked": { + "lastModified": 1695910642, + "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.3.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.3_4": { + "flake": false, + "locked": { + "lastModified": 1695910642, + "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.3.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.4": { + "flake": false, + "locked": { + "lastModified": 1696939266, + "narHash": "sha256-VOMf5+kyOeOmfXTHlv4LNFJuDGa7G3pDnOxtzYR40IU=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "362fdd1293efb4b82410b676ab1273479f6d17ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.4.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.4_2": { + "flake": false, + "locked": { + "lastModified": 1696939266, + "narHash": "sha256-VOMf5+kyOeOmfXTHlv4LNFJuDGa7G3pDnOxtzYR40IU=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "362fdd1293efb4b82410b676ab1273479f6d17ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.4.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.4_3": { + "flake": false, + "locked": { + "lastModified": 1699862708, + "narHash": "sha256-YHXSkdz53zd0fYGIYOgLt6HrA0eaRJi9mXVqDgmvrjk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "54507ef7e85fa8e9d0eb9a669832a3287ffccd57", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.4.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.4_4": { + "flake": false, + "locked": { + "lastModified": 1699862708, + "narHash": "sha256-YHXSkdz53zd0fYGIYOgLt6HrA0eaRJi9mXVqDgmvrjk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "54507ef7e85fa8e9d0eb9a669832a3287ffccd57", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.4.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.5": { + "flake": false, + "locked": { + "lastModified": 1701080174, + "narHash": "sha256-fyiR9TaHGJIIR0UmcCb73Xv9TJq3ht2ioxQ2mT7kVdc=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "27f8c3d3892e38edaef5bea3870161815c4d014c", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.5.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.5_2": { + "flake": false, + "locked": { + "lastModified": 1701080174, + "narHash": "sha256-fyiR9TaHGJIIR0UmcCb73Xv9TJq3ht2ioxQ2mT7kVdc=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "27f8c3d3892e38edaef5bea3870161815c4d014c", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.5.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.6": { + "flake": false, + "locked": { + "lastModified": 1705325287, + "narHash": "sha256-+P87oLdlPyMw8Mgoul7HMWdEvWP/fNlo8jyNtwME8E8=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "6e0b342fa0327e628610f2711f8c3e4eaaa08b1e", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.6.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.6_2": { + "flake": false, + "locked": { + "lastModified": 1705325287, + "narHash": "sha256-+P87oLdlPyMw8Mgoul7HMWdEvWP/fNlo8jyNtwME8E8=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "6e0b342fa0327e628610f2711f8c3e4eaaa08b1e", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.6.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.7": { + "flake": false, + "locked": { + "lastModified": 1708965829, + "narHash": "sha256-LfJ+TBcBFq/XKoiNI7pc4VoHg4WmuzsFxYJ3Fu+Jf+M=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "50322b0a4aefb27adc5ec42f5055aaa8f8e38001", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.7.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.7_2": { + "flake": false, + "locked": { + "lastModified": 1708965829, + "narHash": "sha256-LfJ+TBcBFq/XKoiNI7pc4VoHg4WmuzsFxYJ3Fu+Jf+M=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "50322b0a4aefb27adc5ec42f5055aaa8f8e38001", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.7.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.8": { + "flake": false, + "locked": { + "lastModified": 1715153580, + "narHash": "sha256-Vi/iUt2pWyUJlo9VrYgTcbRviWE0cFO6rmGi9rmALw0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "dd1be1beb16700de59e0d6801957290bcf956a0a", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.8.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.8_2": { + "flake": false, + "locked": { + "lastModified": 1715153580, + "narHash": "sha256-Vi/iUt2pWyUJlo9VrYgTcbRviWE0cFO6rmGi9rmALw0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "dd1be1beb16700de59e0d6801957290bcf956a0a", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.8.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.9": { + "flake": false, + "locked": { + "lastModified": 1718469202, + "narHash": "sha256-THXSz+iwB1yQQsr/PY151+2GvtoJnTIB2pIQ4OzfjD4=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "40891bccb235ebacce020b598b083eab9dda80f1", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.9.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hpc-coveralls": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_10": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_2": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_3": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_4": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_5": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_6": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_7": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_8": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_9": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hydra": { + "inputs": { + "nix": "nix", + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_10": { + "inputs": { + "nix": "nix_18", + "nixpkgs": [ + "db-sync", + "cardano-world", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_11": { + "inputs": { + "nix": "nix_19", + "nixpkgs": [ + "db-sync", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_12": { + "inputs": { + "nix": "nix_20", + "nixpkgs": [ + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_2": { + "inputs": { + "nix": "nix_3", + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_3": { + "inputs": { + "nix": "nix_4", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.1.1", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_4": { + "inputs": { + "nix": "nix_5", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_5": { + "inputs": { + "nix": "nix_6", + "nixpkgs": [ + "cardano-node", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_6": { + "inputs": { + "nix": [ + "db-sync", + "cardano-world", + "bitte", + "capsules", + "bitte", + "nix" + ], + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte", + "capsules", + "bitte", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1631062883, + "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", + "owner": "kreisys", + "repo": "hydra", + "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "type": "github" + }, + "original": { + "owner": "kreisys", + "ref": "hydra-server-includes", + "repo": "hydra", + "type": "github" + } + }, + "hydra_7": { + "inputs": { + "nix": [ + "db-sync", + "cardano-world", + "bitte", + "nix" + ], + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1631062883, + "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", + "owner": "kreisys", + "repo": "hydra", + "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "type": "github" + }, + "original": { + "owner": "kreisys", + "ref": "hydra-server-includes", + "repo": "hydra", + "type": "github" + } + }, + "hydra_8": { + "inputs": { + "nix": [ + "db-sync", + "cardano-world", + "capsules", + "bitte", + "nix" + ], + "nixpkgs": [ + "db-sync", + "cardano-world", + "capsules", + "bitte", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1631062883, + "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", + "owner": "kreisys", + "repo": "hydra", + "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "type": "github" + }, + "original": { + "owner": "kreisys", + "ref": "hydra-server-includes", + "repo": "hydra", + "type": "github" + } + }, + "hydra_9": { + "inputs": { + "nix": "nix_17", + "nixpkgs": [ + "db-sync", + "cardano-world", + "cardano-wallet", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "incl": { + "inputs": { + "nixlib": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1669263024, + "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", + "owner": "divnix", + "repo": "incl", + "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "incl", + "type": "github" + } + }, + "incl_2": { + "inputs": { + "nixlib": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1669263024, + "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", + "owner": "divnix", + "repo": "incl", + "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "incl", + "type": "github" + } + }, + "incl_3": { + "inputs": { + "nixlib": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "haumea", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1669263024, + "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", + "owner": "divnix", + "repo": "incl", + "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "incl", + "type": "github" + } + }, + "incl_4": { + "inputs": { + "nixlib": [ + "cardano-node", + "std", + "lib" + ] + }, + "locked": { + "lastModified": 1669263024, + "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", + "owner": "divnix", + "repo": "incl", + "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "incl", + "type": "github" + } + }, + "inclusive": { + "inputs": { + "stdlib": "stdlib" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_10": { + "inputs": { + "stdlib": "stdlib_10" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_11": { + "inputs": { + "stdlib": "stdlib_11" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_12": { + "inputs": { + "stdlib": "stdlib_12" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_2": { + "inputs": { + "stdlib": "stdlib_2" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_3": { + "inputs": { + "stdlib": "stdlib_3" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_4": { + "inputs": { + "stdlib": "stdlib_4" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_5": { + "inputs": { + "stdlib": "stdlib_5" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_6": { + "inputs": { + "stdlib": "stdlib_6" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_7": { + "inputs": { + "stdlib": "stdlib_7" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_8": { + "inputs": { + "stdlib": "stdlib_8" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_9": { + "inputs": { + "stdlib": "stdlib_9" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inputs-check": { + "inputs": { + "flake-parts": "flake-parts_4", + "nixpkgs": "nixpkgs_7" + }, + "locked": { + "lastModified": 1692633913, + "narHash": "sha256-f80/49lt2hIapc9AEaTBC93jnRZe5zxlm21JXXewkko=", + "owner": "input-output-hk", + "repo": "inputs-check", + "rev": "1e9f65e56140f4e357c9abaf5311e3ea979d33e9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "inputs-check", + "type": "github" + } + }, + "iogo": { + "inputs": { + "devshell": "devshell_8", + "inclusive": "inclusive_4", + "nixpkgs": "nixpkgs_51", + "utils": "utils_13" + }, + "locked": { + "lastModified": 1652212694, + "narHash": "sha256-baAY5wKzccNsm7OCEYuySrkXRmlshokCHQjs4EdYShM=", + "owner": "input-output-hk", + "repo": "bitte-iogo", + "rev": "e465975aa368b2d919e865f71eeed02828e55471", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "bitte-iogo", + "type": "github" + } + }, + "iogo_2": { + "inputs": { + "devshell": "devshell_18", + "inclusive": "inclusive_12", + "nixpkgs": "nixpkgs_80", + "utils": "utils_27" + }, + "locked": { + "lastModified": 1658302707, + "narHash": "sha256-E0FA1CEMQlfAsmtLBRoQE7IY4ItKlBdxZ44YX0tK5Hg=", + "owner": "input-output-hk", + "repo": "bitte-iogo", + "rev": "8751660009202bc95ea3a29e304c393c140a4231", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "bitte-iogo", + "type": "github" + } + }, + "iohk-nix": { + "inputs": { + "blst": "blst", + "nixpkgs": "nixpkgs_8", + "secp256k1": "secp256k1", + "sodium": "sodium" + }, + "locked": { + "lastModified": 1691469905, + "narHash": "sha256-TV0p1dFGYAMl1dLJEfe/tNFjxvV2H7VgHU1I43q+b84=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "2f3760f135616ebc477d3ed74eba9b63c22f83a0", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "2f3760f135616ebc477d3ed74eba9b63c22f83a0", + "type": "github" + } + }, + "iohk-nix-ng": { + "inputs": { + "blst": "blst_2", + "nixpkgs": "nixpkgs_9", + "secp256k1": "secp256k1_2", + "sodium": "sodium_2" + }, + "locked": { + "lastModified": 1696471795, + "narHash": "sha256-aNNvjUtCGXaXSp5M/HSj1SOeLjqLyTRWYbIHqAEeUp0=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "91f16fa8acb58b312f94977715c630d8bf77e33e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohk-nix_2": { + "inputs": { + "nixpkgs": [ + "db-sync", + "cardano-world", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1658222743, + "narHash": "sha256-yFH01psqx30y5Ws4dBElLkxYpIxxqZx4G+jCVhsXpnA=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "9a604d01bd4420ab7f396f14d1947fbe2ce7db8b", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohk-nix_3": { + "inputs": { + "blst": "blst_7", + "nixpkgs": [ + "nixpkgs" + ], + "secp256k1": "secp256k1_7", + "sodium": "sodium_7" + }, + "locked": { + "lastModified": 1721825987, + "narHash": "sha256-PPcma4tjozwXJAWf+YtHUQUulmxwulVlwSQzKItx/n8=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "eb61f2c14e1f610ec59117ad40f8690cddbf80cb", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix": { + "inputs": { + "blst": "blst_3", + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "nixpkgs" + ], + "secp256k1": "secp256k1_3", + "sodium": "sodium_3" + }, + "locked": { + "lastModified": 1698999258, + "narHash": "sha256-42D1BMbdyZD+lT+pWUzb5zDQyasNbMJtH/7stuPuPfE=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "73dc2bb45af6f20cfe1d962f1334eed5e84ae764", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_2": { + "inputs": { + "blst": "blst_4", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.1.1", + "nixpkgs" + ], + "secp256k1": "secp256k1_4", + "sodium": "sodium_4" + }, + "locked": { + "lastModified": 1684223806, + "narHash": "sha256-IyLoP+zhuyygLtr83XXsrvKyqqLQ8FHXTiySFf4FJOI=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "86421fdd89b3af43fa716ccd07638f96c6ecd1e4", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_3": { + "inputs": { + "blst": "blst_5", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "nixpkgs" + ], + "secp256k1": "secp256k1_5", + "sodium": "sodium_5" + }, + "locked": { + "lastModified": 1698746924, + "narHash": "sha256-8og+vqQPEoB2KLUtN5esGMDymT+2bT/rCHZt1NAe7y0=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "af551ca93d969d9715fa9bf86691d9a0a19e89d9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_4": { + "inputs": { + "blst": "blst_6", + "nixpkgs": [ + "cardano-node", + "nixpkgs" + ], + "secp256k1": "secp256k1_6", + "sodium": "sodium_6" + }, + "locked": { + "lastModified": 1721825987, + "narHash": "sha256-PPcma4tjozwXJAWf+YtHUQUulmxwulVlwSQzKItx/n8=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "eb61f2c14e1f610ec59117ad40f8690cddbf80cb", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_5": { + "inputs": { + "nixpkgs": [ + "db-sync", + "cardano-world", + "cardano-wallet", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1653579289, + "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_6": { + "inputs": { + "nixpkgs": [ + "db-sync", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1667394105, + "narHash": "sha256-YhS7zGd6jK/QM/+wWyj0zUBZmE3HOXAL/kpJptGYIWg=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "7fc7625a9ab2ba137bc70ddbc89a13d3fdb78c8b", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iserv-proxy": { + "flake": false, + "locked": { + "lastModified": 1688517130, + "narHash": "sha256-hUqfxSlo+ffqVdkSZ1EDoB7/ILCL25eYkcCXW9/P3Wc=", + "ref": "hkm/remote-iserv", + "rev": "9151db2a9a61d7f5fe52ff8836f18bbd0fd8933c", + "revCount": 13, + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + }, + "original": { + "ref": "hkm/remote-iserv", + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + } + }, + "iserv-proxy_2": { + "flake": false, + "locked": { + "lastModified": 1691634696, + "narHash": "sha256-MZH2NznKC/gbgBu8NgIibtSUZeJ00HTLJ0PlWKCBHb0=", + "ref": "hkm/remote-iserv", + "rev": "43a979272d9addc29fbffc2e8542c5d96e993d73", + "revCount": 14, + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + }, + "original": { + "ref": "hkm/remote-iserv", + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + } + }, + "iserv-proxy_3": { + "flake": false, + "locked": { + "lastModified": 1670983692, + "narHash": "sha256-avLo34JnI9HNyOuauK5R69usJm+GfW3MlyGlYxZhTgY=", + "ref": "hkm/remote-iserv", + "rev": "50d0abb3317ac439a4e7495b185a64af9b7b9300", + "revCount": 10, + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + }, + "original": { + "ref": "hkm/remote-iserv", + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + } + }, + "iserv-proxy_4": { + "flake": false, + "locked": { + "lastModified": 1691634696, + "narHash": "sha256-MZH2NznKC/gbgBu8NgIibtSUZeJ00HTLJ0PlWKCBHb0=", + "ref": "hkm/remote-iserv", + "rev": "43a979272d9addc29fbffc2e8542c5d96e993d73", + "revCount": 14, + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + }, + "original": { + "ref": "hkm/remote-iserv", + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + } + }, + "iserv-proxy_5": { + "flake": false, + "locked": { + "lastModified": 1717479972, + "narHash": "sha256-7vE3RQycHI1YT9LHJ1/fUaeln2vIpYm6Mmn8FTpYeVo=", + "owner": "stable-haskell", + "repo": "iserv-proxy", + "rev": "2ed34002247213fc435d0062350b91bab920626e", + "type": "github" + }, + "original": { + "owner": "stable-haskell", + "ref": "iserv-syms", + "repo": "iserv-proxy", + "type": "github" + } + }, + "iserv-proxy_6": { + "flake": false, + "locked": { + "lastModified": 1717479972, + "narHash": "sha256-7vE3RQycHI1YT9LHJ1/fUaeln2vIpYm6Mmn8FTpYeVo=", + "owner": "stable-haskell", + "repo": "iserv-proxy", + "rev": "2ed34002247213fc435d0062350b91bab920626e", + "type": "github" + }, + "original": { + "owner": "stable-haskell", + "ref": "iserv-syms", + "repo": "iserv-proxy", + "type": "github" + } + }, + "lib": { + "locked": { + "lastModified": 1694306727, + "narHash": "sha256-26fkTOJOI65NOTNKFvtcJF9mzzf/kK9swHzfYt1Dl6Q=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "c30b6a84c0b84ec7aecbe74466033facc9ed103f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "lowdown-src": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_10": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_11": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_12": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_13": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_14": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_15": { + "flake": false, + "locked": { + "lastModified": 1598695561, + "narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_16": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_17": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_18": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_19": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_2": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_20": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_3": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_4": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_5": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_6": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_7": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_8": { + "flake": false, + "locked": { + "lastModified": 1598695561, + "narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_9": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "mdbook-kroki-preprocessor": { + "flake": false, + "locked": { + "lastModified": 1661755005, + "narHash": "sha256-1TJuUzfyMycWlOQH67LR63/ll2GDZz25I3JfScy/Jnw=", + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "rev": "93adb5716d035829efed27f65f2f0833a7d3e76f", + "type": "github" + }, + "original": { + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "type": "github" + } + }, + "mdbook-kroki-preprocessor_2": { + "flake": false, + "locked": { + "lastModified": 1655670640, + "narHash": "sha256-JjqdxftHBjABTkOpFl3cWUJtc/KGwkQ3NRWGLjH2oUs=", + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "rev": "bb6e607437ecc3f22fd9036acee6b797a5b45dbc", + "type": "github" + }, + "original": { + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "type": "github" + } + }, + "mdbook-kroki-preprocessor_3": { + "flake": false, + "locked": { + "lastModified": 1655670640, + "narHash": "sha256-JjqdxftHBjABTkOpFl3cWUJtc/KGwkQ3NRWGLjH2oUs=", + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "rev": "bb6e607437ecc3f22fd9036acee6b797a5b45dbc", + "type": "github" + }, + "original": { + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "type": "github" + } + }, + "n2c": { + "inputs": { + "flake-utils": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "flake-utils" + ], + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1665039323, + "narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "n2c_2": { + "inputs": { + "flake-utils": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "flake-utils" + ], + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1677330646, + "narHash": "sha256-hUYCwJneMjnxTvj30Fjow6UMJUITqHlpUGpXMPXUJsU=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "ebca8f58d450cae1a19c07701a5a8ae40afc9efc", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "n2c_3": { + "inputs": { + "flake-utils": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "flake-utils" + ], + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1685771919, + "narHash": "sha256-3lVKWrhNXjHJB6QkZ2SJaOs4X/mmYXtY6ovPVpDMOHc=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "95e2220911874064b5d809f8d35f7835184c4ddf", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "n2c_4": { + "inputs": { + "flake-utils": "flake-utils_19", + "nixpkgs": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1665039323, + "narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "n2c_5": { + "inputs": { + "flake-utils": "flake-utils_26", + "nixpkgs": "nixpkgs_56" + }, + "locked": { + "lastModified": 1650568002, + "narHash": "sha256-CciO5C3k/a7sbA+lW4jeiU6WGletujMjWcRzc1513tI=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "2cd391fc65847ea54e3657a491c379854b556262", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "n2c_6": { + "inputs": { + "flake-utils": "flake-utils_43", + "nixpkgs": "nixpkgs_91" + }, + "locked": { + "lastModified": 1655533513, + "narHash": "sha256-MAqvv2AZbyNYGJMpV5l9ydN7k66jDErFpaKOvZ1Y7f8=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "2d47dbe633a059d75c7878f554420158712481cb", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "nix": { + "inputs": { + "lowdown-src": "lowdown-src", + "nixpkgs": "nixpkgs_6", + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "owner": "NixOS", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" + } + }, + "nix-cache-proxy": { + "inputs": { + "devshell": "devshell_15", + "inclusive": [ + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "inclusive" + ], + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "nixpkgs" + ], + "utils": "utils_20" + }, + "locked": { + "lastModified": 1644317729, + "narHash": "sha256-R9R1XHv69VvZ/c7lXYs18PHcnEBXS+hDfhjdkZ96lgw=", + "owner": "input-output-hk", + "repo": "nix-cache-proxy", + "rev": "378617d6b9865be96f7dfa16e0ce3f329da844ec", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-cache-proxy", + "type": "github" + } + }, + "nix-inclusive": { + "inputs": { + "stdlib": "stdlib_13" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "nix-nomad": { + "inputs": { + "flake-compat": "flake-compat_8", + "flake-utils": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "nix2container", + "flake-utils" + ], + "gomod2nix": "gomod2nix", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "nixpkgs" + ], + "nixpkgs-lib": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1658277770, + "narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=", + "owner": "tristanpemble", + "repo": "nix-nomad", + "rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70", + "type": "github" + }, + "original": { + "owner": "tristanpemble", + "repo": "nix-nomad", + "type": "github" + } + }, + "nix-nomad_2": { + "inputs": { + "flake-compat": "flake-compat_9", + "flake-utils": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "nix2container", + "flake-utils" + ], + "gomod2nix": "gomod2nix_2", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "nixpkgs" + ], + "nixpkgs-lib": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1658277770, + "narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=", + "owner": "tristanpemble", + "repo": "nix-nomad", + "rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70", + "type": "github" + }, + "original": { + "owner": "tristanpemble", + "repo": "nix-nomad", + "type": "github" + } + }, + "nix-nomad_3": { + "inputs": { + "flake-compat": "flake-compat_14", + "flake-utils": [ + "cardano-node", + "cardano-automation", + "tullia", + "nix2container", + "flake-utils" + ], + "gomod2nix": "gomod2nix_3", + "nixpkgs": [ + "cardano-node", + "cardano-automation", + "tullia", + "nixpkgs" + ], + "nixpkgs-lib": [ + "cardano-node", + "cardano-automation", + "tullia", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1658277770, + "narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=", + "owner": "tristanpemble", + "repo": "nix-nomad", + "rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70", + "type": "github" + }, + "original": { + "owner": "tristanpemble", + "repo": "nix-nomad", + "type": "github" + } + }, + "nix-tools": { + "flake": false, + "locked": { + "lastModified": 1644395812, + "narHash": "sha256-BVFk/BEsTLq5MMZvdy3ZYHKfaS3dHrsKh4+tb5t5b58=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "d847c63b99bbec78bf83be2a61dc9f09b8a9ccc1", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix-tools_2": { + "flake": false, + "locked": { + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix-tools_3": { + "flake": false, + "locked": { + "lastModified": 1658968505, + "narHash": "sha256-UnbQ/Ig/23e9hUdDOBwYHwHgHmQawZ2uazpJ8DLIJgE=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "8a754bdcf20b20e116409c2341cf69065d083053", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix-tools_4": { + "flake": false, + "locked": { + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix2container": { + "inputs": { + "flake-utils": "flake-utils_6", + "nixpkgs": "nixpkgs_17" + }, + "locked": { + "lastModified": 1671269339, + "narHash": "sha256-KR2SXh4c2Y+bgbCfXjTGJ74O9/u4CAPFA0KYZHhKf5Q=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "6800fff45afecc7e47c334d14cf2b2f4f25601a0", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "nix2container_2": { + "inputs": { + "flake-utils": "flake-utils_7", + "nixpkgs": "nixpkgs_19" + }, + "locked": { + "lastModified": 1658567952, + "narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "60bb43d405991c1378baf15a40b5811a53e32ffa", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "nix2container_3": { + "inputs": { + "flake-utils": "flake-utils_10", + "nixpkgs": "nixpkgs_23" + }, + "locked": { + "lastModified": 1658567952, + "narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "60bb43d405991c1378baf15a40b5811a53e32ffa", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "nix2container_4": { + "inputs": { + "flake-utils": "flake-utils_12", + "nixpkgs": "nixpkgs_27" + }, + "locked": { + "lastModified": 1671269339, + "narHash": "sha256-KR2SXh4c2Y+bgbCfXjTGJ74O9/u4CAPFA0KYZHhKf5Q=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "6800fff45afecc7e47c334d14cf2b2f4f25601a0", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "nix2container_5": { + "inputs": { + "flake-utils": "flake-utils_17", + "nixpkgs": "nixpkgs_32" + }, + "locked": { + "lastModified": 1658567952, + "narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "60bb43d405991c1378baf15a40b5811a53e32ffa", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "nix2container_6": { + "inputs": { + "flake-utils": "flake-utils_20", + "nixpkgs": "nixpkgs_36" + }, + "locked": { + "lastModified": 1712990762, + "narHash": "sha256-hO9W3w7NcnYeX8u8cleHiSpK2YJo7ecarFTUlbybl7k=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "20aad300c925639d5d6cbe30013c8357ce9f2a2e", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "nix2container_7": { + "inputs": { + "flake-utils": "flake-utils_45", + "nixpkgs": "nixpkgs_94" + }, + "locked": { + "lastModified": 1653427219, + "narHash": "sha256-q6MzrIZq1BBFxYN+UQjW60LpQJXV6RIIUmO8gKRyMqg=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "11a0e14c2468720f42ca8dec3b82862abf96c837", + "type": "github" + }, + "original": { + "owner": "nlewo", + "ref": "init-nix-db", + "repo": "nix2container", + "type": "github" + } + }, + "nix_10": { + "inputs": { + "lowdown-src": "lowdown-src_10", + "nixpkgs": "nixpkgs_57", + "nixpkgs-regression": "nixpkgs-regression_9" + }, + "locked": { + "lastModified": 1652510778, + "narHash": "sha256-zldZ4SiwkISFXxrbY/UdwooIZ3Z/I6qKxtpc3zD0T/o=", + "owner": "nixos", + "repo": "nix", + "rev": "65cd26eebbbf80eaf0d74092f09b737606cb4b5a", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "2.8.1", + "repo": "nix", + "type": "github" + } + }, + "nix_11": { + "inputs": { + "lowdown-src": "lowdown-src_11", + "nixpkgs": "nixpkgs_59", + "nixpkgs-regression": "nixpkgs-regression_10" + }, + "locked": { + "lastModified": 1645189081, + "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", + "owner": "nixos", + "repo": "nix", + "rev": "9bc03adbba5334663901c1136203bc07e4776be9", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nix", + "type": "github" + } + }, + "nix_12": { + "inputs": { + "lowdown-src": "lowdown-src_12", + "nixpkgs": "nixpkgs_66", "nixpkgs-regression": "nixpkgs-regression_11" }, "locked": { - "lastModified": 1643066034, - "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "lastModified": 1644413094, + "narHash": "sha256-KLGaeSqvhuUFz6DxrB9r3w+lfp9bXIiCT9K1cqg7Ze8=", + "owner": "nixos", + "repo": "nix", + "rev": "52f52319ad21bdbd7a33bb85eccc83756648f110", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nix", + "rev": "52f52319ad21bdbd7a33bb85eccc83756648f110", + "type": "github" + } + }, + "nix_13": { + "inputs": { + "lowdown-src": "lowdown-src_13", + "nixpkgs": "nixpkgs_67", + "nixpkgs-regression": "nixpkgs-regression_12" + }, + "locked": { + "lastModified": 1645437800, + "narHash": "sha256-MAMIKi3sIQ0b3jzYyOb5VY29GRgv7JXl1VXoUM9xUZw=", + "owner": "NixOS", + "repo": "nix", + "rev": "f22b9e72f51f97f8f2d334748d3e97123940a146", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nix", + "rev": "f22b9e72f51f97f8f2d334748d3e97123940a146", + "type": "github" + } + }, + "nix_14": { + "inputs": { + "lowdown-src": "lowdown-src_14", + "nixpkgs": "nixpkgs_72", + "nixpkgs-regression": "nixpkgs-regression_13" + }, + "locked": { + "lastModified": 1646164353, + "narHash": "sha256-Nj3ARvplf0Xa+h4F5Cq1r9cc81C2UIpbAKDgJLsDmUc=", + "owner": "kreisys", + "repo": "nix", + "rev": "45677cae8d474270ecd797eb40eb1f8836981604", + "type": "github" + }, + "original": { + "owner": "kreisys", + "ref": "goodnix-maybe-dont-functor", + "repo": "nix", + "type": "github" + } + }, + "nix_15": { + "inputs": { + "lowdown-src": "lowdown-src_15", + "nixpkgs": "nixpkgs_74" + }, + "locked": { + "lastModified": 1604400356, + "narHash": "sha256-PX1cSYv0Y6I2tidcuEwJTo8X5vAvf9vjdfHO51LD/J0=", + "owner": "NixOS", + "repo": "nix", + "rev": "cf82e14712b3be881b7c880468cd5486e8934638", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nix", + "type": "github" + } + }, + "nix_16": { + "inputs": { + "lowdown-src": "lowdown-src_16", + "nixpkgs": "nixpkgs_76", + "nixpkgs-regression": "nixpkgs-regression_14" + }, + "locked": { + "lastModified": 1645189081, + "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", + "owner": "nixos", + "repo": "nix", + "rev": "9bc03adbba5334663901c1136203bc07e4776be9", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nix", + "type": "github" + } + }, + "nix_17": { + "inputs": { + "lowdown-src": "lowdown-src_17", + "nixpkgs": "nixpkgs_88", + "nixpkgs-regression": "nixpkgs-regression_15" + }, + "locked": { + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", + "type": "github" + } + }, + "nix_18": { + "inputs": { + "lowdown-src": "lowdown-src_18", + "nixpkgs": "nixpkgs_90", + "nixpkgs-regression": "nixpkgs-regression_16" + }, + "locked": { + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", + "type": "github" + } + }, + "nix_19": { + "inputs": { + "lowdown-src": "lowdown-src_19", + "nixpkgs": "nixpkgs_97", + "nixpkgs-regression": "nixpkgs-regression_17" + }, + "locked": { + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", + "type": "github" + } + }, + "nix_2": { + "inputs": { + "flake-compat": "flake-compat_3", + "lowdown-src": "lowdown-src_2", + "nixpkgs": "nixpkgs_10", + "nixpkgs-regression": "nixpkgs-regression_2" + }, + "locked": { + "lastModified": 1693573010, + "narHash": "sha256-HBm8mR2skhPtbJ7p+ByrOZjs7SfsfZPwy75MwI1EUmk=", + "owner": "nixos", + "repo": "nix", + "rev": "5568ca5ff130a8a0bc3db5878432eb527c74dd60", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "2.17-maintenance", + "repo": "nix", + "type": "github" + } + }, + "nix_20": { + "inputs": { + "lowdown-src": "lowdown-src_20", + "nixpkgs": "nixpkgs_98", + "nixpkgs-regression": "nixpkgs-regression_18" + }, + "locked": { + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "owner": "NixOS", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" + } + }, + "nix_3": { + "inputs": { + "lowdown-src": "lowdown-src_3", + "nixpkgs": "nixpkgs_14", + "nixpkgs-regression": "nixpkgs-regression_3" + }, + "locked": { + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "owner": "NixOS", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" + } + }, + "nix_4": { + "inputs": { + "lowdown-src": "lowdown-src_4", + "nixpkgs": "nixpkgs_16", + "nixpkgs-regression": "nixpkgs-regression_4" + }, + "locked": { + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "owner": "NixOS", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" + } + }, + "nix_5": { + "inputs": { + "lowdown-src": "lowdown-src_5", + "nixpkgs": "nixpkgs_26", + "nixpkgs-regression": "nixpkgs-regression_5" + }, + "locked": { + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "owner": "NixOS", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" + } + }, + "nix_6": { + "inputs": { + "lowdown-src": "lowdown-src_6", + "nixpkgs": "nixpkgs_35", + "nixpkgs-regression": "nixpkgs-regression_6" + }, + "locked": { + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "owner": "NixOS", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" + } + }, + "nix_7": { + "inputs": { + "lowdown-src": "lowdown-src_7", + "nixpkgs": "nixpkgs_43", + "nixpkgs-regression": "nixpkgs-regression_7" + }, + "locked": { + "lastModified": 1646164353, + "narHash": "sha256-Nj3ARvplf0Xa+h4F5Cq1r9cc81C2UIpbAKDgJLsDmUc=", + "owner": "kreisys", + "repo": "nix", + "rev": "45677cae8d474270ecd797eb40eb1f8836981604", + "type": "github" + }, + "original": { + "owner": "kreisys", + "ref": "goodnix-maybe-dont-functor", + "repo": "nix", + "type": "github" + } + }, + "nix_8": { + "inputs": { + "lowdown-src": "lowdown-src_8", + "nixpkgs": "nixpkgs_45" + }, + "locked": { + "lastModified": 1604400356, + "narHash": "sha256-PX1cSYv0Y6I2tidcuEwJTo8X5vAvf9vjdfHO51LD/J0=", + "owner": "NixOS", + "repo": "nix", + "rev": "cf82e14712b3be881b7c880468cd5486e8934638", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nix", + "type": "github" + } + }, + "nix_9": { + "inputs": { + "lowdown-src": "lowdown-src_9", + "nixpkgs": "nixpkgs_47", + "nixpkgs-regression": "nixpkgs-regression_8" + }, + "locked": { + "lastModified": 1645189081, + "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", + "owner": "nixos", + "repo": "nix", + "rev": "9bc03adbba5334663901c1136203bc07e4776be9", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nix", + "type": "github" + } + }, + "nixago": { + "inputs": { + "flake-utils": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "flake-utils" + ], + "nixago-exts": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "blank" + ], + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1661824785, + "narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=", + "owner": "nix-community", + "repo": "nixago", + "rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago", + "type": "github" + } + }, + "nixago-exts": { + "locked": { + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago-extensions", + "type": "github" + } + }, + "nixago-exts_2": { + "locked": { + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago-extensions", + "type": "github" + } + }, + "nixago_2": { + "inputs": { + "flake-utils": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "flake-utils" + ], + "nixago-exts": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1676075813, + "narHash": "sha256-X/aIT8Qc8UCqnxJvaZykx3CJ0ZnDFvO+dqp/7fglZWo=", + "owner": "nix-community", + "repo": "nixago", + "rev": "9cab4dde31ec2f2c05d702ea8648ce580664e906", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago", + "type": "github" + } + }, + "nixago_3": { + "inputs": { + "flake-utils": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "flake-utils" + ], + "nixago-exts": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1683210100, + "narHash": "sha256-bhGDOlkWtlhVECpoOog4fWiFJmLCpVEg09a40aTjCbw=", + "owner": "nix-community", + "repo": "nixago", + "rev": "1da60ad9412135f9ed7a004669fdcf3d378ec630", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago", + "type": "github" + } + }, + "nixago_4": { + "inputs": { + "flake-utils": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "flake-utils" + ], + "nixago-exts": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "nixpkgs": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1661824785, + "narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=", + "owner": "nix-community", + "repo": "nixago", + "rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago", + "type": "github" + } + }, + "nixago_5": { + "inputs": { + "flake-utils": [ + "db-sync", + "cardano-world", + "bitte", + "std", + "flake-utils" + ], + "nixago-exts": "nixago-exts", + "nixpkgs": [ + "db-sync", + "cardano-world", + "bitte", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1659153038, + "narHash": "sha256-g4npRU8YBR7CAqMF0SyXtkHnoY9q+NcxvZwcc6UvLBc=", + "owner": "nix-community", + "repo": "nixago", + "rev": "608abdd0fe6729d1f7244e03f1a7f8a5d6408898", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago", + "type": "github" + } + }, + "nixago_6": { + "inputs": { + "flake-utils": [ + "db-sync", + "cardano-world", + "std", + "flake-utils" + ], + "nixago-exts": "nixago-exts_2", + "nixpkgs": [ + "db-sync", + "cardano-world", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1659153038, + "narHash": "sha256-g4npRU8YBR7CAqMF0SyXtkHnoY9q+NcxvZwcc6UvLBc=", + "owner": "nix-community", + "repo": "nixago", + "rev": "608abdd0fe6729d1f7244e03f1a7f8a5d6408898", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago", + "type": "github" + } + }, + "nixlib": { + "locked": { + "lastModified": 1652576347, + "narHash": "sha256-52Wu7hkcIRcS4UenSSrt01J2sAbbQ6YqxZIDpuEPL/c=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "bdf553800c9c34ed00641785b02038f67f44d671", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixlib_2": { + "locked": { + "lastModified": 1644107864, + "narHash": "sha256-Wrbt6Gs+hjXD3HUICPBJHKnHEUqiyx8rzHCgvqC1Bok=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "58eabcf65e7dba189eb0013f86831c159e3b2be6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixlib_3": { + "locked": { + "lastModified": 1656809537, + "narHash": "sha256-pwXBYG3ThN4ccJjvcdNdonQ8Wyv0y/iYdnuesiFUY1U=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "40e271f69106323734b55e2ba74f13bebde324c0", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1687420147, + "narHash": "sha256-NILbmZVsoP2Aw0OAIXdbYXrWc/qggIDDyIwZ01yUx+Q=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d449a456ba7d81038fc9ec9141eae7ee3aaf2982", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_10": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_2": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_3": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_4": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_5": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_6": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_7": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_8": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_9": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105": { + "locked": { + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105_10": { + "locked": { + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105_2": { + "locked": { + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105_3": { + "locked": { + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105_4": { + "locked": { + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105_5": { + "locked": { + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105_6": { + "locked": { + "lastModified": 1642244250, + "narHash": "sha256-vWpUEqQdVP4srj+/YLJRTN9vjpTs4je0cdWKXPbDItc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0fd9ee1aa36ce865ad273f4f07fdc093adeb5c00", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105_7": { + "locked": { + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105_8": { + "locked": { + "lastModified": 1655034179, + "narHash": "sha256-rf1/7AbzuYDw6+8Xvvf3PtEOygymLBrFsFxvext5ZjI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "046ee4af7a9f016a364f8f78eeaa356ba524ac31", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105_9": { + "locked": { + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111": { + "locked": { + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_10": { + "locked": { + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_2": { + "locked": { + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_3": { + "locked": { + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_4": { + "locked": { + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_5": { + "locked": { + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_6": { + "locked": { + "lastModified": 1644510859, + "narHash": "sha256-xjpVvL5ecbyi0vxtVl/Fh9bwGlMbw3S06zE5nUzFB8A=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0d1d5d7e3679fec9d07f2eb804d9f9fdb98378d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_7": { + "locked": { + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_8": { + "locked": { + "lastModified": 1656782578, + "narHash": "sha256-1eMCBEqJplPotTo/SZ/t5HU6Sf2I8qKlZi9MX7jv9fw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "573603b7fdb9feb0eb8efc16ee18a015c667ab1b", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111_9": { + "locked": { + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2205": { + "locked": { + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2205_2": { + "locked": { + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2205_3": { + "locked": { + "lastModified": 1682600000, + "narHash": "sha256-ha4BehR1dh8EnXSoE1m/wyyYVvHI9txjW4w5/oxsW5Y=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "50fc86b75d2744e1ab3837ef74b53f103a9b55a0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2205_4": { + "locked": { + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2205_5": { + "locked": { + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2205_6": { + "locked": { + "lastModified": 1657876628, + "narHash": "sha256-URmf0O2cQ/3heg2DJOeLyU/JmfVMqG4X5t9crQXMaeY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "549d82bdd40f760a438c3c3497c1c61160f3de55", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2205_7": { + "locked": { + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2211": { + "locked": { + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2211_2": { + "locked": { + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", "owner": "NixOS", - "repo": "nix", - "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.6.0", - "repo": "nix", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_14": { - "inputs": { - "lowdown-src": "lowdown-src_14", - "nixpkgs": "nixpkgs_68", - "nixpkgs-regression": "nixpkgs-regression_12" + "nixpkgs-2211_3": { + "locked": { + "lastModified": 1682682915, + "narHash": "sha256-haR0u/j/nUvlMloYlaOYq1FMXTvkNHw+wGxc+0qXisM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "09f1b33fcc0f59263137e23e935c1bb03ec920e4", + "type": "github" }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2211_4": { "locked": { - "lastModified": 1643066034, - "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", "owner": "NixOS", - "repo": "nix", - "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.6.0", - "repo": "nix", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_15": { - "inputs": { - "lowdown-src": "lowdown-src_15", - "nixpkgs": "nixpkgs_69", - "nixpkgs-regression": "nixpkgs-regression_13" + "nixpkgs-2211_5": { + "locked": { + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", + "type": "github" }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2211_6": { "locked": { - "lastModified": 1661606874, - "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", "owner": "NixOS", - "repo": "nix", - "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.11.0", - "repo": "nix", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_16": { - "inputs": { - "lowdown-src": "lowdown-src_16", - "nixpkgs": "nixpkgs_71", - "nixpkgs-regression": "nixpkgs-regression_14" + "nixpkgs-2305": { + "locked": { + "lastModified": 1690680713, + "narHash": "sha256-NXCWA8N+GfSQyoN7ZNiOgq/nDJKOp5/BHEpiZP8sUZw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b81af66deb21f73a70c67e5ea189568af53b1e8c", + "type": "github" }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2305_2": { "locked": { - "lastModified": 1643066034, - "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "lastModified": 1695416179, + "narHash": "sha256-610o1+pwbSu+QuF3GE0NU5xQdTHM3t9wyYhB9l94Cd8=", "owner": "NixOS", - "repo": "nix", - "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "repo": "nixpkgs", + "rev": "715d72e967ec1dd5ecc71290ee072bcaf5181ed6", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.6.0", - "repo": "nix", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_2": { - "inputs": { - "lowdown-src": "lowdown-src_2", - "nixpkgs": "nixpkgs_14", - "nixpkgs-regression": "nixpkgs-regression_2" + "nixpkgs-2305_3": { + "locked": { + "lastModified": 1695416179, + "narHash": "sha256-610o1+pwbSu+QuF3GE0NU5xQdTHM3t9wyYhB9l94Cd8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "715d72e967ec1dd5ecc71290ee072bcaf5181ed6", + "type": "github" }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2305_4": { "locked": { - "lastModified": 1646164353, - "narHash": "sha256-Nj3ARvplf0Xa+h4F5Cq1r9cc81C2UIpbAKDgJLsDmUc=", - "owner": "kreisys", - "repo": "nix", - "rev": "45677cae8d474270ecd797eb40eb1f8836981604", + "lastModified": 1701362232, + "narHash": "sha256-GVdzxL0lhEadqs3hfRLuj+L1OJFGiL/L7gCcelgBlsw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d2332963662edffacfddfad59ff4f709dde80ffe", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "goodnix-maybe-dont-functor", - "repo": "nix", + "owner": "NixOS", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_3": { - "inputs": { - "lowdown-src": "lowdown-src_3", - "nixpkgs": "nixpkgs_16" + "nixpkgs-2305_5": { + "locked": { + "lastModified": 1705033721, + "narHash": "sha256-K5eJHmL1/kev6WuqyqqbS1cdNnSidIZ3jeqJ7GbrYnQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a1982c92d8980a0114372973cbdfe0a307f1bdea", + "type": "github" }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2311": { "locked": { - "lastModified": 1604400356, - "narHash": "sha256-PX1cSYv0Y6I2tidcuEwJTo8X5vAvf9vjdfHO51LD/J0=", + "lastModified": 1701386440, + "narHash": "sha256-xI0uQ9E7JbmEy/v8kR9ZQan6389rHug+zOtZeZFiDJk=", "owner": "NixOS", - "repo": "nix", - "rev": "cf82e14712b3be881b7c880468cd5486e8934638", + "repo": "nixpkgs", + "rev": "293822e55ec1872f715a66d0eda9e592dc14419f", "type": "github" }, "original": { "owner": "NixOS", - "repo": "nix", + "ref": "nixpkgs-23.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_4": { - "inputs": { - "lowdown-src": "lowdown-src_4", - "nixpkgs": "nixpkgs_18", - "nixpkgs-regression": "nixpkgs-regression_3" + "nixpkgs-2311_2": { + "locked": { + "lastModified": 1719957072, + "narHash": "sha256-gvFhEf5nszouwLAkT9nWsDzocUTqLWHuL++dvNjMp9I=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7144d6241f02d171d25fba3edeaf15e0f2592105", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-23.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2405": { + "locked": { + "lastModified": 1720122915, + "narHash": "sha256-Nby8WWxj0elBu1xuRaUcRjPi/rU3xVbkAt2kj4QwX2U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "835cf2d3f37989c5db6585a28de967a667a75fb1", + "type": "github" }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-24.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-arion": { "locked": { - "lastModified": 1645189081, - "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", + "lastModified": 1721996520, + "narHash": "sha256-R/d5Af+YT2i6/QlGKQ4mZt/kziI1D6KTXumRWkbX/+s=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cd3ac4d9337a8be63e48a38583c5978627f4daeb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-docker": { + "locked": { + "lastModified": 1652739558, + "narHash": "sha256-znGkjGugajqF/sFS+H4+ENmGTaVPFE0uu1JjQZJLEaQ=", "owner": "nixos", - "repo": "nix", - "rev": "9bc03adbba5334663901c1136203bc07e4776be9", + "repo": "nixpkgs", + "rev": "ff691ed9ba21528c1b4e034f36a04027e4522c58", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ff691ed9ba21528c1b4e034f36a04027e4522c58", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1671359686, + "narHash": "sha256-3MpC6yZo+Xn9cPordGz2/ii6IJpP2n8LE8e/ebUXLrs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "04f574a1c0fde90b51bf68198e2297ca4e7cccf4", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib_2": { + "locked": { + "dir": "lib", + "lastModified": 1682879489, + "narHash": "sha256-sASwo8gBt7JDnOOstnps90K1wxmVfyhsTPPNTGBPjjg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib_3": { + "locked": { + "dir": "lib", + "lastModified": 1690881714, + "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9e1960bc196baf6881340d53dccb203a951745a2", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nix", + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "nix_5": { - "inputs": { - "lowdown-src": "lowdown-src_5", - "nixpkgs": "nixpkgs_28", - "nixpkgs-regression": "nixpkgs-regression_4" - }, + "nixpkgs-lib_4": { "locked": { - "lastModified": 1652510778, - "narHash": "sha256-zldZ4SiwkISFXxrbY/UdwooIZ3Z/I6qKxtpc3zD0T/o=", - "owner": "nixos", - "repo": "nix", - "rev": "65cd26eebbbf80eaf0d74092f09b737606cb4b5a", + "dir": "lib", + "lastModified": 1690881714, + "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9e1960bc196baf6881340d53dccb203a951745a2", "type": "github" }, "original": { - "owner": "nixos", - "ref": "2.8.1", - "repo": "nix", + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "nix_6": { - "inputs": { - "lowdown-src": "lowdown-src_6", - "nixpkgs": "nixpkgs_30", - "nixpkgs-regression": "nixpkgs-regression_5" - }, + "nixpkgs-lib_5": { "locked": { - "lastModified": 1645189081, - "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", - "owner": "nixos", - "repo": "nix", - "rev": "9bc03adbba5334663901c1136203bc07e4776be9", + "dir": "lib", + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nix", + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "nix_7": { - "inputs": { - "lowdown-src": "lowdown-src_7", - "nixpkgs": "nixpkgs_37", - "nixpkgs-regression": "nixpkgs-regression_6" - }, + "nixpkgs-regression": { "locked": { - "lastModified": 1644413094, - "narHash": "sha256-KLGaeSqvhuUFz6DxrB9r3w+lfp9bXIiCT9K1cqg7Ze8=", - "owner": "nixos", - "repo": "nix", - "rev": "52f52319ad21bdbd7a33bb85eccc83756648f110", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nix", - "rev": "52f52319ad21bdbd7a33bb85eccc83756648f110", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nix_8": { - "inputs": { - "lowdown-src": "lowdown-src_8", - "nixpkgs": "nixpkgs_38", - "nixpkgs-regression": "nixpkgs-regression_7" - }, + "nixpkgs-regression_10": { "locked": { - "lastModified": 1645437800, - "narHash": "sha256-MAMIKi3sIQ0b3jzYyOb5VY29GRgv7JXl1VXoUM9xUZw=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", - "repo": "nix", - "rev": "f22b9e72f51f97f8f2d334748d3e97123940a146", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" + } + }, + "nixpkgs-regression_11": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", - "repo": "nix", - "rev": "f22b9e72f51f97f8f2d334748d3e97123940a146", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" + }, + "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nix_9": { - "inputs": { - "lowdown-src": "lowdown-src_9", - "nixpkgs": "nixpkgs_43", - "nixpkgs-regression": "nixpkgs-regression_8" - }, + "nixpkgs-regression_12": { "locked": { - "lastModified": 1646164353, - "narHash": "sha256-Nj3ARvplf0Xa+h4F5Cq1r9cc81C2UIpbAKDgJLsDmUc=", - "owner": "kreisys", - "repo": "nix", - "rev": "45677cae8d474270ecd797eb40eb1f8836981604", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "goodnix-maybe-dont-functor", - "repo": "nix", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixago": { - "inputs": { - "flake-utils": [ - "cardano-node", - "tullia", - "std", - "flake-utils" - ], - "nixago-exts": [ - "cardano-node", - "tullia", - "std", - "blank" - ], - "nixpkgs": [ - "cardano-node", - "tullia", - "std", - "nixpkgs" - ] - }, + "nixpkgs-regression_13": { "locked": { - "lastModified": 1661824785, - "narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=", - "owner": "nix-community", - "repo": "nixago", - "rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixago-exts": { + "nixpkgs-regression_14": { "locked": { - "lastModified": 1625557891, - "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", - "owner": "divnix", - "repo": "blank", - "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago-extensions", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixago-exts_2": { + "nixpkgs-regression_15": { "locked": { - "lastModified": 1625557891, - "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", - "owner": "divnix", - "repo": "blank", - "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago-extensions", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixago_2": { - "inputs": { - "flake-utils": [ - "db-sync", - "cardano-world", - "bitte", - "std", - "flake-utils" - ], - "nixago-exts": "nixago-exts", - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte", - "std", - "nixpkgs" - ] - }, + "nixpkgs-regression_16": { "locked": { - "lastModified": 1659153038, - "narHash": "sha256-g4npRU8YBR7CAqMF0SyXtkHnoY9q+NcxvZwcc6UvLBc=", - "owner": "nix-community", - "repo": "nixago", - "rev": "608abdd0fe6729d1f7244e03f1a7f8a5d6408898", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixago_3": { - "inputs": { - "flake-utils": [ - "db-sync", - "cardano-world", - "std", - "flake-utils" - ], - "nixago-exts": "nixago-exts_2", - "nixpkgs": [ - "db-sync", - "cardano-world", - "std", - "nixpkgs" - ] - }, + "nixpkgs-regression_17": { "locked": { - "lastModified": 1659153038, - "narHash": "sha256-g4npRU8YBR7CAqMF0SyXtkHnoY9q+NcxvZwcc6UvLBc=", - "owner": "nix-community", - "repo": "nixago", - "rev": "608abdd0fe6729d1f7244e03f1a7f8a5d6408898", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixlib": { + "nixpkgs-regression_18": { "locked": { - "lastModified": 1652576347, - "narHash": "sha256-52Wu7hkcIRcS4UenSSrt01J2sAbbQ6YqxZIDpuEPL/c=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "bdf553800c9c34ed00641785b02038f67f44d671", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixlib_2": { + "nixpkgs-regression_2": { "locked": { - "lastModified": 1644107864, - "narHash": "sha256-Wrbt6Gs+hjXD3HUICPBJHKnHEUqiyx8rzHCgvqC1Bok=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "58eabcf65e7dba189eb0013f86831c159e3b2be6", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixlib_3": { + "nixpkgs-regression_3": { "locked": { - "lastModified": 1656809537, - "narHash": "sha256-pwXBYG3ThN4ccJjvcdNdonQ8Wyv0y/iYdnuesiFUY1U=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "40e271f69106323734b55e2ba74f13bebde324c0", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs": { + "nixpkgs-regression_4": { "locked": { - "lastModified": 1687420147, - "narHash": "sha256-NILbmZVsoP2Aw0OAIXdbYXrWc/qggIDDyIwZ01yUx+Q=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d449a456ba7d81038fc9ec9141eae7ee3aaf2982", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "release-23.05", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-2003": { + "nixpkgs-regression_5": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-2003_2": { + "nixpkgs-regression_6": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-2003_3": { + "nixpkgs-regression_7": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs-2003_4": { + "nixpkgs-regression_8": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" + } + }, + "nixpkgs-regression_9": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" + }, + "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs-2003_5": { + "nixpkgs-stable": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1690066826, + "narHash": "sha256-6L2qb+Zc0BFkh72OS9uuX637gniOjzU6qCDBpjB2LGY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "ce45b591975d070044ca24e3003c830d26fea1c8", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", + "ref": "release-23.05", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2003_6": { + "nixpkgs-unstable": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1690720142, + "narHash": "sha256-GywuiZjBKfFkntQwpNQfL+Ksa2iGjPprBGL0/psgRZM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "3acb5c4264c490e7714d503c7166a3fde0c51324", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2003_7": { + "nixpkgs-unstable_10": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105": { + "nixpkgs-unstable_11": { "locked": { - "lastModified": 1659914493, - "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "lastModified": 1657888067, + "narHash": "sha256-GnwJoFBTPfW3+mz7QEeJEEQ9OMHZOiIJ/qDhZxrlKh8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "rev": "65fae659e31098ca4ac825a6fef26d890aaf3f4e", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_2": { + "nixpkgs-unstable_12": { "locked": { - "lastModified": 1642244250, - "narHash": "sha256-vWpUEqQdVP4srj+/YLJRTN9vjpTs4je0cdWKXPbDItc=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0fd9ee1aa36ce865ad273f4f07fdc093adeb5c00", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_3": { + "nixpkgs-unstable_13": { "locked": { - "lastModified": 1645296114, - "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "lastModified": 1720181791, + "narHash": "sha256-i4vJL12/AdyuQuviMMd1Hk2tsGt02hDNhA0Zj1m16N8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "rev": "4284c2b73c8bce4b46a6adf23e16d9e2ec8da4bb", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_4": { + "nixpkgs-unstable_2": { "locked": { - "lastModified": 1655034179, - "narHash": "sha256-rf1/7AbzuYDw6+8Xvvf3PtEOygymLBrFsFxvext5ZjI=", - "owner": "NixOS", + "lastModified": 1696577711, + "narHash": "sha256-94VRjvClIKDym1QRqPkX5LTQoAwZ1E6QE/3dWtOXSIQ=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "046ee4af7a9f016a364f8f78eeaa356ba524ac31", + "rev": "a2eb207f45e4a14a1e3019d9e3863d1e208e2295", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "owner": "nixos", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_5": { + "nixpkgs-unstable_3": { "locked": { - "lastModified": 1645296114, - "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "lastModified": 1695318763, + "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_6": { + "nixpkgs-unstable_4": { "locked": { - "lastModified": 1659914493, - "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "lastModified": 1682656005, + "narHash": "sha256-fYplYo7so1O+rSQ2/aS+SbTPwLTeoUXk4ekKNtSl4P8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "rev": "6806b63e824f84b0f0e60b6d660d4ae753de0477", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_7": { + "nixpkgs-unstable_5": { "locked": { - "lastModified": 1645296114, - "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "lastModified": 1695318763, + "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111": { + "nixpkgs-unstable_6": { "locked": { - "lastModified": 1659446231, - "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "lastModified": 1694822471, + "narHash": "sha256-6fSDCj++lZVMZlyqOe9SIOL8tYSBz1bI8acwovRwoX8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "rev": "47585496bcb13fb72e4a90daeea2f434e2501998", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", "repo": "nixpkgs", + "rev": "47585496bcb13fb72e4a90daeea2f434e2501998", "type": "github" } }, - "nixpkgs-2111_2": { + "nixpkgs-unstable_7": { "locked": { - "lastModified": 1644510859, - "narHash": "sha256-xjpVvL5ecbyi0vxtVl/Fh9bwGlMbw3S06zE5nUzFB8A=", - "owner": "NixOS", + "lastModified": 1646331602, + "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "0d1d5d7e3679fec9d07f2eb804d9f9fdb98378d3", + "rev": "ad267cc9cf3d5a6ae63940df31eb31382d6356e6", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "owner": "nixos", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_3": { + "nixpkgs-unstable_8": { "locked": { - "lastModified": 1648744337, - "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", - "owner": "NixOS", + "lastModified": 1656338871, + "narHash": "sha256-+LOvZFt3MpWtrxXLH4igQtRVzyD43VnuTJjDVbt7phY=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "rev": "819e4d63fc7f337a822a049fd055cd7615a5e0d6", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable_9": { + "locked": { + "lastModified": 1646331602, + "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ad267cc9cf3d5a6ae63940df31eb31382d6356e6", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_4": { + "nixpkgs_10": { "locked": { - "lastModified": 1656782578, - "narHash": "sha256-1eMCBEqJplPotTo/SZ/t5HU6Sf2I8qKlZi9MX7jv9fw=", + "lastModified": 1670461440, + "narHash": "sha256-jy1LB8HOMKGJEGXgzFRLDU1CBGL0/LlkolgnqIsF0D8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "573603b7fdb9feb0eb8efc16ee18a015c667ab1b", + "rev": "04a75b2eecc0acf6239acf9dd04485ff8d14f425", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixos-22.11-small", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_5": { + "nixpkgs_11": { "locked": { - "lastModified": 1648744337, - "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "lastModified": 1690026219, + "narHash": "sha256-oOduRk/kzQxOBknZXTLSEYd7tk+GoKvr8wV6Ab+t4AU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "rev": "f465da166263bc0d4b39dfd4ca28b777c92d4b73", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_6": { + "nixpkgs_12": { "locked": { - "lastModified": 1659446231, - "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "lastModified": 1675249806, + "narHash": "sha256-u8Rcqekusl3pMZm68hZqr6zozI8Ug5IxqOiqDLAlu1k=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "rev": "79feedf38536de2a27d13fe2eaf200a9c05193ba", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_7": { + "nixpkgs_13": { "locked": { - "lastModified": 1648744337, - "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", - "owner": "NixOS", + "lastModified": 1636823747, + "narHash": "sha256-oWo1nElRAOZqEf90Yek2ixdHyjD+gqtS/pAgwaQ9UhQ=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "rev": "f6a2ed2082d9a51668c86ba27d0b5496f7a2ea93", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "owner": "nixos", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2205": { + "nixpkgs_14": { "locked": { - "lastModified": 1682600000, - "narHash": "sha256-ha4BehR1dh8EnXSoE1m/wyyYVvHI9txjW4w5/oxsW5Y=", + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "50fc86b75d2744e1ab3837ef74b53f103a9b55a0", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-22.05-darwin", + "ref": "nixos-22.05-small", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2205_2": { + "nixpkgs_15": { "locked": { - "lastModified": 1657876628, - "narHash": "sha256-URmf0O2cQ/3heg2DJOeLyU/JmfVMqG4X5t9crQXMaeY=", + "lastModified": 1642336556, + "narHash": "sha256-QSPPbFEwy0T0DrIuSzAACkaANPQaR1lZR/nHZGz9z04=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "549d82bdd40f760a438c3c3497c1c61160f3de55", + "rev": "f3d9d4bd898cca7d04af2ae4f6ef01f2219df3d6", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-22.05-darwin", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs-2205_3": { + "nixpkgs_16": { "locked": { - "lastModified": 1685573264, - "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "380be19fbd2d9079f677978361792cb25e8a3635", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-22.05-darwin", + "ref": "nixos-22.05-small", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2211": { + "nixpkgs_17": { "locked": { - "lastModified": 1682682915, - "narHash": "sha256-haR0u/j/nUvlMloYlaOYq1FMXTvkNHw+wGxc+0qXisM=", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "09f1b33fcc0f59263137e23e935c1bb03ec920e4", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-22.11-darwin", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2211_2": { + "nixpkgs_18": { "locked": { - "lastModified": 1688392541, - "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "lastModified": 1653581809, + "narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", + "rev": "83658b28fe638a170a19b8933aa008b30640fbd1", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-22.11-darwin", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2305": { + "nixpkgs_19": { "locked": { - "lastModified": 1701362232, - "narHash": "sha256-GVdzxL0lhEadqs3hfRLuj+L1OJFGiL/L7gCcelgBlsw=", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d2332963662edffacfddfad59ff4f709dde80ffe", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-23.05-darwin", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2311": { + "nixpkgs_2": { "locked": { - "lastModified": 1701386440, - "narHash": "sha256-xI0uQ9E7JbmEy/v8kR9ZQan6389rHug+zOtZeZFiDJk=", + "lastModified": 1687420147, + "narHash": "sha256-NILbmZVsoP2Aw0OAIXdbYXrWc/qggIDDyIwZ01yUx+Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "293822e55ec1872f715a66d0eda9e592dc14419f", + "rev": "d449a456ba7d81038fc9ec9141eae7ee3aaf2982", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-23.11-darwin", + "ref": "release-23.05", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-docker": { + "nixpkgs_20": { "locked": { - "lastModified": 1652739558, - "narHash": "sha256-znGkjGugajqF/sFS+H4+ENmGTaVPFE0uu1JjQZJLEaQ=", + "lastModified": 1674407282, + "narHash": "sha256-2qwc8mrPINSFdWffPK+ji6nQ9aGnnZyHSItVcYDZDlk=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ff691ed9ba21528c1b4e034f36a04027e4522c58", + "rev": "ab1254087f4cdf4af74b552d7fc95175d9bdbb49", "type": "github" }, "original": { "owner": "nixos", + "ref": "nixos-22.11", "repo": "nixpkgs", - "rev": "ff691ed9ba21528c1b4e034f36a04027e4522c58", "type": "github" } }, - "nixpkgs-regression": { + "nixpkgs_21": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", + "lastModified": 1665087388, + "narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7", "type": "github" }, "original": { - "owner": "NixOS", + "owner": "nixos", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression_10": { + "nixpkgs_22": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1653581809, + "narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "83658b28fe638a170a19b8933aa008b30640fbd1", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" - } - }, - "nixpkgs-regression_11": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", + "ref": "nixos-unstable", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" - }, - "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" } }, - "nixpkgs-regression_12": { + "nixpkgs_23": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_13": { + "nixpkgs_24": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", + "lastModified": 1675940568, + "narHash": "sha256-epG6pOT9V0kS+FUqd7R6/CWkgnZx2DMT5Veqo+y6G3c=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "6ccc4a59c3f1b56d039d93da52696633e641bc71", "type": "github" }, "original": { - "owner": "NixOS", + "owner": "nixos", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression_14": { + "nixpkgs_25": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1642336556, + "narHash": "sha256-QSPPbFEwy0T0DrIuSzAACkaANPQaR1lZR/nHZGz9z04=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "f3d9d4bd898cca7d04af2ae4f6ef01f2219df3d6", "type": "github" }, "original": { "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "indirect" } }, - "nixpkgs-regression_2": { + "nixpkgs_26": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" - } - }, - "nixpkgs-regression_3": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", + "ref": "nixos-22.05-small", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" - }, - "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" } }, - "nixpkgs-regression_4": { + "nixpkgs_27": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" - } - }, - "nixpkgs-regression_5": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" - }, - "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" } }, - "nixpkgs-regression_6": { + "nixpkgs_28": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "lastModified": 1681001314, + "narHash": "sha256-5sDnCLdrKZqxLPK4KA8+f4A3YKO/u6ElpMILvX0g72c=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "367c0e1086a4eb4502b24d872cea2c7acdd557f4", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" } }, - "nixpkgs-regression_7": { + "nixpkgs_29": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", + "lastModified": 1675940568, + "narHash": "sha256-epG6pOT9V0kS+FUqd7R6/CWkgnZx2DMT5Veqo+y6G3c=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "6ccc4a59c3f1b56d039d93da52696633e641bc71", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_8": { + "nixpkgs_3": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1677543769, + "narHash": "sha256-LwbqS8vGisXl2WHpK9r5+kodr0zoIT8F2YB0R4y1TsA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "b26d52c9feb6476580016e78935cbf96eb3e2115", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_9": { + "nixpkgs_30": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", + "lastModified": 1677063315, + "narHash": "sha256-qiB4ajTeAOVnVSAwCNEEkoybrAlA+cpeiBxLobHndE8=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "988cc958c57ce4350ec248d2d53087777f9e1949", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-unstable": { + "nixpkgs_31": { "locked": { - "lastModified": 1682656005, - "narHash": "sha256-fYplYo7so1O+rSQ2/aS+SbTPwLTeoUXk4ekKNtSl4P8=", + "lastModified": 1653581809, + "narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6806b63e824f84b0f0e60b6d660d4ae753de0477", + "rev": "83658b28fe638a170a19b8933aa008b30640fbd1", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_2": { + "nixpkgs_32": { "locked": { - "lastModified": 1646331602, - "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", - "owner": "nixos", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad267cc9cf3d5a6ae63940df31eb31382d6356e6", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", + "owner": "NixOS", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_3": { + "nixpkgs_33": { "locked": { - "lastModified": 1656338871, - "narHash": "sha256-+LOvZFt3MpWtrxXLH4igQtRVzyD43VnuTJjDVbt7phY=", + "lastModified": 1665087388, + "narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "819e4d63fc7f337a822a049fd055cd7615a5e0d6", + "rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7", "type": "github" }, "original": { @@ -6693,93 +11620,88 @@ "type": "github" } }, - "nixpkgs-unstable_4": { + "nixpkgs_34": { "locked": { - "lastModified": 1646331602, - "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", - "owner": "nixos", + "lastModified": 1642336556, + "narHash": "sha256-QSPPbFEwy0T0DrIuSzAACkaANPQaR1lZR/nHZGz9z04=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad267cc9cf3d5a6ae63940df31eb31382d6356e6", + "rev": "f3d9d4bd898cca7d04af2ae4f6ef01f2219df3d6", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs-unstable_5": { + "nixpkgs_35": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-22.05-small", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_6": { + "nixpkgs_36": { "locked": { - "lastModified": 1657888067, - "narHash": "sha256-GnwJoFBTPfW3+mz7QEeJEEQ9OMHZOiIJ/qDhZxrlKh8=", + "lastModified": 1712920918, + "narHash": "sha256-1yxFvUcJfUphK9V91KufIQom7gCsztza0H4Rz2VCWUU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "65fae659e31098ca4ac825a6fef26d890aaf3f4e", + "rev": "92323443a56f4e9fc4e4b712e3119f66d0969297", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_7": { + "nixpkgs_37": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", - "owner": "NixOS", + "lastModified": 1708343346, + "narHash": "sha256-qlzHvterVRzS8fS0ophQpkh0rqw0abijHEOAKm0HmV0=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "9312b935a538684049cb668885e60f15547d4c5f", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", + "owner": "nixos", + "ref": "release-23.11", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_8": { + "nixpkgs_38": { "locked": { - "lastModified": 1701336116, - "narHash": "sha256-kEmpezCR/FpITc6yMbAh4WrOCiT2zg5pSjnKrq51h5Y=", + "lastModified": 1627969475, + "narHash": "sha256-MhVtkVt1MFfaDY3ObJu54NBcsaPk19vOBZ8ouhjO4qs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f5c27c6136db4d76c30e533c20517df6864c46ee", + "rev": "bd27e2e8316ac6eab11aa35c586e743286f23ecf", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs-unstable_9": { + "nixpkgs_39": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "lastModified": 1644972330, + "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "19574af0af3ffaf7c9e359744ed32556f34536bd", "type": "github" }, "original": { @@ -6789,23 +11711,23 @@ "type": "github" } }, - "nixpkgs_10": { + "nixpkgs_4": { "locked": { - "lastModified": 1644972330, - "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", - "owner": "NixOS", + "lastModified": 1645013224, + "narHash": "sha256-b7OEC8vwzJv3rsz9pwnTX2LQDkeOWz2DbKypkVvNHXc=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "19574af0af3ffaf7c9e359744ed32556f34536bd", + "rev": "b66b39216b1fef2d8c33cc7a5c72d8da80b79970", "type": "github" }, "original": { - "owner": "NixOS", + "owner": "nixos", "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_11": { + "nixpkgs_40": { "locked": { "lastModified": 1627969475, "narHash": "sha256-MhVtkVt1MFfaDY3ObJu54NBcsaPk19vOBZ8ouhjO4qs=", @@ -6819,7 +11741,7 @@ "type": "indirect" } }, - "nixpkgs_12": { + "nixpkgs_41": { "locked": { "lastModified": 1644972330, "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", @@ -6835,7 +11757,7 @@ "type": "github" } }, - "nixpkgs_13": { + "nixpkgs_42": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -6851,7 +11773,7 @@ "type": "github" } }, - "nixpkgs_14": { + "nixpkgs_43": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -6866,7 +11788,7 @@ "type": "indirect" } }, - "nixpkgs_15": { + "nixpkgs_44": { "locked": { "lastModified": 1638452135, "narHash": "sha256-5Il6hgrTgcWIsB7zug0yDFccYXx7pJCw8cwJdXMuLfM=", @@ -6882,7 +11804,7 @@ "type": "github" } }, - "nixpkgs_16": { + "nixpkgs_45": { "locked": { "lastModified": 1602702596, "narHash": "sha256-fqJ4UgOb4ZUnCDIapDb4gCrtAah5Rnr2/At3IzMitig=", @@ -6897,7 +11819,7 @@ "type": "indirect" } }, - "nixpkgs_17": { + "nixpkgs_46": { "locked": { "lastModified": 1638887115, "narHash": "sha256-emjtIeqyJ84Eb3X7APJruTrwcfnHQKs55XGljj62prs=", @@ -6913,7 +11835,7 @@ "type": "github" } }, - "nixpkgs_18": { + "nixpkgs_47": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -6928,7 +11850,7 @@ "type": "indirect" } }, - "nixpkgs_19": { + "nixpkgs_48": { "locked": { "lastModified": 1641909823, "narHash": "sha256-Uxo+Wm6c/ijNhaJlYtFLJG9mh75FYZaBreMC2ZE0nEY=", @@ -6944,37 +11866,39 @@ "type": "github" } }, - "nixpkgs_2": { + "nixpkgs_49": { "locked": { - "lastModified": 1642336556, - "narHash": "sha256-QSPPbFEwy0T0DrIuSzAACkaANPQaR1lZR/nHZGz9z04=", - "owner": "NixOS", + "lastModified": 1647350163, + "narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "f3d9d4bd898cca7d04af2ae4f6ef01f2219df3d6", + "rev": "3eb07eeafb52bcbf02ce800f032f18d666a9498d", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs_20": { + "nixpkgs_5": { "locked": { - "lastModified": 1647350163, - "narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=", + "lastModified": 1680945546, + "narHash": "sha256-8FuaH5t/aVi/pR1XxnF0qi4WwMYC+YxlfdsA0V+TEuQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "3eb07eeafb52bcbf02ce800f032f18d666a9498d", + "rev": "d9f759f2ea8d265d974a6e1259bd510ac5844c5d", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_21": { + "nixpkgs_50": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -6990,7 +11914,7 @@ "type": "github" } }, - "nixpkgs_22": { + "nixpkgs_51": { "locked": { "lastModified": 1646506091, "narHash": "sha256-sWNAJE2m+HOh1jtXlHcnhxsj6/sXrHgbqVNcVRlveK4=", @@ -7006,7 +11930,7 @@ "type": "github" } }, - "nixpkgs_23": { + "nixpkgs_52": { "locked": { "lastModified": 1658119717, "narHash": "sha256-4upOZIQQ7Bc4CprqnHsKnqYfw+arJeAuU+QcpjYBXW0=", @@ -7022,7 +11946,7 @@ "type": "github" } }, - "nixpkgs_24": { + "nixpkgs_53": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7038,7 +11962,7 @@ "type": "github" } }, - "nixpkgs_25": { + "nixpkgs_54": { "locked": { "lastModified": 1652576347, "narHash": "sha256-52Wu7hkcIRcS4UenSSrt01J2sAbbQ6YqxZIDpuEPL/c=", @@ -7053,7 +11977,7 @@ "type": "github" } }, - "nixpkgs_26": { + "nixpkgs_55": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7069,7 +11993,7 @@ "type": "github" } }, - "nixpkgs_27": { + "nixpkgs_56": { "locked": { "lastModified": 1642451377, "narHash": "sha256-hvAuYDUN8XIrcQKE6wDw4LjTCcwrTp2B1i1i/5vfDMQ=", @@ -7084,7 +12008,7 @@ "type": "github" } }, - "nixpkgs_28": { + "nixpkgs_57": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7099,7 +12023,7 @@ "type": "indirect" } }, - "nixpkgs_29": { + "nixpkgs_58": { "locked": { "lastModified": 1652559422, "narHash": "sha256-jPVTNImBTUIFdtur+d4IVot6eXmsvtOcBm0TzxmhWPk=", @@ -7115,38 +12039,38 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_59": { "locked": { - "lastModified": 1657693803, - "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-22.05-small", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" } }, - "nixpkgs_30": { + "nixpkgs_6": { "locked": { - "lastModified": 1632864508, - "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", "type": "github" }, "original": { - "id": "nixpkgs", - "ref": "nixos-21.05-small", - "type": "indirect" + "owner": "NixOS", + "ref": "nixos-22.05-small", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs_31": { + "nixpkgs_60": { "locked": { "lastModified": 1641909823, "narHash": "sha256-Uxo+Wm6c/ijNhaJlYtFLJG9mh75FYZaBreMC2ZE0nEY=", @@ -7162,7 +12086,7 @@ "type": "github" } }, - "nixpkgs_32": { + "nixpkgs_61": { "locked": { "lastModified": 1647350163, "narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=", @@ -7178,7 +12102,7 @@ "type": "github" } }, - "nixpkgs_33": { + "nixpkgs_62": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7194,7 +12118,7 @@ "type": "github" } }, - "nixpkgs_34": { + "nixpkgs_63": { "locked": { "lastModified": 1658311025, "narHash": "sha256-GqagY5YmaZB3YaO41kKcQhe5RcpS83wnsW8iCu5Znqo=", @@ -7210,7 +12134,7 @@ "type": "github" } }, - "nixpkgs_35": { + "nixpkgs_64": { "locked": { "lastModified": 1646331602, "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", @@ -7226,7 +12150,7 @@ "type": "github" } }, - "nixpkgs_36": { + "nixpkgs_65": { "locked": { "lastModified": 1643381941, "narHash": "sha256-pHTwvnN4tTsEKkWlXQ8JMY423epos8wUOhthpwJjtpc=", @@ -7242,7 +12166,7 @@ "type": "github" } }, - "nixpkgs_37": { + "nixpkgs_66": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7257,7 +12181,7 @@ "type": "indirect" } }, - "nixpkgs_38": { + "nixpkgs_67": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7269,41 +12193,26 @@ "original": { "id": "nixpkgs", "ref": "nixos-21.05-small", - "type": "indirect" - } - }, - "nixpkgs_39": { - "locked": { - "lastModified": 1644486793, - "narHash": "sha256-EeijR4guVHgVv+JpOX3cQO+1XdrkJfGmiJ9XVsVU530=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "1882c6b7368fd284ad01b0a5b5601ef136321292", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" + "type": "indirect" } }, - "nixpkgs_4": { + "nixpkgs_68": { "locked": { - "lastModified": 1654807842, - "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", + "lastModified": 1644486793, + "narHash": "sha256-EeijR4guVHgVv+JpOX3cQO+1XdrkJfGmiJ9XVsVU530=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", + "rev": "1882c6b7368fd284ad01b0a5b5601ef136321292", "type": "github" }, "original": { "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_40": { + "nixpkgs_69": { "locked": { "lastModified": 1627969475, "narHash": "sha256-MhVtkVt1MFfaDY3ObJu54NBcsaPk19vOBZ8ouhjO4qs=", @@ -7317,7 +12226,23 @@ "type": "indirect" } }, - "nixpkgs_41": { + "nixpkgs_7": { + "locked": { + "lastModified": 1692339729, + "narHash": "sha256-TUK76/Pqm9qIDjEGd27Lz9EiBIvn5F70JWDmEQ4Y5DQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ae521bd4e460b076a455dca8b13f4151489a725c", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_70": { "locked": { "lastModified": 1644972330, "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", @@ -7333,7 +12258,7 @@ "type": "github" } }, - "nixpkgs_42": { + "nixpkgs_71": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7349,7 +12274,7 @@ "type": "github" } }, - "nixpkgs_43": { + "nixpkgs_72": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7364,7 +12289,7 @@ "type": "indirect" } }, - "nixpkgs_44": { + "nixpkgs_73": { "locked": { "lastModified": 1638452135, "narHash": "sha256-5Il6hgrTgcWIsB7zug0yDFccYXx7pJCw8cwJdXMuLfM=", @@ -7380,7 +12305,7 @@ "type": "github" } }, - "nixpkgs_45": { + "nixpkgs_74": { "locked": { "lastModified": 1602702596, "narHash": "sha256-fqJ4UgOb4ZUnCDIapDb4gCrtAah5Rnr2/At3IzMitig=", @@ -7395,7 +12320,7 @@ "type": "indirect" } }, - "nixpkgs_46": { + "nixpkgs_75": { "locked": { "lastModified": 1638887115, "narHash": "sha256-emjtIeqyJ84Eb3X7APJruTrwcfnHQKs55XGljj62prs=", @@ -7411,7 +12336,7 @@ "type": "github" } }, - "nixpkgs_47": { + "nixpkgs_76": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7426,7 +12351,7 @@ "type": "indirect" } }, - "nixpkgs_48": { + "nixpkgs_77": { "locked": { "lastModified": 1641909823, "narHash": "sha256-Uxo+Wm6c/ijNhaJlYtFLJG9mh75FYZaBreMC2ZE0nEY=", @@ -7442,7 +12367,7 @@ "type": "github" } }, - "nixpkgs_49": { + "nixpkgs_78": { "locked": { "lastModified": 1647350163, "narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=", @@ -7458,39 +12383,39 @@ "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_79": { "locked": { - "lastModified": 1653581809, - "narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=", - "owner": "NixOS", + "lastModified": 1644525281, + "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "83658b28fe638a170a19b8933aa008b30640fbd1", + "rev": "48d63e924a2666baf37f4f14a18f19347fbd54a2", "type": "github" }, "original": { - "owner": "NixOS", + "owner": "nixos", "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_50": { + "nixpkgs_8": { "locked": { - "lastModified": 1644525281, - "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", + "lastModified": 1684171562, + "narHash": "sha256-BMUWjVWAUdyMWKk0ATMC9H0Bv4qAV/TXwwPUvTiC5IQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "48d63e924a2666baf37f4f14a18f19347fbd54a2", + "rev": "55af203d468a6f5032a519cba4f41acf5a74b638", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-unstable", + "ref": "release-22.11", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_51": { + "nixpkgs_80": { "locked": { "lastModified": 1646506091, "narHash": "sha256-sWNAJE2m+HOh1jtXlHcnhxsj6/sXrHgbqVNcVRlveK4=", @@ -7506,7 +12431,7 @@ "type": "github" } }, - "nixpkgs_52": { + "nixpkgs_81": { "locked": { "lastModified": 1658119717, "narHash": "sha256-4upOZIQQ7Bc4CprqnHsKnqYfw+arJeAuU+QcpjYBXW0=", @@ -7522,7 +12447,7 @@ "type": "github" } }, - "nixpkgs_53": { + "nixpkgs_82": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7538,7 +12463,7 @@ "type": "github" } }, - "nixpkgs_54": { + "nixpkgs_83": { "locked": { "lastModified": 1646470760, "narHash": "sha256-dQISyucVCCPaFioUhy5ZgfBz8rOMKGI8k13aPDFTqEs=", @@ -7554,7 +12479,7 @@ "type": "github" } }, - "nixpkgs_55": { + "nixpkgs_84": { "locked": { "lastModified": 1619531122, "narHash": "sha256-ovm5bo6PkZzNKh2YGXbRKYIjega0EjiEP0YDwyeXEYU=", @@ -7568,7 +12493,7 @@ "type": "indirect" } }, - "nixpkgs_56": { + "nixpkgs_85": { "locked": { "lastModified": 1656461576, "narHash": "sha256-rlmmw6lIlkMQIiB+NsnO8wQYWTfle8TA41UREPLP5VY=", @@ -7584,7 +12509,7 @@ "type": "github" } }, - "nixpkgs_57": { + "nixpkgs_86": { "locked": { "lastModified": 1655567057, "narHash": "sha256-Cc5hQSMsTzOHmZnYm8OSJ5RNUp22bd5NADWLHorULWQ=", @@ -7598,7 +12523,7 @@ "type": "indirect" } }, - "nixpkgs_58": { + "nixpkgs_87": { "locked": { "lastModified": 1656401090, "narHash": "sha256-bUS2nfQsvTQW2z8SK7oEFSElbmoBahOPtbXPm0AL3I4=", @@ -7612,7 +12537,7 @@ "type": "indirect" } }, - "nixpkgs_59": { + "nixpkgs_88": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7627,22 +12552,7 @@ "type": "indirect" } }, - "nixpkgs_6": { - "locked": { - "lastModified": 1654807842, - "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_60": { + "nixpkgs_89": { "locked": { "lastModified": 1656809537, "narHash": "sha256-pwXBYG3ThN4ccJjvcdNdonQ8Wyv0y/iYdnuesiFUY1U=", @@ -7657,7 +12567,23 @@ "type": "github" } }, - "nixpkgs_61": { + "nixpkgs_9": { + "locked": { + "lastModified": 1684171562, + "narHash": "sha256-BMUWjVWAUdyMWKk0ATMC9H0Bv4qAV/TXwwPUvTiC5IQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "55af203d468a6f5032a519cba4f41acf5a74b638", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "release-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_90": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7672,7 +12598,7 @@ "type": "indirect" } }, - "nixpkgs_62": { + "nixpkgs_91": { "locked": { "lastModified": 1654807842, "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", @@ -7687,7 +12613,7 @@ "type": "github" } }, - "nixpkgs_63": { + "nixpkgs_92": { "locked": { "lastModified": 1656947410, "narHash": "sha256-htDR/PZvjUJGyrRJsVqDmXR8QeoswBaRLzHt13fd0iY=", @@ -7703,7 +12629,7 @@ "type": "github" } }, - "nixpkgs_64": { + "nixpkgs_93": { "locked": { "lastModified": 1658311025, "narHash": "sha256-GqagY5YmaZB3YaO41kKcQhe5RcpS83wnsW8iCu5Znqo=", @@ -7719,7 +12645,7 @@ "type": "github" } }, - "nixpkgs_65": { + "nixpkgs_94": { "locked": { "lastModified": 1642451377, "narHash": "sha256-hvAuYDUN8XIrcQKE6wDw4LjTCcwrTp2B1i1i/5vfDMQ=", @@ -7734,7 +12660,7 @@ "type": "github" } }, - "nixpkgs_66": { + "nixpkgs_95": { "locked": { "lastModified": 1653920503, "narHash": "sha256-BBeCZwZImtjP3oYy4WogkQYy5OxNyfNciVSc1AfZgLQ=", @@ -7750,7 +12676,7 @@ "type": "github" } }, - "nixpkgs_67": { + "nixpkgs_96": { "locked": { "lastModified": 1650469885, "narHash": "sha256-BuILRZ6pzMnGey8/irbjGq1oo3vIvZa1pitSdZCmIXA=", @@ -7766,7 +12692,7 @@ "type": "github" } }, - "nixpkgs_68": { + "nixpkgs_97": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7781,7 +12707,7 @@ "type": "indirect" } }, - "nixpkgs_69": { + "nixpkgs_98": { "locked": { "lastModified": 1657693803, "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", @@ -7797,29 +12723,13 @@ "type": "github" } }, - "nixpkgs_7": { - "locked": { - "lastModified": 1674407282, - "narHash": "sha256-2qwc8mrPINSFdWffPK+ji6nQ9aGnnZyHSItVcYDZDlk=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "ab1254087f4cdf4af74b552d7fc95175d9bdbb49", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-22.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_70": { + "nixpkgs_99": { "locked": { - "lastModified": 1697723726, - "narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe+/uVNy6zCGMXgoeMb7T9rg=", + "lastModified": 1713714899, + "narHash": "sha256-+z/XjO3QJs5rLE5UOf015gdVauVRQd2vZtsFkaXBq2Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7c9cc5a6e5d38010801741ac830a3f8fd667a7a0", + "rev": "6143fc5eeb9c4f00163267708e26191d1e918932", "type": "github" }, "original": { @@ -7829,56 +12739,11 @@ "type": "github" } }, - "nixpkgs_71": { - "locked": { - "lastModified": 1632864508, - "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "ref": "nixos-21.05-small", - "type": "indirect" - } - }, - "nixpkgs_8": { - "locked": { - "lastModified": 1665087388, - "narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_9": { - "locked": { - "lastModified": 1627969475, - "narHash": "sha256-MhVtkVt1MFfaDY3ObJu54NBcsaPk19vOBZ8ouhjO4qs=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "bd27e2e8316ac6eab11aa35c586e743286f23ecf", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, "nomad": { "inputs": { - "nix": "nix_3", - "nixpkgs": "nixpkgs_17", - "utils": "utils_4" + "nix": "nix_8", + "nixpkgs": "nixpkgs_46", + "utils": "utils_9" }, "locked": { "lastModified": 1648128770, @@ -7897,11 +12762,11 @@ }, "nomad-driver-nix": { "inputs": { - "devshell": "devshell_2", - "inclusive": "inclusive", - "nix": "nix_4", - "nixpkgs": "nixpkgs_19", - "utils": "utils_5" + "devshell": "devshell_6", + "inclusive": "inclusive_2", + "nix": "nix_9", + "nixpkgs": "nixpkgs_48", + "utils": "utils_10" }, "locked": { "lastModified": 1648029666, @@ -7919,11 +12784,11 @@ }, "nomad-driver-nix_2": { "inputs": { - "devshell": "devshell_5", - "inclusive": "inclusive_4", - "nix": "nix_6", - "nixpkgs": "nixpkgs_31", - "utils": "utils_10" + "devshell": "devshell_9", + "inclusive": "inclusive_5", + "nix": "nix_11", + "nixpkgs": "nixpkgs_60", + "utils": "utils_15" }, "locked": { "lastModified": 1648029666, @@ -7941,11 +12806,11 @@ }, "nomad-driver-nix_3": { "inputs": { - "devshell": "devshell_12", - "inclusive": "inclusive_9", - "nix": "nix_11", - "nixpkgs": "nixpkgs_48", - "utils": "utils_19" + "devshell": "devshell_16", + "inclusive": "inclusive_10", + "nix": "nix_16", + "nixpkgs": "nixpkgs_77", + "utils": "utils_24" }, "locked": { "lastModified": 1648029666, @@ -7963,10 +12828,10 @@ }, "nomad-follower": { "inputs": { - "devshell": "devshell_3", - "inclusive": "inclusive_2", - "nixpkgs": "nixpkgs_20", - "utils": "utils_6" + "devshell": "devshell_7", + "inclusive": "inclusive_3", + "nixpkgs": "nixpkgs_49", + "utils": "utils_11" }, "locked": { "lastModified": 1649836589, @@ -7984,10 +12849,10 @@ }, "nomad-follower_2": { "inputs": { - "devshell": "devshell_6", - "inclusive": "inclusive_5", - "nixpkgs": "nixpkgs_32", - "utils": "utils_11" + "devshell": "devshell_10", + "inclusive": "inclusive_6", + "nixpkgs": "nixpkgs_61", + "utils": "utils_16" }, "locked": { "lastModified": 1658244176, @@ -8005,10 +12870,10 @@ }, "nomad-follower_3": { "inputs": { - "devshell": "devshell_13", - "inclusive": "inclusive_10", - "nixpkgs": "nixpkgs_49", - "utils": "utils_20" + "devshell": "devshell_17", + "inclusive": "inclusive_11", + "nixpkgs": "nixpkgs_78", + "utils": "utils_25" }, "locked": { "lastModified": 1649836589, @@ -8019,39 +12884,84 @@ "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nomad-follower", + "owner": "input-output-hk", + "repo": "nomad-follower", + "type": "github" + } + }, + "nomad_2": { + "inputs": { + "nix": "nix_15", + "nixpkgs": "nixpkgs_75", + "utils": "utils_23" + }, + "locked": { + "lastModified": 1648128770, + "narHash": "sha256-iv5Zjddi28OJH7Kh8/oGJ0k32PQXiY+56qXKiLIxSEI=", + "owner": "input-output-hk", + "repo": "nomad", + "rev": "beb504f6c8bd832e1d4509e4104187774b8ecfc0", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release-1.2.6", + "repo": "nomad", + "type": "github" + } + }, + "nosys": { + "locked": { + "lastModified": 1667881534, + "narHash": "sha256-FhwJ15uPLRsvaxtt/bNuqE/ykMpNAPF0upozFKhTtXM=", + "owner": "divnix", + "repo": "nosys", + "rev": "2d0d5207f6a230e9d0f660903f8db9807b54814f", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "nosys", + "type": "github" + } + }, + "nosys_2": { + "locked": { + "lastModified": 1668010795, + "narHash": "sha256-JBDVBnos8g0toU7EhIIqQ1If5m/nyBqtHhL3sicdPwI=", + "owner": "divnix", + "repo": "nosys", + "rev": "feade0141487801c71ff55623b421ed535dbdefa", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "nosys", "type": "github" } }, - "nomad_2": { - "inputs": { - "nix": "nix_10", - "nixpkgs": "nixpkgs_46", - "utils": "utils_18" - }, + "nosys_3": { "locked": { - "lastModified": 1648128770, - "narHash": "sha256-iv5Zjddi28OJH7Kh8/oGJ0k32PQXiY+56qXKiLIxSEI=", - "owner": "input-output-hk", - "repo": "nomad", - "rev": "beb504f6c8bd832e1d4509e4104187774b8ecfc0", + "lastModified": 1668010795, + "narHash": "sha256-JBDVBnos8g0toU7EhIIqQ1If5m/nyBqtHhL3sicdPwI=", + "owner": "divnix", + "repo": "nosys", + "rev": "feade0141487801c71ff55623b421ed535dbdefa", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "release-1.2.6", - "repo": "nomad", + "owner": "divnix", + "repo": "nosys", "type": "github" } }, - "nosys": { + "nosys_4": { "locked": { - "lastModified": 1667881534, - "narHash": "sha256-FhwJ15uPLRsvaxtt/bNuqE/ykMpNAPF0upozFKhTtXM=", + "lastModified": 1668010795, + "narHash": "sha256-JBDVBnos8g0toU7EhIIqQ1If5m/nyBqtHhL3sicdPwI=", "owner": "divnix", "repo": "nosys", - "rev": "2d0d5207f6a230e9d0f660903f8db9807b54814f", + "rev": "feade0141487801c71ff55623b421ed535dbdefa", "type": "github" }, "original": { @@ -8060,6 +12970,23 @@ "type": "github" } }, + "offchain-metadata-tools-service": { + "flake": false, + "locked": { + "lastModified": 1684160858, + "narHash": "sha256-2pu/T4uoXBxhI47PrOS6zHRZRwaSM6qA87HJySwwIBo=", + "owner": "input-output-hk", + "repo": "offchain-metadata-tools", + "rev": "a68c12b10fe5ed9802defb4a6ca80919b695d945", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "feat-add-password-to-db-conn-string", + "repo": "offchain-metadata-tools", + "type": "github" + } + }, "ogmios": { "flake": false, "locked": { @@ -8077,61 +13004,41 @@ "type": "github" } }, - "ogmios-nixos": { - "inputs": { - "CHaP": "CHaP_3", - "blank": "blank_5", - "cardano-configurations": "cardano-configurations_2", - "cardano-node": [ - "cardano-node" - ], - "flake-compat": "flake-compat_13", - "haskell-nix": [ - "haskell-nix" - ], - "iohk-nix": [ - "iohk-nix" - ], - "nixpkgs": [ - "nixpkgs" - ], - "ogmios-src": [ - "ogmios" - ] - }, + "ogmios_2": { + "flake": false, "locked": { - "lastModified": 1695289922, - "narHash": "sha256-WeZkYCyvOqnVx9zYgyO2rh0rd3O2DmxH0HZ4OJnf/aw=", - "owner": "mlabs-haskell", - "repo": "ogmios-nixos", - "rev": "78e829e9ebd50c5891024dcd1004c2ac51facd80", + "lastModified": 1720778275, + "narHash": "sha256-OpUeVbztfLy+9d2M5w2Jgx1b/IhDNAQdlr/eP1iKUQI=", + "owner": "CardanoSolutions", + "repo": "ogmios", + "rev": "63a9e9d33eadbca22d1ecc90b9623b962148d174", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "ogmios-nixos", - "rev": "78e829e9ebd50c5891024dcd1004c2ac51facd80", + "owner": "CardanoSolutions", + "ref": "v6.5.0", + "repo": "ogmios", "type": "github" } }, - "ogmios_2": { + "old-ghc-nix": { "flake": false, "locked": { - "lastModified": 1691769233, - "narHash": "sha256-7CLprKq3RwJfvy31LAPux+DYFLjEmbRBFgvtYDpJA8Q=", - "owner": "CardanoSolutions", - "repo": "ogmios", - "rev": "3d3f359b0987c009ef66fb4d4b4bddce92b9aeb3", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "CardanoSolutions", - "ref": "v6.0.0", - "repo": "ogmios", + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", "type": "github" } }, - "old-ghc-nix": { + "old-ghc-nix_10": { "flake": false, "locked": { "lastModified": 1631092763, @@ -8250,108 +13157,367 @@ "type": "github" } }, + "old-ghc-nix_8": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "old-ghc-nix_9": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, "ops-lib": { "flake": false, "locked": { - "lastModified": 1675186784, - "narHash": "sha256-HqDtrvk1l7YeREzCSEpUtChtlEgT6Tww9WrJiozjukc=", - "owner": "input-output-hk", - "repo": "ops-lib", - "rev": "5be29ed53b2a4cbbf4cf326fa2e9c1f2b754d26d", + "lastModified": 1675186784, + "narHash": "sha256-HqDtrvk1l7YeREzCSEpUtChtlEgT6Tww9WrJiozjukc=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "5be29ed53b2a4cbbf4cf326fa2e9c1f2b754d26d", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "ops-lib_2": { + "flake": false, + "locked": { + "lastModified": 1675186784, + "narHash": "sha256-HqDtrvk1l7YeREzCSEpUtChtlEgT6Tww9WrJiozjukc=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "5be29ed53b2a4cbbf4cf326fa2e9c1f2b754d26d", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "ops-lib_3": { + "flake": false, + "locked": { + "lastModified": 1713366514, + "narHash": "sha256-0hNlv+grFTE+TeXIbxSY97QoEEaUupOKMusZ4PesdrQ=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "19d83fa8eab1c0b7765f736eb4e8569d84d3e39d", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "ops-lib_4": { + "flake": false, + "locked": { + "lastModified": 1649848729, + "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "ops-lib_5": { + "flake": false, + "locked": { + "lastModified": 1649848729, + "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "ops-lib_6": { + "flake": false, + "locked": { + "lastModified": 1649848729, + "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "paisano": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ], + "nosys": "nosys_2", + "yants": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "yants" + ] + }, + "locked": { + "lastModified": 1677437285, + "narHash": "sha256-YGfMothgUq1T9wMJYEhOSvdIiD/8gLXO1YcZA6hyIWU=", + "owner": "paisano-nix", + "repo": "core", + "rev": "5f2fc05e98e001cb1cf9535ded09e05d90cec131", + "type": "github" + }, + "original": { + "owner": "paisano-nix", + "repo": "core", + "type": "github" + } + }, + "paisano-actions": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "paisano-mdbook-preprocessor", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1677306424, + "narHash": "sha256-H9/dI2rGEbKo4KEisqbRPHFG2ajF8Tm111NPdKGIf28=", + "owner": "paisano-nix", + "repo": "actions", + "rev": "65ec4e080b3480167fc1a748c89a05901eea9a9b", + "type": "github" + }, + "original": { + "owner": "paisano-nix", + "repo": "actions", + "type": "github" + } + }, + "paisano-mdbook-preprocessor": { + "inputs": { + "crane": "crane", + "fenix": "fenix_2", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" + ], + "paisano-actions": "paisano-actions", + "std": [ + "cardano-nix", + "cardano-node-8.7.3", + "std" + ] + }, + "locked": { + "lastModified": 1680654400, + "narHash": "sha256-Qdpio+ldhUK3zfl22Mhf8HUULdUOJXDWDdO7MIK69OU=", + "owner": "paisano-nix", + "repo": "mdbook-paisano-preprocessor", + "rev": "11a8fc47f574f194a7ae7b8b98001f6143ba4cf1", + "type": "github" + }, + "original": { + "owner": "paisano-nix", + "repo": "mdbook-paisano-preprocessor", + "type": "github" + } + }, + "paisano-tui": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "std": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std" + ] + }, + "locked": { + "lastModified": 1677533603, + "narHash": "sha256-Nq1dH/qn7Wg/Tj1+id+ZM3o0fzqonW73jAgY3mCp35M=", + "owner": "paisano-nix", + "repo": "tui", + "rev": "802958d123b0a5437441be0cab1dee487b0ed3eb", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "ops-lib", + "owner": "paisano-nix", + "repo": "tui", "type": "github" } }, - "ops-lib_2": { - "flake": false, + "paisano-tui_2": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "std": [ + "cardano-nix", + "cardano-node-8.7.3", + "std" + ] + }, "locked": { - "lastModified": 1649848729, - "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", - "owner": "input-output-hk", - "repo": "ops-lib", - "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "lastModified": 1681847764, + "narHash": "sha256-mdd7PJW1BZvxy0cIKsPfAO+ohVl/V7heE5ZTAHzTdv8=", + "owner": "paisano-nix", + "repo": "tui", + "rev": "3096bad91cae73ab8ab3367d31f8a143d248a244", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "ops-lib", + "owner": "paisano-nix", + "ref": "0.1.1", + "repo": "tui", "type": "github" } }, - "ops-lib_3": { + "paisano-tui_3": { "flake": false, "locked": { - "lastModified": 1649848729, - "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", - "owner": "input-output-hk", - "repo": "ops-lib", - "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "lastModified": 1708637035, + "narHash": "sha256-R19YURSK+MY/Rw6FZnojQS9zuDh+OoTAyngQAjjoubc=", + "owner": "paisano-nix", + "repo": "tui", + "rev": "231761b260587a64817e4ffae3afc15defaa15db", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "ops-lib", + "owner": "paisano-nix", + "ref": "v0.5.0", + "repo": "tui", "type": "github" } }, - "ops-lib_4": { - "flake": false, + "paisano_2": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" + ], + "nosys": "nosys_3", + "yants": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1649848729, - "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", - "owner": "input-output-hk", - "repo": "ops-lib", - "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "lastModified": 1686862844, + "narHash": "sha256-m8l/HpRBJnZ3c0F1u0IyQ3nYGWE0R9V5kfORuqZPzgk=", + "owner": "paisano-nix", + "repo": "core", + "rev": "6674b3d3577212c1eeecd30d62d52edbd000e726", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "ops-lib", + "owner": "paisano-nix", + "ref": "0.1.1", + "repo": "core", "type": "github" } }, - "plutip": { + "paisano_3": { "inputs": { - "CHaP": "CHaP_4", - "cardano-node": [ - "cardano-node" - ], - "flake-compat": "flake-compat_14", - "hackage-nix": [ - "hackage-nix" - ], - "haskell-nix": [ - "haskell-nix" - ], - "iohk-nix": [ - "iohk-nix" - ], + "call-flake": "call-flake", "nixpkgs": [ + "cardano-node", + "std", "nixpkgs" + ], + "nosys": "nosys_4", + "yants": [ + "cardano-node", + "std", + "yants" ] }, "locked": { - "lastModified": 1695131439, - "narHash": "sha256-7ZhZUDhlFvV2us4G27iAk6lHezKS/4WA07NQn88VtQU=", - "owner": "mlabs-haskell", - "repo": "plutip", - "rev": "1bf0b547cd3689c727586abb8385c008fb2a3d1c", + "lastModified": 1708640854, + "narHash": "sha256-EpcAmvIS4ErqhXtVEfd2GPpU/E/s8CCRSfYzk6FZ/fY=", + "owner": "paisano-nix", + "repo": "core", + "rev": "adcf742bc9463c08764ca9e6955bd5e7dcf3a3fe", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "ref": "gergely/version-bump", - "repo": "plutip", + "owner": "paisano-nix", + "ref": "0.2.0", + "repo": "core", "type": "github" } }, "poetry2nix": { "inputs": { - "flake-utils": "flake-utils_17", + "flake-utils": "flake-utils_32", "nixpkgs": [ "db-sync", "cardano-world", @@ -8377,8 +13543,8 @@ }, "pre-commit-hooks": { "inputs": { - "flake-utils": "flake-utils_23", - "nixpkgs": "nixpkgs_55" + "flake-utils": "flake-utils_38", + "nixpkgs": "nixpkgs_84" }, "locked": { "lastModified": 1639823344, @@ -8394,12 +13560,40 @@ "type": "github" } }, + "pre-commit-hooks-nix": { + "inputs": { + "flake-compat": "flake-compat_13", + "flake-utils": "flake-utils_15", + "gitignore": "gitignore", + "nixpkgs": [ + "cardano-nix", + "nixpkgs" + ], + "nixpkgs-stable": [ + "cardano-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1708018599, + "narHash": "sha256-M+Ng6+SePmA8g06CmUZWi1AjG2tFBX9WCXElBHEKnyM=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "5df5a70ad7575f6601d91f0efec95dd9bc619431", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "ragenix": { "inputs": { "agenix": "agenix_3", - "flake-utils": "flake-utils_8", - "nixpkgs": "nixpkgs_21", - "rust-overlay": "rust-overlay" + "flake-utils": "flake-utils_23", + "nixpkgs": "nixpkgs_50", + "rust-overlay": "rust-overlay_2" }, "locked": { "lastModified": 1641119695, @@ -8418,9 +13612,9 @@ "ragenix_2": { "inputs": { "agenix": "agenix_4", - "flake-utils": "flake-utils_10", - "nixpkgs": "nixpkgs_24", - "rust-overlay": "rust-overlay_2" + "flake-utils": "flake-utils_25", + "nixpkgs": "nixpkgs_53", + "rust-overlay": "rust-overlay_3" }, "locked": { "lastModified": 1645147603, @@ -8439,9 +13633,9 @@ "ragenix_3": { "inputs": { "agenix": "agenix_5", - "flake-utils": "flake-utils_12", - "nixpkgs": "nixpkgs_33", - "rust-overlay": "rust-overlay_3" + "flake-utils": "flake-utils_27", + "nixpkgs": "nixpkgs_62", + "rust-overlay": "rust-overlay_4" }, "locked": { "lastModified": 1641119695, @@ -8460,9 +13654,9 @@ "ragenix_4": { "inputs": { "agenix": "agenix_7", - "flake-utils": "flake-utils_19", - "nixpkgs": "nixpkgs_50", - "rust-overlay": "rust-overlay_4" + "flake-utils": "flake-utils_34", + "nixpkgs": "nixpkgs_79", + "rust-overlay": "rust-overlay_5" }, "locked": { "lastModified": 1641119695, @@ -8481,9 +13675,9 @@ "ragenix_5": { "inputs": { "agenix": "agenix_8", - "flake-utils": "flake-utils_21", - "nixpkgs": "nixpkgs_53", - "rust-overlay": "rust-overlay_5" + "flake-utils": "flake-utils_36", + "nixpkgs": "nixpkgs_82", + "rust-overlay": "rust-overlay_6" }, "locked": { "lastModified": 1645147603, @@ -8504,26 +13698,58 @@ "CHaP": "CHaP", "blockfrost": "blockfrost", "cardano-configurations": "cardano-configurations", + "cardano-nix": "cardano-nix", "cardano-node": "cardano-node", "db-sync": "db-sync", "easy-purescript-nix": "easy-purescript-nix", - "flake-compat": "flake-compat_11", + "flake-compat": "flake-compat_24", "hackage-nix": "hackage-nix", - "haskell-nix": "haskell-nix_3", - "hercules-ci-effects": "hercules-ci-effects", - "iohk-nix": "iohk-nix_2", - "kupo": "kupo", - "kupo-nixos": "kupo-nixos", + "haskell-nix": "haskell-nix_4", + "hercules-ci-effects": "hercules-ci-effects_2", + "iohk-nix": "iohk-nix_3", "nixpkgs": [ "haskell-nix", "nixpkgs-unstable" ], - "ogmios": "ogmios_2", - "ogmios-nixos": "ogmios-nixos", - "plutip": "plutip" + "nixpkgs-arion": "nixpkgs-arion", + "ogmios": "ogmios_2" } }, "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1645205556, + "narHash": "sha256-e4lZW3qRyOEJ+vLKFQP7m2Dxh5P44NrnekZYLxlucww=", + "owner": "rust-analyzer", + "repo": "rust-analyzer", + "rev": "acf5874b39f3dc5262317a6074d9fc7285081161", + "type": "github" + }, + "original": { + "owner": "rust-analyzer", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-analyzer-src_2": { + "flake": false, + "locked": { + "lastModified": 1677221702, + "narHash": "sha256-1M+58rC4eTCWNmmX0hQVZP20t3tfYNunl9D/PrGUyGE=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "f5401f620699b26ed9d47a1d2e838143a18dbe3b", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-analyzer-src_3": { "flake": false, "locked": { "lastModified": 1645024434, @@ -8540,7 +13766,7 @@ "type": "github" } }, - "rust-analyzer-src_2": { + "rust-analyzer-src_4": { "flake": false, "locked": { "lastModified": 1649178056, @@ -8557,7 +13783,7 @@ "type": "github" } }, - "rust-analyzer-src_3": { + "rust-analyzer-src_5": { "flake": false, "locked": { "lastModified": 1645024434, @@ -8574,7 +13800,7 @@ "type": "github" } }, - "rust-analyzer-src_4": { + "rust-analyzer-src_6": { "flake": false, "locked": { "lastModified": 1660579619, @@ -8591,7 +13817,7 @@ "type": "github" } }, - "rust-analyzer-src_5": { + "rust-analyzer-src_7": { "flake": false, "locked": { "lastModified": 1645024434, @@ -8608,7 +13834,7 @@ "type": "github" } }, - "rust-analyzer-src_6": { + "rust-analyzer-src_8": { "flake": false, "locked": { "lastModified": 1649178056, @@ -8626,6 +13852,39 @@ } }, "rust-overlay": { + "inputs": { + "flake-utils": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "paisano-mdbook-preprocessor", + "crane", + "flake-utils" + ], + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "paisano-mdbook-preprocessor", + "crane", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1675391458, + "narHash": "sha256-ukDKZw922BnK5ohL9LhwtaDAdCsJL7L6ScNEyF1lO9w=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "383a4acfd11d778d5c2efcf28376cbd845eeaedf", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_2": { "inputs": { "flake-utils": [ "db-sync", @@ -8660,7 +13919,7 @@ "type": "github" } }, - "rust-overlay_2": { + "rust-overlay_3": { "inputs": { "flake-utils": [ "db-sync", @@ -8693,7 +13952,7 @@ "type": "github" } }, - "rust-overlay_3": { + "rust-overlay_4": { "inputs": { "flake-utils": [ "db-sync", @@ -8724,7 +13983,7 @@ "type": "github" } }, - "rust-overlay_4": { + "rust-overlay_5": { "inputs": { "flake-utils": [ "db-sync", @@ -8757,7 +14016,7 @@ "type": "github" } }, - "rust-overlay_5": { + "rust-overlay_6": { "inputs": { "flake-utils": [ "db-sync", @@ -8775,20 +14034,105 @@ ] }, "locked": { - "lastModified": 1644633594, - "narHash": "sha256-Te6mBYYirUwsoqENvVx1K1EEoRq2CKrTnNkWF42jNgE=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "14c48021a9a5fe6ea8ae6b21c15caa106afa9d19", + "lastModified": 1644633594, + "narHash": "sha256-Te6mBYYirUwsoqENvVx1K1EEoRq2CKrTnNkWF42jNgE=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "14c48021a9a5fe6ea8ae6b21c15caa106afa9d19", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "secp256k1": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", + "type": "github" + }, + "original": { + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", + "type": "github" + } + }, + "secp256k1_2": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", + "type": "github" + }, + "original": { + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", + "type": "github" + } + }, + "secp256k1_3": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", + "type": "github" + }, + "original": { + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", + "type": "github" + } + }, + "secp256k1_4": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", + "type": "github" + }, + "original": { + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", + "type": "github" + } + }, + "secp256k1_5": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", "type": "github" }, "original": { - "owner": "oxalica", - "repo": "rust-overlay", + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", "type": "github" } }, - "secp256k1": { + "secp256k1_6": { "flake": false, "locked": { "lastModified": 1683999695, @@ -8805,7 +14149,7 @@ "type": "github" } }, - "secp256k1_2": { + "secp256k1_7": { "flake": false, "locked": { "lastModified": 1683999695, @@ -8856,7 +14200,143 @@ "type": "github" } }, + "sodium_3": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sodium_4": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sodium_5": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sodium_6": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sodium_7": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": "nixpkgs_11", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1690199016, + "narHash": "sha256-yTLL72q6aqGmzHq+C3rDp3rIjno7EJZkFLof6Ika7cE=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "c36df4fe4bf4bb87759b1891cab21e7a05219500", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, + "stable": { + "locked": { + "lastModified": 1669735802, + "narHash": "sha256-qtG/o/i5ZWZLmXw108N2aPiVsxOcidpHJYNkT45ry9Q=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "731cc710aeebecbf45a258e977e8b68350549522", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, "stackage": { + "flake": false, + "locked": { + "lastModified": 1701043780, + "narHash": "sha256-d5CYT7WGEaL6IFNmUg4JUb+onxI/tO1qgHs/TCIKB3A=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "cb49435b81adf0549589c51f39b5b38b4369f106", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "stackage_2": { "flake": false, "locked": { "lastModified": 1685491814, @@ -8872,7 +14352,39 @@ "type": "github" } }, - "stackage_2": { + "stackage_3": { + "flake": false, + "locked": { + "lastModified": 1700438989, + "narHash": "sha256-x+7Qtboko7ds8CU8pq2sIZiD45DauYoX9LxBfwQr/hs=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "9c2015334cc77837b8454b3b10ef4f711a256f6f", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "stackage_4": { + "flake": false, + "locked": { + "lastModified": 1718756571, + "narHash": "sha256-8rL8viTbuE9/yV1of6SWp2tHmhVMD2UmkOfmN5KDbKg=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "027672fb6fd45828b0e623c8152572d4058429ad", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "stackage_5": { "flake": false, "locked": { "lastModified": 1646010978, @@ -8888,7 +14400,7 @@ "type": "github" } }, - "stackage_3": { + "stackage_6": { "flake": false, "locked": { "lastModified": 1655255731, @@ -8904,107 +14416,314 @@ "type": "github" } }, - "stackage_4": { + "stackage_7": { + "flake": false, + "locked": { + "lastModified": 1659402917, + "narHash": "sha256-zRDOtN4A2KmfzmZiqqxOAIw1YVPhnoIaszKKd+qCEcQ=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "778df3c4b35eac853d57fac7bafc7c9f2dde917f", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "stackage_8": { "flake": false, "locked": { - "lastModified": 1659402917, - "narHash": "sha256-zRDOtN4A2KmfzmZiqqxOAIw1YVPhnoIaszKKd+qCEcQ=", - "owner": "input-output-hk", - "repo": "stackage.nix", - "rev": "778df3c4b35eac853d57fac7bafc7c9f2dde917f", + "lastModified": 1650936094, + "narHash": "sha256-9ibS+iszPXe3HQd8rexVfrQeO4JkXSPokhbPiJ/Lags=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "85f94546f85fb9b92080f958bec655a364b2f0e5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "stackage_9": { + "flake": false, + "locked": { + "lastModified": 1721952692, + "narHash": "sha256-UXiGzFWWOZMZRYkhS0oVaNK/v8Rr5PxxsM2qV1T6iJI=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "73bfeeb1dccad2858f22f6f57b6571b10579ed2e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "statix": { + "inputs": { + "fenix": "fenix", + "nixpkgs": "nixpkgs_4" + }, + "locked": { + "lastModified": 1676888642, + "narHash": "sha256-C73LOMVVCkeL0jA5xN7klLEDEB4NkuiATEJY4A/tIyM=", + "owner": "nerdypepper", + "repo": "statix", + "rev": "3c7136a23f444db252a556928c1489869ca3ab4e", + "type": "github" + }, + "original": { + "owner": "nerdypepper", + "repo": "statix", + "type": "github" + } + }, + "std": { + "inputs": { + "arion": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "blank" + ], + "blank": "blank", + "devshell": "devshell", + "dmerge": "dmerge", + "flake-utils": "flake-utils_8", + "incl": "incl", + "makes": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "blank" + ], + "microvm": [ + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "blank" + ], + "n2c": "n2c", + "nixago": "nixago", + "nixpkgs": "nixpkgs_21", + "nosys": "nosys", + "yants": "yants" + }, + "locked": { + "lastModified": 1674526466, + "narHash": "sha256-tMTaS0bqLx6VJ+K+ZT6xqsXNpzvSXJTmogkraBGzymg=", + "owner": "divnix", + "repo": "std", + "rev": "516387e3d8d059b50e742a2ff1909ed3c8f82826", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "stackage.nix", + "owner": "divnix", + "repo": "std", "type": "github" } }, - "stackage_5": { - "flake": false, + "std_2": { + "inputs": { + "arion": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "blank": "blank_2", + "devshell": "devshell_2", + "dmerge": "dmerge_2", + "flake-utils": "flake-utils_11", + "incl": "incl_2", + "makes": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "microvm": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "n2c": "n2c_2", + "nixago": "nixago_2", + "nixpkgs": "nixpkgs_24", + "paisano": "paisano", + "paisano-tui": "paisano-tui", + "yants": "yants_2" + }, "locked": { - "lastModified": 1650936094, - "narHash": "sha256-9ibS+iszPXe3HQd8rexVfrQeO4JkXSPokhbPiJ/Lags=", - "owner": "input-output-hk", - "repo": "stackage.nix", - "rev": "85f94546f85fb9b92080f958bec655a364b2f0e5", + "lastModified": 1677533652, + "narHash": "sha256-H37dcuWAGZs6Yl9mewMNVcmSaUXR90/bABYFLT/nwhk=", + "owner": "divnix", + "repo": "std", + "rev": "490542f624412662e0411d8cb5a9af988ef56633", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "stackage.nix", + "owner": "divnix", + "repo": "std", "type": "github" } }, - "stackage_6": { - "flake": false, + "std_3": { + "inputs": { + "arion": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "blank": "blank_3", + "devshell": "devshell_3", + "dmerge": "dmerge_3", + "flake-utils": "flake-utils_13", + "haumea": "haumea", + "incl": "incl_3", + "makes": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "microvm": [ + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "n2c": "n2c_3", + "nixago": "nixago_3", + "nixpkgs": "nixpkgs_29", + "paisano": "paisano_2", + "paisano-mdbook-preprocessor": "paisano-mdbook-preprocessor", + "paisano-tui": "paisano-tui_2", + "yants": "yants_3" + }, "locked": { - "lastModified": 1702771826, - "narHash": "sha256-4jFlIYY/hzkRrt4mXpUV81wC9ge4VpC5zcmQANl8GQg=", - "owner": "input-output-hk", - "repo": "stackage.nix", - "rev": "4aab61a73de63a828ac33eb588e1e65411020a0c", + "lastModified": 1687300684, + "narHash": "sha256-oBqbss0j+B568GoO3nF2BCoPEgPxUjxfZQGynW6mhEk=", + "owner": "divnix", + "repo": "std", + "rev": "80e5792eae98353a97ab1e85f3fba2784e4a3690", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "stackage.nix", + "owner": "divnix", + "repo": "std", "type": "github" } }, - "stackage_7": { - "flake": false, + "std_4": { + "inputs": { + "blank": "blank_4", + "devshell": "devshell_5", + "dmerge": "dmerge_4", + "flake-utils": "flake-utils_18", + "makes": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor", + "microvm": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "n2c": "n2c_4", + "nixago": "nixago_4", + "nixpkgs": "nixpkgs_33", + "yants": "yants_4" + }, "locked": { - "lastModified": 1654219171, - "narHash": "sha256-5kp4VTlum+AMmoIbhtrcVSEfYhR4oTKSrwe1iysD8uU=", - "owner": "input-output-hk", - "repo": "stackage.nix", - "rev": "6d1fc076976ce6c45da5d077bf882487076efe5c", + "lastModified": 1665513321, + "narHash": "sha256-D6Pacw9yf/HMs84KYuCxHXnNDL7v43gtcka5URagFqE=", + "owner": "divnix", + "repo": "std", + "rev": "94a90eedb9cfc115b12ae8f6622d9904788559e4", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "stackage.nix", + "owner": "divnix", + "repo": "std", "type": "github" } }, - "std": { + "std_5": { "inputs": { "arion": [ "cardano-node", - "tullia", "std", "blank" ], - "blank": "blank", - "devshell": "devshell", - "dmerge": "dmerge", - "flake-utils": "flake-utils_5", - "incl": "incl", + "blank": "blank_5", + "devshell": [ + "cardano-node", + "std", + "blank" + ], + "dmerge": "dmerge_5", + "haumea": "haumea_2", + "incl": "incl_4", + "lib": "lib", "makes": [ "cardano-node", - "tullia", "std", "blank" ], "microvm": [ "cardano-node", - "tullia", "std", "blank" ], - "n2c": "n2c", - "nixago": "nixago", - "nixpkgs": "nixpkgs_8", - "nosys": "nosys", - "yants": "yants" + "n2c": [ + "cardano-node", + "std", + "blank" + ], + "nixago": [ + "cardano-node", + "std", + "blank" + ], + "nixpkgs": "nixpkgs_37", + "paisano": "paisano_3", + "paisano-tui": "paisano-tui_3", + "terranix": [ + "cardano-node", + "std", + "blank" + ], + "yants": "yants_5" }, "locked": { - "lastModified": 1674526466, - "narHash": "sha256-tMTaS0bqLx6VJ+K+ZT6xqsXNpzvSXJTmogkraBGzymg=", + "lastModified": 1715201063, + "narHash": "sha256-LcLYV5CDhIiJs3MfxGZFKsXPR4PtfnY4toZ75GM+2Pw=", "owner": "divnix", "repo": "std", - "rev": "516387e3d8d059b50e742a2ff1909ed3c8f82826", + "rev": "b6924a7d37a46fc1dda8efe405040e27ecf1bbd6", "type": "github" }, "original": { @@ -9013,15 +14732,15 @@ "type": "github" } }, - "std_2": { + "std_6": { "inputs": { - "devshell": "devshell_7", - "dmerge": "dmerge_2", - "flake-utils": "flake-utils_13", - "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor", - "nixago": "nixago_2", - "nixpkgs": "nixpkgs_34", - "yants": "yants_3" + "devshell": "devshell_11", + "dmerge": "dmerge_6", + "flake-utils": "flake-utils_28", + "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor_2", + "nixago": "nixago_5", + "nixpkgs": "nixpkgs_63", + "yants": "yants_7" }, "locked": { "lastModified": 1661370377, @@ -9037,15 +14756,15 @@ "type": "github" } }, - "std_3": { + "std_7": { "inputs": { - "devshell": "devshell_15", - "dmerge": "dmerge_3", - "flake-utils": "flake-utils_29", - "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor_2", - "nixago": "nixago_3", - "nixpkgs": "nixpkgs_64", - "yants": "yants_5" + "devshell": "devshell_19", + "dmerge": "dmerge_7", + "flake-utils": "flake-utils_44", + "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor_3", + "nixago": "nixago_6", + "nixpkgs": "nixpkgs_93", + "yants": "yants_9" }, "locked": { "lastModified": 1661367957, @@ -9061,11 +14780,11 @@ "type": "github" } }, - "std_4": { + "std_8": { "inputs": { - "devshell": "devshell_16", - "nixpkgs": "nixpkgs_67", - "yants": "yants_6" + "devshell": "devshell_20", + "nixpkgs": "nixpkgs_96", + "yants": "yants_10" }, "locked": { "lastModified": 1652784712, @@ -9141,6 +14860,21 @@ "type": "github" } }, + "stdlib_13": { + "locked": { + "lastModified": 1590026685, + "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", + "owner": "manveru", + "repo": "nix-lib", + "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "type": "github" + }, + "original": { + "owner": "manveru", + "repo": "nix-lib", + "type": "github" + } + }, "stdlib_2": { "locked": { "lastModified": 1590026685, @@ -9211,60 +14945,150 @@ "type": "github" }, "original": { - "owner": "manveru", - "repo": "nix-lib", + "owner": "manveru", + "repo": "nix-lib", + "type": "github" + } + }, + "stdlib_7": { + "locked": { + "lastModified": 1590026685, + "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", + "owner": "manveru", + "repo": "nix-lib", + "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "type": "github" + }, + "original": { + "owner": "manveru", + "repo": "nix-lib", + "type": "github" + } + }, + "stdlib_8": { + "locked": { + "lastModified": 1590026685, + "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", + "owner": "manveru", + "repo": "nix-lib", + "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "type": "github" + }, + "original": { + "owner": "manveru", + "repo": "nix-lib", + "type": "github" + } + }, + "stdlib_9": { + "locked": { + "lastModified": 1590026685, + "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", + "owner": "manveru", + "repo": "nix-lib", + "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "type": "github" + }, + "original": { + "owner": "manveru", + "repo": "nix-lib", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", "type": "github" } }, - "stdlib_7": { + "systems_4": { "locked": { - "lastModified": 1590026685, - "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", - "owner": "manveru", - "repo": "nix-lib", - "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "manveru", - "repo": "nix-lib", + "owner": "nix-systems", + "repo": "default", "type": "github" } }, - "stdlib_8": { + "systems_5": { "locked": { - "lastModified": 1590026685, - "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", - "owner": "manveru", - "repo": "nix-lib", - "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "manveru", - "repo": "nix-lib", + "owner": "nix-systems", + "repo": "default", "type": "github" } }, - "stdlib_9": { + "systems_6": { "locked": { - "lastModified": 1590026685, - "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", - "owner": "manveru", - "repo": "nix-lib", - "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "manveru", - "repo": "nix-lib", + "owner": "nix-systems", + "repo": "default", "type": "github" } }, "tailwind-haskell": { "inputs": { - "flake-utils": "flake-utils_24", - "nixpkgs": "nixpkgs_58" + "flake-utils": "flake-utils_39", + "nixpkgs": "nixpkgs_87" }, "locked": { "lastModified": 1654211622, @@ -9281,27 +15105,38 @@ "type": "github" } }, + "terraform-providers": { + "inputs": { + "nixpkgs": "nixpkgs_12" + }, + "locked": { + "lastModified": 1695893013, + "narHash": "sha256-+5EuXNXwxpTiOEGCbZWtZCU75WcVwnS89heLa5xJ2K0=", + "owner": "nix-community", + "repo": "nixpkgs-terraform-providers-bin", + "rev": "6c6865ae6f9bff7aaa4e86c875f520f2aca65c0d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs-terraform-providers-bin", + "type": "github" + } + }, "terranix": { "inputs": { "bats-assert": "bats-assert", "bats-support": "bats-support", - "flake-utils": "flake-utils_9", - "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte", - "capsules", - "bitte", - "blank" - ], + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_13", "terranix-examples": "terranix-examples" }, "locked": { - "lastModified": 1637158331, - "narHash": "sha256-x5LEKtSkVq+D3BXHDBOb2wdCLxAhVmXIWONRi9lxDPg=", + "lastModified": 1684906298, + "narHash": "sha256-pNuJxmVMGbBHw7pa+Bx0HY0orXIXoyyAXOKuQ1zpfus=", "owner": "terranix", "repo": "terranix", - "rev": "34198bb154af86d2a559446f10d7339e53126abe", + "rev": "c0dd15076856c6cb425795b8c7d5d37d3a1e922a", "type": "github" }, "original": { @@ -9355,15 +15190,32 @@ "type": "github" } }, + "terranix-examples_4": { + "locked": { + "lastModified": 1636300201, + "narHash": "sha256-0n1je1WpiR6XfCsvi8ZK7GrpEnMl+DpwhWaO1949Vbc=", + "owner": "terranix", + "repo": "terranix-examples", + "rev": "a934aa1cf88f6bd6c6ddb4c77b77ec6e1660bd5e", + "type": "github" + }, + "original": { + "owner": "terranix", + "repo": "terranix-examples", + "type": "github" + } + }, "terranix_2": { "inputs": { "bats-assert": "bats-assert_2", "bats-support": "bats-support_2", - "flake-utils": "flake-utils_14", + "flake-utils": "flake-utils_24", "nixpkgs": [ "db-sync", "cardano-world", "bitte", + "capsules", + "bitte", "blank" ], "terranix-examples": "terranix-examples_2" @@ -9386,11 +15238,10 @@ "inputs": { "bats-assert": "bats-assert_3", "bats-support": "bats-support_3", - "flake-utils": "flake-utils_20", + "flake-utils": "flake-utils_29", "nixpkgs": [ "db-sync", "cardano-world", - "capsules", "bitte", "blank" ], @@ -9405,59 +15256,278 @@ "type": "github" }, "original": { - "owner": "terranix", - "repo": "terranix", + "owner": "terranix", + "repo": "terranix", + "type": "github" + } + }, + "terranix_4": { + "inputs": { + "bats-assert": "bats-assert_4", + "bats-support": "bats-support_4", + "flake-utils": "flake-utils_35", + "nixpkgs": [ + "db-sync", + "cardano-world", + "capsules", + "bitte", + "blank" + ], + "terranix-examples": "terranix-examples_4" + }, + "locked": { + "lastModified": 1637158331, + "narHash": "sha256-x5LEKtSkVq+D3BXHDBOb2wdCLxAhVmXIWONRi9lxDPg=", + "owner": "terranix", + "repo": "terranix", + "rev": "34198bb154af86d2a559446f10d7339e53126abe", + "type": "github" + }, + "original": { + "owner": "terranix", + "repo": "terranix", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": "nixpkgs_5" + }, + "locked": { + "lastModified": 1683117219, + "narHash": "sha256-IyNRNRxw0slA3VQySVA7QPXHMOxlbx0ePWvj9oln+Wk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "c8c3731dc404f837f38f89c2c5ffc2afc02e249d", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_2": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1691440708, + "narHash": "sha256-c7Cc08vJ0IPFgIERpTdO2xvDHQNL7Uf5iXT0GlYO6vo=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "2a535809ac5c9a32288f4d3b938296e056d948cc", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_3": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697388351, + "narHash": "sha256-63N2eBpKaziIy4R44vjpUu8Nz5fCJY7okKrkixvDQmY=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "aae39f64f5ecbe89792d05eacea5cb241891292a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "tullia": { + "inputs": { + "nix-nomad": "nix-nomad", + "nix2container": "nix2container_2", + "nixpkgs": "nixpkgs_20", + "std": "std" + }, + "locked": { + "lastModified": 1675695930, + "narHash": "sha256-B7rEZ/DBUMlK1AcJ9ajnAPPxqXY6zW2SBX+51bZV0Ac=", + "owner": "input-output-hk", + "repo": "tullia", + "rev": "621365f2c725608f381b3ad5b57afef389fd4c31", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "tullia", + "type": "github" + } + }, + "tullia_2": { + "inputs": { + "nix-nomad": "nix-nomad_2", + "nix2container": "nix2container_3", + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "nixpkgs" + ], + "std": "std_2" + }, + "locked": { + "lastModified": 1684859161, + "narHash": "sha256-wOKutImA7CRL0rN+Ng80E72fD5FkVub7LLP2k9NICpg=", + "owner": "input-output-hk", + "repo": "tullia", + "rev": "2964cff1a16eefe301bdddb508c49d94d04603d6", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "tullia", + "type": "github" + } + }, + "tullia_3": { + "inputs": { + "nix-nomad": "nix-nomad_3", + "nix2container": "nix2container_5", + "nixpkgs": [ + "cardano-node", + "cardano-automation", + "nixpkgs" + ], + "std": "std_4" + }, + "locked": { + "lastModified": 1668711738, + "narHash": "sha256-CBjky16o9pqsGE1bWu6nRlRajgSXMEk+yaFQLibqXcE=", + "owner": "input-output-hk", + "repo": "tullia", + "rev": "ead1f515c251f0e060060ef0e2356a51d3dfe4b0", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "tullia", + "type": "github" + } + }, + "tullia_4": { + "inputs": { + "nix2container": "nix2container_7", + "nixpkgs": "nixpkgs_95", + "std": "std_8" + }, + "locked": { + "lastModified": 1657811465, + "narHash": "sha256-KHNWwKuUIG08CUg/ol81zf26RRlnsQsyqMr63vXcCes=", + "owner": "input-output-hk", + "repo": "tullia", + "rev": "f025fcf3676d1d1281de184e89c5f7c8e7f74ebe", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "tullia", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_10": { + "locked": { + "lastModified": 1633020561, + "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", + "owner": "kreisys", + "repo": "flake-utils", + "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "type": "github" + }, + "original": { + "owner": "kreisys", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_11": { + "locked": { + "lastModified": 1633020561, + "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", + "owner": "kreisys", + "repo": "flake-utils", + "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "type": "github" + }, + "original": { + "owner": "kreisys", + "repo": "flake-utils", "type": "github" } }, - "tullia": { - "inputs": { - "nix-nomad": "nix-nomad", - "nix2container": "nix2container_2", - "nixpkgs": "nixpkgs_7", - "std": "std" - }, + "utils_12": { "locked": { - "lastModified": 1675695930, - "narHash": "sha256-B7rEZ/DBUMlK1AcJ9ajnAPPxqXY6zW2SBX+51bZV0Ac=", - "owner": "input-output-hk", - "repo": "tullia", - "rev": "621365f2c725608f381b3ad5b57afef389fd4c31", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "tullia", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "tullia_2": { - "inputs": { - "nix2container": "nix2container_3", - "nixpkgs": "nixpkgs_66", - "std": "std_4" - }, + "utils_13": { "locked": { - "lastModified": 1657811465, - "narHash": "sha256-KHNWwKuUIG08CUg/ol81zf26RRlnsQsyqMr63vXcCes=", - "owner": "input-output-hk", - "repo": "tullia", - "rev": "f025fcf3676d1d1281de184e89c5f7c8e7f74ebe", + "lastModified": 1633020561, + "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", + "owner": "kreisys", + "repo": "flake-utils", + "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "tullia", + "owner": "kreisys", + "repo": "flake-utils", "type": "github" } }, - "utils": { + "utils_14": { "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "lastModified": 1637014545, + "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", "type": "github" }, "original": { @@ -9466,7 +15536,7 @@ "type": "github" } }, - "utils_10": { + "utils_15": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9481,7 +15551,7 @@ "type": "github" } }, - "utils_11": { + "utils_16": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9496,7 +15566,7 @@ "type": "github" } }, - "utils_12": { + "utils_17": { "locked": { "lastModified": 1638122382, "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", @@ -9511,7 +15581,7 @@ "type": "github" } }, - "utils_13": { + "utils_18": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9526,7 +15596,7 @@ "type": "github" } }, - "utils_14": { + "utils_19": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9541,7 +15611,22 @@ "type": "github" } }, - "utils_15": { + "utils_2": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_20": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9556,7 +15641,7 @@ "type": "github" } }, - "utils_16": { + "utils_21": { "locked": { "lastModified": 1644229661, "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", @@ -9571,7 +15656,7 @@ "type": "github" } }, - "utils_17": { + "utils_22": { "locked": { "lastModified": 1637014545, "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", @@ -9586,7 +15671,7 @@ "type": "github" } }, - "utils_18": { + "utils_23": { "locked": { "lastModified": 1601282935, "narHash": "sha256-WQAFV6sGGQxrRs3a+/Yj9xUYvhTpukQJIcMbIi7LCJ4=", @@ -9601,7 +15686,7 @@ "type": "github" } }, - "utils_19": { + "utils_24": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9616,22 +15701,7 @@ "type": "github" } }, - "utils_2": { - "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "utils_20": { + "utils_25": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9646,7 +15716,7 @@ "type": "github" } }, - "utils_21": { + "utils_26": { "locked": { "lastModified": 1638122382, "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", @@ -9661,7 +15731,7 @@ "type": "github" } }, - "utils_22": { + "utils_27": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9676,7 +15746,7 @@ "type": "github" } }, - "utils_23": { + "utils_28": { "locked": { "lastModified": 1638122382, "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", @@ -9693,11 +15763,11 @@ }, "utils_3": { "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "owner": "numtide", "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { @@ -9708,11 +15778,11 @@ }, "utils_4": { "locked": { - "lastModified": 1601282935, - "narHash": "sha256-WQAFV6sGGQxrRs3a+/Yj9xUYvhTpukQJIcMbIi7LCJ4=", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "588973065fce51f4763287f0fda87a174d78bf48", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { @@ -9723,41 +15793,44 @@ }, "utils_5": { "locked": { - "lastModified": 1633020561, - "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", - "owner": "kreisys", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", "repo": "flake-utils", - "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { - "owner": "kreisys", + "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "utils_6": { "locked": { - "lastModified": 1633020561, - "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", - "owner": "kreisys", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", "repo": "flake-utils", - "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "kreisys", + "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "utils_7": { + "inputs": { + "systems": "systems_6" + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -9768,26 +15841,26 @@ }, "utils_8": { "locked": { - "lastModified": 1633020561, - "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", - "owner": "kreisys", + "lastModified": 1637014545, + "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "owner": "numtide", "repo": "flake-utils", - "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", "type": "github" }, "original": { - "owner": "kreisys", + "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "utils_9": { "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "lastModified": 1601282935, + "narHash": "sha256-WQAFV6sGGQxrRs3a+/Yj9xUYvhTpukQJIcMbIi7LCJ4=", "owner": "numtide", "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "rev": "588973065fce51f4763287f0fda87a174d78bf48", "type": "github" }, "original": { @@ -9833,7 +15906,8 @@ "yants": { "inputs": { "nixpkgs": [ - "cardano-node", + "cardano-nix", + "cardano-node-8.1.1", "tullia", "std", "nixpkgs" @@ -9853,9 +15927,15 @@ "type": "github" } }, - "yants_2": { + "yants_10": { "inputs": { - "nixpkgs": "nixpkgs_25" + "nixpkgs": [ + "db-sync", + "cardano-world", + "tullia", + "std", + "nixpkgs" + ] }, "locked": { "lastModified": 1645126146, @@ -9871,22 +15951,47 @@ "type": "github" } }, + "yants_2": { + "inputs": { + "nixpkgs": [ + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1667096281, + "narHash": "sha256-wRRec6ze0gJHmGn6m57/zhz/Kdvp9HS4Nl5fkQ+uIuA=", + "owner": "divnix", + "repo": "yants", + "rev": "d18f356ec25cb94dc9c275870c3a7927a10f8c3c", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "yants", + "type": "github" + } + }, "yants_3": { "inputs": { "nixpkgs": [ - "db-sync", - "cardano-world", - "bitte", + "cardano-nix", + "cardano-node-8.7.3", "std", + "haumea", "nixpkgs" ] }, "locked": { - "lastModified": 1645126146, - "narHash": "sha256-XQ1eg4gzXoc7Tl8iXak1uCt3KnsTyxqPtLE+vOoDnrQ=", + "lastModified": 1686863218, + "narHash": "sha256-kooxYm3/3ornWtVBNHM3Zh020gACUyFX2G0VQXnB+mk=", "owner": "divnix", "repo": "yants", - "rev": "77df2be1b3cce9f571c6cf451f786b266a6869cc", + "rev": "8f0da0dba57149676aa4817ec0c880fbde7a648d", "type": "github" }, "original": { @@ -9897,7 +16002,53 @@ }, "yants_4": { "inputs": { - "nixpkgs": "nixpkgs_60" + "nixpkgs": [ + "cardano-node", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660507851, + "narHash": "sha256-BKjq7JnVuUR/xDtcv6Vm9GYGKAblisXrAgybor9hT/s=", + "owner": "divnix", + "repo": "yants", + "rev": "0b895ca02a8fa72bad50b454cb3e7d8a66407c96", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "yants", + "type": "github" + } + }, + "yants_5": { + "inputs": { + "nixpkgs": [ + "cardano-node", + "std", + "lib" + ] + }, + "locked": { + "lastModified": 1686863218, + "narHash": "sha256-kooxYm3/3ornWtVBNHM3Zh020gACUyFX2G0VQXnB+mk=", + "owner": "divnix", + "repo": "yants", + "rev": "8f0da0dba57149676aa4817ec0c880fbde7a648d", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "yants", + "type": "github" + } + }, + "yants_6": { + "inputs": { + "nixpkgs": "nixpkgs_54" }, "locked": { "lastModified": 1645126146, @@ -9913,11 +16064,12 @@ "type": "github" } }, - "yants_5": { + "yants_7": { "inputs": { "nixpkgs": [ "db-sync", "cardano-world", + "bitte", "std", "nixpkgs" ] @@ -9936,12 +16088,29 @@ "type": "github" } }, - "yants_6": { + "yants_8": { + "inputs": { + "nixpkgs": "nixpkgs_89" + }, + "locked": { + "lastModified": 1645126146, + "narHash": "sha256-XQ1eg4gzXoc7Tl8iXak1uCt3KnsTyxqPtLE+vOoDnrQ=", + "owner": "divnix", + "repo": "yants", + "rev": "77df2be1b3cce9f571c6cf451f786b266a6869cc", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "yants", + "type": "github" + } + }, + "yants_9": { "inputs": { "nixpkgs": [ "db-sync", "cardano-world", - "tullia", "std", "nixpkgs" ] diff --git a/flake.nix b/flake.nix index a38d4555d1..047c6de0b2 100644 --- a/flake.nix +++ b/flake.nix @@ -9,6 +9,7 @@ inputs = { nixpkgs.follows = "haskell-nix/nixpkgs-unstable"; + nixpkgs-arion.url = "github:NixOS/nixpkgs"; hackage-nix = { url = "github:input-output-hk/hackage.nix"; flake = false; @@ -32,41 +33,28 @@ flake = false; }; - cardano-node.url = "github:input-output-hk/cardano-node/8.1.1"; + cardano-node.url = "github:input-output-hk/cardano-node/4f4e372a1641ac68cd09fb0339e6f55bef1ab85d"; - ogmios-nixos = { - url = "github:mlabs-haskell/ogmios-nixos/78e829e9ebd50c5891024dcd1004c2ac51facd80"; - inputs = { - nixpkgs.follows = "nixpkgs"; - iohk-nix.follows = "iohk-nix"; - haskell-nix.follows = "haskell-nix"; - cardano-node.follows = "cardano-node"; - ogmios-src.follows = "ogmios"; - }; - }; - - ogmios = { - url = "github:CardanoSolutions/ogmios/v6.0.0"; + # Repository with network parameters + # NOTE(bladyjoker): Cardano configurations (yaml/json) often change format and break, that's why we pin to a specific known version. + cardano-configurations = { + # Override with "path:/path/to/cardano-configurations"; + url = "github:input-output-hk/cardano-configurations?rev=7969a73e5c7ee1f3b2a40274b34191fdd8de170b"; flake = false; }; - kupo-nixos = { - url = "github:mlabs-haskell/kupo-nixos/6f89cbcc359893a2aea14dd380f9a45e04c6aa67"; - inputs.kupo.follows = "kupo"; + # Get Ogmios and Kupo from cardano-nix + cardano-nix = { + url = "github:mlabs-haskell/cardano.nix"; + inputs.nixpkgs.follows = "nixpkgs"; }; - kupo = { - url = "github:CardanoSolutions/kupo/v2.2.0"; + # Get Ogmios test fixtures + ogmios = { + url = "github:CardanoSolutions/ogmios/v6.5.0"; flake = false; }; - # Repository with network parameters - # NOTE(bladyjoker): Cardano configurations (yaml/json) often change format and break, that's why we pin to a specific known version. - cardano-configurations = { - # Override with "path:/path/to/cardano-configurations"; - url = "github:input-output-hk/cardano-configurations?rev=d952529afdfdf6d53ce190b1bf8af990a7ae9590"; - flake = false; - }; easy-purescript-nix = { url = "github:justinwoo/easy-purescript-nix"; flake = false; @@ -75,26 +63,15 @@ blockfrost.url = "github:blockfrost/blockfrost-backend-ryo/v1.7.0"; db-sync.url = "github:input-output-hk/cardano-db-sync/13.1.0.0"; - # Plutip server related inputs - plutip = { - url = "github:mlabs-haskell/plutip?ref=gergely/version-bump"; - # TODO(bladyjoker): Why are we overriding inputs here? - inputs = { - nixpkgs.follows = "nixpkgs"; - iohk-nix.follows = "iohk-nix"; - haskell-nix.follows = "haskell-nix"; - hackage-nix.follows = "hackage-nix"; - cardano-node.follows = "cardano-node"; - }; - }; - hercules-ci-effects.url = "github:hercules-ci/hercules-ci-effects"; }; outputs = { self , nixpkgs + , nixpkgs-arion , cardano-configurations + , cardano-node , ... }@inputs: let @@ -105,12 +82,16 @@ "aarch64-darwin" ]; + ogmiosVersion = "6.5.0"; + kupoVersion = "2.9.0"; + perSystem = nixpkgs.lib.genAttrs supportedSystems; mkNixpkgsFor = system: import nixpkgs { overlays = nixpkgs.lib.attrValues self.overlays ++ [ (_: _: { ogmios-fixtures = inputs.ogmios; + arion = (import nixpkgs-arion { inherit system; }).arion; }) ]; inherit system; @@ -186,6 +167,7 @@ packages = with pkgs; [ arion fd + psmisc nixpkgs-fmt nodePackages.eslint nodePackages.prettier @@ -225,15 +207,15 @@ name = "ctl-e2e-test"; runnerMain = "Test.Ctl.E2E"; testMain = "Ctl.Examples.ByUrl"; - buildInputs = [ inputs.kupo-nixos.packages.${pkgs.system}.kupo ]; + buildInputs = [ inputs.cardano-nix.packages.${pkgs.system}."kupo-${kupoVersion}" ]; }; - ctl-plutip-test = project.runPlutipTest { - name = "ctl-plutip-test"; - testMain = "Test.Ctl.Plutip"; + ctl-local-testnet-test = project.runLocalTestnetTest { + name = "ctl-local-testnet-test"; + testMain = "Test.Ctl.Testnet"; }; - ctl-staking-test = project.runPlutipTest { + ctl-staking-test = project.runLocalTestnetTest { name = "ctl-staking-test"; - testMain = "Test.Ctl.Plutip.Staking"; + testMain = "Test.Ctl.Testnet.Staking"; }; ctl-unit-test = project.runPursTest { name = "ctl-unit-test"; @@ -244,6 +226,8 @@ devShell = project.devShell; + nodeModules = project.nodeModules; + apps = { # TODO: restore this # https://github.com/Plutonomicon/cardano-transaction-lib/issues/1578 @@ -252,23 +236,6 @@ # }; }; }; - - plutipServerFor = system: - let - pkgs = import inputs.nixpkgs { - inherit system; - overlays = [ - inputs.haskell-nix.overlay - inputs.iohk-nix.overlays.crypto - ]; - }; - in - import ./plutip-server { - inherit pkgs; - inherit (inputs) plutip CHaP cardano-node; - inherit (pkgs) system; - src = ./plutip-server; - }; in { overlay = builtins.trace @@ -313,10 +280,11 @@ inherit (prev) system; in { - plutip-server = - (plutipServerFor system).hsPkgs.plutip-server.components.exes.plutip-server; - ogmios = ogmios-nixos.packages.${system}."ogmios:exe:ogmios"; - kupo = inputs.kupo-nixos.packages.${system}.kupo; + ogmios = cardano-nix.packages.${system}."ogmios-${ogmiosVersion}"; + cardano-testnet = cardano-node.packages.${system}.cardano-testnet; + cardano-node = cardano-node.packages.${system}.cardano-node; + cardano-cli = cardano-node.packages.${system}.cardano-cli; + kupo = cardano-nix.packages.${system}."kupo-${kupoVersion}"; cardano-db-sync = inputs.db-sync.packages.${system}.cardano-db-sync; blockfrost-backend-ryo = inputs.blockfrost.packages.${system}.blockfrost-backend-ryo; buildCtlRuntime = buildCtlRuntime final; @@ -326,21 +294,14 @@ ); }; - # flake from haskell.nix project - hsFlake = perSystem (system: (plutipServerFor system).flake { }); - devShells = perSystem (system: { # This is the default `devShell` and can be run without specifying # it (i.e. `nix develop`) default = (psProjectFor (nixpkgsFor system)).devShell; - - # This can be used with `nix develop .#devPlutipServer` to work with `./plutip-server` - devPlutipServer = ((plutipServerFor system).flake { }).devShell; }); packages = perSystem (system: (psProjectFor (nixpkgsFor system)).packages - // ((plutipServerFor system).flake { }).packages ); apps = perSystem (system: @@ -365,9 +326,9 @@ checks = perSystem (system: let pkgs = nixpkgsFor system; - + psProject = psProjectFor pkgs; in - (psProjectFor pkgs).checks + psProject.checks // { formatting-check = pkgs.runCommand "formatting-check" { @@ -380,7 +341,10 @@ ]; } '' - cd ${self} + cd $TMPDIR + ln -sfn ${psProject.nodeModules}/lib/node_modules node_modules + cp -r ${self}/* . + make check-format touch $out ''; @@ -391,10 +355,12 @@ nativeBuildInputs = [ pkgs.jq ]; } '' cd ${self} - diff <(jq -S .dependencies <<< $ctlPackageJson) <(jq -S .dependencies <<< $ctlScaffoldPackageJson) - # We don't want to include `doctoc` in the template dev dependencies. diff \ - <(jq -S '.devDependencies | del(.doctoc)' <<< $ctlPackageJson) \ + <(jq -S .dependencies <<< $ctlPackageJson) \ + <(jq -S .dependencies <<< $ctlScaffoldPackageJson) + # We don't want to include some dev dependencies. + diff \ + <(jq -S '.devDependencies | del(.jssha) | del(.blakejs) | del(.doctoc) | del(.globals) | del(.["@eslint/js"])' <<< $ctlPackageJson) \ <(jq -S .devDependencies <<< $ctlScaffoldPackageJson) touch $out ''; @@ -508,16 +474,18 @@ }; }; - nixosConfigurations.test = nixpkgs.lib.nixosSystem { + nixosConfigurations.test = nixpkgs.lib.nixosSystem rec { system = "x86_64-linux"; modules = [ inputs.cardano-node.nixosModules.cardano-node - inputs.ogmios-nixos.nixosModules.ogmios - inputs.kupo-nixos.nixosModules.kupo + inputs.cardano-nix.nixosModules.ogmios + inputs.cardano-nix.nixosModules.kupo ./nix/test-nixos-configuration.nix ]; specialArgs = { inherit (inputs) cardano-configurations; + ogmios = inputs.cardano-nix.packages.${system}."ogmios-${ogmiosVersion}"; + kupo = inputs.cardano-nix.packages.${system}."kupo-${kupoVersion}"; }; }; diff --git a/nix/default.nix b/nix/default.nix index 9821b1e6b9..55f0f8af27 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -89,10 +89,10 @@ let , packageLockOnly ? false # If `true`, all of CTL's runtime dependencies will be added to the # shell's `packages`. These packages are *required* if you plan on running - # Plutip tests in your local shell environment (that is, not using Nix - # directly as with `runPlutipTest`). Make sure you have applied - # `overlays.runtime` or otherwise added the runtime packages to your - # package set if you select this option! + # cardano-testnet tests in your local shell environment (that is, not + # using Nix directly as with `runLocalTestnetTest`). Make sure you have + # applied `overlays.runtime` or otherwise added the runtime packages to + # your package set if you select this option! , withRuntime ? true # If `true`, the `chromium` package from your package set will be made # available in the shell environment. This can help with ensuring that @@ -132,8 +132,10 @@ let lists.optional withRuntime ( [ pkgs.ogmios - pkgs.plutip-server pkgs.kupo + pkgs.cardano-testnet + pkgs.cardano-node + pkgs.cardano-cli ] ) ) @@ -319,6 +321,12 @@ let # Provide NPM dependencies to the test suite scripts ln -sfn ${nodeModules}/lib/node_modules node_modules + # This line fixes an issue where the hedgehog output generated by cardano-testnet + # was not being handled, making it impossible to extract cardano-testnet + # workspace information and thus causing cluster initialization to fail. + # see https://github.com/hedgehogqa/haskell-hedgehog/issues/110 + export LC_ALL=C.UTF-8 + # Call the main module and execute the entry point function ${nodejs}/bin/node --enable-source-maps -e 'import("./output/${testMain}/index.js").then(m => m.${psEntryPoint}())' @@ -326,23 +334,28 @@ let touch $out ''; - # Runs a test using Plutip. Takes the same arguments as `runPursTest` + # Runs a test using cardano-testnet. Takes the same arguments as `runPursTest` # # NOTE: You *must* either use CTL's `overlays.runtime` or otherwise make the # the following required `buildInputs` available in your own package set: # # - `ogmios` # - `kupo` - # - `plutip-server` + # - `cardano-testnet` + # - `cardano-node` + # - `cardano-cli` # - runPlutipTest = + runLocalTestnetTest = args: runPursTest ( args // { buildInputs = with pkgs; [ ogmios - plutip-server kupo + cardano-testnet + cardano-node + cardano-cli + psmisc ] ++ (args.buildInputs or [ ]); } @@ -435,9 +448,11 @@ let nodeModules ogmios kupo - plutip-server + cardano-testnet + cardano-node + cardano-cli chromium - python38 # To serve bundled CTL + python39 # To serve bundled CTL # Utils needed by E2E test code which # used to check for browser availability gnutar # used unpack settings archive within E2E test code @@ -485,6 +500,8 @@ let cp -r $src/* . chmod -R +rw . + export LC_ALL=C.UTF-8 + ${nodejs}/bin/node \ --enable-source-maps \ -e 'import("./output/${runnerMain}/index.js").then(m => m.${runnerPsEntryPoint}())' \ @@ -612,7 +629,7 @@ let in { inherit - buildPursProject buildPursDependencies runPursTest runPlutipTest runE2ETest + buildPursProject buildPursDependencies runPursTest runLocalTestnetTest runE2ETest bundlePursProjectEsbuild bundlePursProjectWebpack buildPursDocs # TODO: restore buildSearchablePursDocs and launchSearchablePursDocs diff --git a/nix/runtime.nix b/nix/runtime.nix index c03e5bc572..45dd521efb 100644 --- a/nix/runtime.nix +++ b/nix/runtime.nix @@ -3,6 +3,8 @@ rec { defaultConfig = final: with final; { inherit (inputs) cardano-configurations; # { name = "preprod"; magic = 1; } + # { name = "preview"; magic = 2; } + # { name = "sanchonet"; magic = 4; } # { name = "mainnet"; magic = null; } # See `doc/development.md` and `doc/runtime.md#changing-network-configurations` # for info on how to switch networks. @@ -27,7 +29,6 @@ rec { port = 1442; since = "origin"; match = "*/*"; # matches Shelley addresses only - tag = "v2.2.0"; deferDbIndexes = true; # whether to pass --defer-db-indexes pruneUtxo = true; # whether to pass --prune-utxo # TODO: Do we want to support connection through ogmios? @@ -137,7 +138,7 @@ rec { "${pkgs.bash}/bin/sh" "-c" '' - ${inputs.kupo-nixos.packages.${pkgs.system}.kupo}/bin/kupo \ + ${pkgs.kupo}/bin/kupo \ --node-config /config/cardano-node/config.json \ --node-socket "${nodeSocketPath}" \ --since "${kupo.since}" \ diff --git a/nix/test-nixos-configuration.nix b/nix/test-nixos-configuration.nix index bbfe022e92..df7781e2f7 100644 --- a/nix/test-nixos-configuration.nix +++ b/nix/test-nixos-configuration.nix @@ -1,10 +1,11 @@ -{ config, modulesPath, pkgs, cardano-configurations, ... }: +{ config, modulesPath, pkgs, cardano-configurations, ogmios, kupo, ... }: { imports = [ "${modulesPath}/virtualisation/qemu-vm.nix" ]; virtualisation = { memorySize = 8192; diskSize = 100000; + restrictNetwork = false; forwardPorts = [ # SSH { from = "host"; host.port = 2222; guest.port = 22; } @@ -23,27 +24,38 @@ users.extraUsers.root.password = ""; users.mutableUsers = false; + environment.systemPackages = with pkgs; [ + lsof + ]; + # services services.cardano-node = { enable = true; - systemdSocketActivation = true; - nodeConfigFile = "${cardano-configurations}/network/mainnet/cardano-node/config.json"; - topology = "${cardano-configurations}/network/mainnet/cardano-node/topology.json"; + hostAddr = "0.0.0.0"; + socketPath = "/var/run/cardano-node/node.socket"; + systemdSocketActivation = false; + nodeConfigFile = "${cardano-configurations}/network/preview/cardano-node/config.json"; + topology = "${cardano-configurations}/network/preview/cardano-node/topology.json"; }; services.ogmios = { enable = true; + package = ogmios; host = "0.0.0.0"; - nodeSocket = "/var/run/cardano-node/node.socket"; + user = "cardano-node"; + group = "cardano-node"; + nodeSocketPath = "/var/run/cardano-node/node.socket"; + nodeConfigPath = "${cardano-configurations}/network/preview/cardano-node/config.json"; }; services.kupo = { enable = true; + package = kupo; + user = "cardano-node"; + group = "cardano-node"; host = "0.0.0.0"; - user = "kupo"; - group = "kupo"; - nodeConfig = "${cardano-configurations}/network/mainnet/cardano-node/config.json"; - nodeSocket = "/var/run/cardano-node/node.socket"; + nodeSocketPath = "/var/run/cardano-node/node.socket"; + nodeConfigPath = "${cardano-configurations}/network/preview/cardano-node/config.json"; }; } diff --git a/package-lock.json b/package-lock.json index e33f069314..d3ebd7d738 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,37 +6,36 @@ "packages": { "": { "name": "cardano-transaction-lib", - "version": "5.0.0", "license": "MIT", "dependencies": { - "@emurgo/cardano-message-signing-browser": "1.0.1", - "@emurgo/cardano-message-signing-nodejs": "1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc-browser": "^1.0.6", - "@mlabs-haskell/cardano-serialization-lib-gc-nodejs": "^1.0.6", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1", + "@mlabs-haskell/cardano-message-signing": "^1.0.1", + "@mlabs-haskell/cardano-serialization-lib-gc": "12.0.0-alpha.31", "@mlabs-haskell/json-bigint": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "1.0.29-alpha", "@noble/secp256k1": "^1.7.0", - "apply-args-browser": "0.0.1", - "apply-args-nodejs": "0.0.1", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", "bip39": "^3.1.0", - "blakejs": "1.2.1", "bufferutil": "4.0.5", - "jssha": "3.2.0", + "isomorphic-ws": "^5.0.0", "puppeteer-core": "^15.3.2", "reconnecting-websocket": "4.4.0", "uniqid": "5.4.0", "utf-8-validate": "^5.0.10", - "ws": "8.4.0", + "web-encoding": "^1.1.5", + "ws": "^8.16.0", "xhr2": "0.2.1" }, "devDependencies": { + "@eslint/js": "^9.7.0", + "blakejs": "1.2.1", "buffer": "6.0.3", "doctoc": "^2.2.1", "esbuild": "0.18.11", "esbuild-plugin-polyfill-node": "^0.3.0", "esbuild-plugin-wasm": "^1.1.0", + "globals": "^15.8.0", + "jssha": "3.2.0", "node-polyfill-webpack-plugin": "2.0.1", "webpack": "5.88.1", "webpack-cli": "5.1.4", @@ -63,14 +62,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "node_modules/@emurgo/cardano-serialization-lib-browser": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.4.0.tgz", - "integrity": "sha512-VWMvLRBFo7MAYh42zledURFs5BpMTWvkP4DzsLNbyJxZlwjDS+bPyehJVyGc116d2gq8NHFmANbfdeuK8ffJ7A==" + "version": "12.0.0-alpha.32", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.32.tgz", + "integrity": "sha512-Pe2cUB69zLRKLsk0orj2C6drntJXK3P9l9rBmK3tzJTlUUuYWECPY8IhnLNmax3YborYOxY3bJBucTf/zqBHeA==" }, "node_modules/@emurgo/cardano-serialization-lib-nodejs": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.4.0.tgz", - "integrity": "sha512-dMiofDcqv+IrAITCgWBZmsMLqwv2xImDsJDSrKiYYG1zRKaL8XfMOxx6S0WEnKVj5/343Q5FFURYcSu3iBRNMQ==" + "version": "12.0.0-alpha.32", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.32.tgz", + "integrity": "sha512-HykivQs8K4f2KNRcXFw+D91llAxZhu1neKPVYwyWe6nYZPW/9Tn1A9p602ceGmF0LxIeiJBg0GYOufAA5yVsUQ==" }, "node_modules/@esbuild/android-arm": { "version": "0.18.11", @@ -424,6 +423,15 @@ "node": ">=12" } }, + "node_modules/@eslint/js": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz", + "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -494,34 +502,54 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, - "node_modules/@mlabs-haskell/cardano-serialization-lib-gc-browser": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc-browser/-/cardano-serialization-lib-gc-browser-1.0.6.tgz", - "integrity": "sha512-b7dLrrhjUJSdsmjzariCZO734NB+M/ONLGBiQ/TQzMRtsMydqSFQg6WbMdwYPustoNmQOg6a8bm9+RgllqdmFw==", + "node_modules/@mlabs-haskell/cardano-message-signing": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-message-signing/-/cardano-message-signing-1.0.1.tgz", + "integrity": "sha512-LNX+Msq1rJ86d5mmaR2Om5tUqB0ZthfE69fpsZcxOYDHNw5s+qtcCyNEmzAWfHC+uIJ4NDEJA8Gk2RfWto7ChA==", "dependencies": { - "@emurgo/cardano-serialization-lib-browser": "^11.2.1", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1" + "@emurgo/cardano-message-signing-browser": "^1.0.1", + "@emurgo/cardano-message-signing-nodejs": "^1.0.1" } }, - "node_modules/@mlabs-haskell/cardano-serialization-lib-gc-nodejs": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc-nodejs/-/cardano-serialization-lib-gc-nodejs-1.0.6.tgz", - "integrity": "sha512-I1FqhjEHgib+y0+6K1tSqvrtldRvqjrM5mL+TW9224ezEDScQeCroPWbgGBwwi6rjkN9YpS8Uz6gC0vo8lua1A==", + "node_modules/@mlabs-haskell/cardano-serialization-lib-gc": { + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", + "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", "dependencies": { - "@emurgo/cardano-serialization-lib-nodejs": "^11.4.0", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1" + "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", + "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, "node_modules/@mlabs-haskell/csl-gc-wrapper": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/csl-gc-wrapper/-/csl-gc-wrapper-1.0.1.tgz", - "integrity": "sha512-8pEb4BoQlD5zN+KtOCgtTg62OmLPjMa+DiJvoAzlLcWmp01P3TyJPgbEOtS+xiZpGA+1rRkdyeeLZV3wyw8Xfw==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/csl-gc-wrapper/-/csl-gc-wrapper-1.0.2.tgz", + "integrity": "sha512-jyASltvC/ZVzpMUgbIkIaCLc56uGqymCPnieLkgIMWPhzcRoAxEfshjYONyxPY5XIl0NdIQXjbppXFoPQMk0VQ==" }, "node_modules/@mlabs-haskell/json-bigint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@mlabs-haskell/json-bigint/-/json-bigint-2.0.0.tgz", "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, + "node_modules/@mlabs-haskell/uplc-apply-args": { + "version": "1.0.29-alpha", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-1.0.29-alpha.tgz", + "integrity": "sha512-eTazItNZlOvuK/ZNHBKUOM3fL1mhRaY0GFYPtalo6PrkGcwZeSzlD6+B8Mbgmb18HusDZPSRi3zhp/urxOygFA==", + "dependencies": { + "@mlabs-haskell/uplc-apply-args-browser": "^1.0.29-alpha", + "@mlabs-haskell/uplc-apply-args-nodejs": "^1.0.29-alpha2" + } + }, + "node_modules/@mlabs-haskell/uplc-apply-args-browser": { + "version": "1.0.29-alpha", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-1.0.29-alpha.tgz", + "integrity": "sha512-U/FEEI1UbHGRLblNHX4WxF5KpPR3S/C1rgXvN8X6gL2CDc4iAqvbP88d5vqwLL+seG2aO4pqqJXQnnKtlLHk7A==" + }, + "node_modules/@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "1.0.29-alpha2", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-1.0.29-alpha2.tgz", + "integrity": "sha512-91Lfk0SGH3cEHGE/F/If9lot42OJ6+bpM4HsHZr5PDvHFNOICFdTwLq/6BFmIClCkdZZNuDZIc1EpRCBgtdROw==" + }, "node_modules/@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -980,6 +1008,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -1135,16 +1169,6 @@ "node": ">= 8" } }, - "node_modules/apply-args-browser": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-browser/-/apply-args-browser-0.0.1.tgz", - "integrity": "sha512-gq4ldo4Fk5SEVpeW/0yBe0v5g3VDEWAm9LB80zGarYtDvojTD7ar0Y/WvIy9gYAkKmlE3USu5wYwKKCqOXfNkg==" - }, - "node_modules/apply-args-nodejs": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-nodejs/-/apply-args-nodejs-0.0.1.tgz", - "integrity": "sha512-JwZPEvEDrL+4y16Un6FcNjDSITpsBykchgwPh8UtxnziYrbxKAc2BUfyC5uvA6ZVIhQjiO4r+Kg1MQ3nqWk+1Q==" - }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -1185,7 +1209,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -1307,7 +1330,8 @@ "node_modules/blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "dev": true }, "node_modules/bn.js": { "version": "5.2.1", @@ -1611,7 +1635,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -2741,7 +2764,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, "dependencies": { "is-callable": "^1.1.3" } @@ -2806,14 +2828,12 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -2875,11 +2895,22 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/globals": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", + "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -2903,7 +2934,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -2936,7 +2966,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -2948,7 +2977,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -2960,7 +2988,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -3322,7 +3349,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -3373,7 +3399,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -3431,7 +3456,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -3526,7 +3550,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, "dependencies": { "which-typed-array": "^1.1.11" }, @@ -3570,6 +3593,14 @@ "node": ">=0.10.0" } }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "peerDependencies": { + "ws": "*" + } + }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -3600,6 +3631,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.2.0.tgz", "integrity": "sha512-QuruyBENDWdN4tZwJbQq7/eAK85FqrI4oDbXjy5IBhYD+2pTJyBUWZe8ctWaCkrV0gy6AaelgOZZBMeswEa/6Q==", + "dev": true, "engines": { "node": "*" } @@ -5806,7 +5838,6 @@ "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", @@ -5905,6 +5936,17 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -6199,27 +6241,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/webpack-merge": { "version": "5.9.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", @@ -6293,7 +6314,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -6320,15 +6340,15 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", - "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -6394,14 +6414,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "@emurgo/cardano-serialization-lib-browser": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.4.0.tgz", - "integrity": "sha512-VWMvLRBFo7MAYh42zledURFs5BpMTWvkP4DzsLNbyJxZlwjDS+bPyehJVyGc116d2gq8NHFmANbfdeuK8ffJ7A==" + "version": "12.0.0-alpha.32", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.32.tgz", + "integrity": "sha512-Pe2cUB69zLRKLsk0orj2C6drntJXK3P9l9rBmK3tzJTlUUuYWECPY8IhnLNmax3YborYOxY3bJBucTf/zqBHeA==" }, "@emurgo/cardano-serialization-lib-nodejs": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.4.0.tgz", - "integrity": "sha512-dMiofDcqv+IrAITCgWBZmsMLqwv2xImDsJDSrKiYYG1zRKaL8XfMOxx6S0WEnKVj5/343Q5FFURYcSu3iBRNMQ==" + "version": "12.0.0-alpha.32", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.32.tgz", + "integrity": "sha512-HykivQs8K4f2KNRcXFw+D91llAxZhu1neKPVYwyWe6nYZPW/9Tn1A9p602ceGmF0LxIeiJBg0GYOufAA5yVsUQ==" }, "@esbuild/android-arm": { "version": "0.18.11", @@ -6557,6 +6577,12 @@ "dev": true, "optional": true }, + "@eslint/js": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz", + "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==", + "dev": true + }, "@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -6618,34 +6644,54 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, - "@mlabs-haskell/cardano-serialization-lib-gc-browser": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc-browser/-/cardano-serialization-lib-gc-browser-1.0.6.tgz", - "integrity": "sha512-b7dLrrhjUJSdsmjzariCZO734NB+M/ONLGBiQ/TQzMRtsMydqSFQg6WbMdwYPustoNmQOg6a8bm9+RgllqdmFw==", + "@mlabs-haskell/cardano-message-signing": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-message-signing/-/cardano-message-signing-1.0.1.tgz", + "integrity": "sha512-LNX+Msq1rJ86d5mmaR2Om5tUqB0ZthfE69fpsZcxOYDHNw5s+qtcCyNEmzAWfHC+uIJ4NDEJA8Gk2RfWto7ChA==", "requires": { - "@emurgo/cardano-serialization-lib-browser": "^11.2.1", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1" + "@emurgo/cardano-message-signing-browser": "^1.0.1", + "@emurgo/cardano-message-signing-nodejs": "^1.0.1" } }, - "@mlabs-haskell/cardano-serialization-lib-gc-nodejs": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc-nodejs/-/cardano-serialization-lib-gc-nodejs-1.0.6.tgz", - "integrity": "sha512-I1FqhjEHgib+y0+6K1tSqvrtldRvqjrM5mL+TW9224ezEDScQeCroPWbgGBwwi6rjkN9YpS8Uz6gC0vo8lua1A==", + "@mlabs-haskell/cardano-serialization-lib-gc": { + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", + "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", "requires": { - "@emurgo/cardano-serialization-lib-nodejs": "^11.4.0", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1" + "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", + "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, "@mlabs-haskell/csl-gc-wrapper": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/csl-gc-wrapper/-/csl-gc-wrapper-1.0.1.tgz", - "integrity": "sha512-8pEb4BoQlD5zN+KtOCgtTg62OmLPjMa+DiJvoAzlLcWmp01P3TyJPgbEOtS+xiZpGA+1rRkdyeeLZV3wyw8Xfw==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/csl-gc-wrapper/-/csl-gc-wrapper-1.0.2.tgz", + "integrity": "sha512-jyASltvC/ZVzpMUgbIkIaCLc56uGqymCPnieLkgIMWPhzcRoAxEfshjYONyxPY5XIl0NdIQXjbppXFoPQMk0VQ==" }, "@mlabs-haskell/json-bigint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@mlabs-haskell/json-bigint/-/json-bigint-2.0.0.tgz", "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, + "@mlabs-haskell/uplc-apply-args": { + "version": "1.0.29-alpha", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-1.0.29-alpha.tgz", + "integrity": "sha512-eTazItNZlOvuK/ZNHBKUOM3fL1mhRaY0GFYPtalo6PrkGcwZeSzlD6+B8Mbgmb18HusDZPSRi3zhp/urxOygFA==", + "requires": { + "@mlabs-haskell/uplc-apply-args-browser": "^1.0.29-alpha", + "@mlabs-haskell/uplc-apply-args-nodejs": "^1.0.29-alpha2" + } + }, + "@mlabs-haskell/uplc-apply-args-browser": { + "version": "1.0.29-alpha", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-1.0.29-alpha.tgz", + "integrity": "sha512-U/FEEI1UbHGRLblNHX4WxF5KpPR3S/C1rgXvN8X6gL2CDc4iAqvbP88d5vqwLL+seG2aO4pqqJXQnnKtlLHk7A==" + }, + "@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "1.0.29-alpha2", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-1.0.29-alpha2.tgz", + "integrity": "sha512-91Lfk0SGH3cEHGE/F/If9lot42OJ6+bpM4HsHZr5PDvHFNOICFdTwLq/6BFmIClCkdZZNuDZIc1EpRCBgtdROw==" + }, "@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -7069,6 +7115,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -7182,16 +7234,6 @@ "picomatch": "^2.0.4" } }, - "apply-args-browser": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-browser/-/apply-args-browser-0.0.1.tgz", - "integrity": "sha512-gq4ldo4Fk5SEVpeW/0yBe0v5g3VDEWAm9LB80zGarYtDvojTD7ar0Y/WvIy9gYAkKmlE3USu5wYwKKCqOXfNkg==" - }, - "apply-args-nodejs": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-nodejs/-/apply-args-nodejs-0.0.1.tgz", - "integrity": "sha512-JwZPEvEDrL+4y16Un6FcNjDSITpsBykchgwPh8UtxnziYrbxKAc2BUfyC5uvA6ZVIhQjiO4r+Kg1MQ3nqWk+1Q==" - }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -7233,8 +7275,7 @@ "available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "bail": { "version": "1.0.5", @@ -7311,7 +7352,8 @@ "blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "dev": true }, "bn.js": { "version": "5.2.1", @@ -7556,7 +7598,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -8440,7 +8481,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, "requires": { "is-callable": "^1.1.3" } @@ -8489,14 +8529,12 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -8540,11 +8578,16 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "globals": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", + "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", + "dev": true + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "requires": { "get-intrinsic": "^1.1.3" } @@ -8565,7 +8608,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -8588,20 +8630,17 @@ "has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "requires": { "has-symbols": "^1.0.2" } @@ -8867,7 +8906,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, "requires": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -8891,8 +8929,7 @@ "is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" }, "is-core-module": { "version": "2.13.0", @@ -8925,7 +8962,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, "requires": { "has-tostringtag": "^1.0.0" } @@ -8986,7 +9022,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, "requires": { "which-typed-array": "^1.1.11" } @@ -9018,6 +9053,12 @@ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true }, + "isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "requires": {} + }, "jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -9044,7 +9085,8 @@ "jssha": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.2.0.tgz", - "integrity": "sha512-QuruyBENDWdN4tZwJbQq7/eAK85FqrI4oDbXjy5IBhYD+2pTJyBUWZe8ctWaCkrV0gy6AaelgOZZBMeswEa/6Q==" + "integrity": "sha512-QuruyBENDWdN4tZwJbQq7/eAK85FqrI4oDbXjy5IBhYD+2pTJyBUWZe8ctWaCkrV0gy6AaelgOZZBMeswEa/6Q==", + "dev": true }, "kind-of": { "version": "6.0.3", @@ -10716,7 +10758,6 @@ "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, "requires": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", @@ -10795,6 +10836,15 @@ "minimalistic-assert": "^1.0.0" } }, + "web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "requires": { + "@zxing/text-encoding": "0.9.0", + "util": "^0.12.3" + } + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -10991,13 +11041,6 @@ "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } - }, - "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "requires": {} } } }, @@ -11056,7 +11099,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dev": true, "requires": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -11077,9 +11119,9 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "ws": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", - "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "requires": {} }, "xhr2": { diff --git a/package.json b/package.json index 9cf1dee5ff..cc09665ece 100755 --- a/package.json +++ b/package.json @@ -1,8 +1,6 @@ { "type": "module", "name": "cardano-transaction-lib", - "version": "5.0.0", - "description": "", "repository": { "type": "git", "url": "https://github.com/Plutonomicon/cardano-transaction-lib.git" @@ -11,15 +9,15 @@ "test": "test" }, "scripts": { - "test": "npm run unit-test && npm run integration-test && npm run plutip-test && npm run staking-test", + "test": "npm run unit-test && npm run integration-test && npm run testnet-test && npm run staking-test", "start-runtime": "nix run -L .#ctl-runtime", "start-blockfrost-runtime": "nix run -L .#ctl-runtime-blockfrost", "integration-test": "spago run --main Test.Ctl.Integration", "blockfrost-test": "source ./test/blockfrost.env && spago run --main Test.Ctl.Blockfrost.Contract", "blockfrost-local-test": "source ./test/blockfrost-local.env && spago run --main Test.Ctl.Blockfrost.Contract", "unit-test": "spago run --main Test.Ctl.Unit", - "plutip-test": "spago run --main Test.Ctl.Plutip", - "staking-test": "spago run --main Test.Ctl.Plutip.Staking", + "testnet-test": "spago run --main Test.Ctl.Testnet", + "staking-test": "spago run --main Test.Ctl.Testnet.Staking", "e2e-serve": "make esbuild-serve", "e2e-test": "source ./test/e2e.env && spago test --main Test.Ctl.E2E -a 'run'", "e2e-test-debug": "source ./test/e2e.env && spago test --main Test.Ctl.E2E -a 'run --no-headless'", @@ -31,37 +29,36 @@ "webpack-bundle": "make webpack-bundle", "webpack-serve": "make webpack-serve" }, - "author": "", "license": "MIT", "dependencies": { - "@emurgo/cardano-message-signing-browser": "1.0.1", - "@emurgo/cardano-message-signing-nodejs": "1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc-browser": "^1.0.6", - "@mlabs-haskell/cardano-serialization-lib-gc-nodejs": "^1.0.6", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1", + "@mlabs-haskell/cardano-message-signing": "^1.0.1", + "@mlabs-haskell/cardano-serialization-lib-gc": "12.0.0-alpha.31", "@mlabs-haskell/json-bigint": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "1.0.29-alpha", "@noble/secp256k1": "^1.7.0", - "apply-args-browser": "0.0.1", - "apply-args-nodejs": "0.0.1", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", "bip39": "^3.1.0", - "blakejs": "1.2.1", "bufferutil": "4.0.5", - "jssha": "3.2.0", + "isomorphic-ws": "^5.0.0", "puppeteer-core": "^15.3.2", "reconnecting-websocket": "4.4.0", "uniqid": "5.4.0", "utf-8-validate": "^5.0.10", - "ws": "8.4.0", + "web-encoding": "^1.1.5", + "ws": "^8.16.0", "xhr2": "0.2.1" }, "devDependencies": { + "@eslint/js": "^9.7.0", + "blakejs": "1.2.1", "buffer": "6.0.3", "doctoc": "^2.2.1", "esbuild": "0.18.11", "esbuild-plugin-polyfill-node": "^0.3.0", "esbuild-plugin-wasm": "^1.1.0", + "globals": "^15.8.0", + "jssha": "3.2.0", "node-polyfill-webpack-plugin": "2.0.1", "webpack": "5.88.1", "webpack-cli": "5.1.4", diff --git a/packages.dhall b/packages.dhall index 43c24759f6..0b8e8cc059 100644 --- a/packages.dhall +++ b/packages.dhall @@ -1,109 +1,3 @@ -{- -Welcome to your new Dhall package-set! - -Below are instructions for how to edit this file for most use -cases, so that you don't need to know Dhall to use it. - -## Warning: Don't Move This Top-Level Comment! - -Due to how `dhall format` currently works, this comment's -instructions cannot appear near corresponding sections below -because `dhall format` will delete the comment. However, -it will not delete a top-level comment like this one. - -## Use Cases - -Most will want to do one or both of these options: -1. Override/Patch a package's dependency -2. Add a package not already in the default package set - -This file will continue to work whether you use one or both options. -Instructions for each option are explained below. - -### Overriding/Patching a package - -Purpose: -- Change a package's dependency to a newer/older release than the - default package set's release -- Use your own modified version of some dependency that may - include new API, changed API, removed API by - using your custom git repo of the library rather than - the package set's repo - -Syntax: -where `entityName` is one of the following: -- dependencies -- repo -- version -------------------------------- -let upstream = -- -in upstream - with packageName.entityName = "new value" -------------------------------- - -Example: -------------------------------- -let upstream = -- -in upstream - with halogen.version = "master" - with halogen.repo = "https://example.com/path/to/git/repo.git" - - with halogen-vdom.version = "v4.0.0" -------------------------------- - -### Additions - -Purpose: -- Add packages that aren't already included in the default package set - -Syntax: -where `` is: -- a tag (i.e. "v4.0.0") -- a branch (i.e. "master") -- commit hash (i.e. "701f3e44aafb1a6459281714858fadf2c4c2a977") -------------------------------- -let upstream = -- -in upstream - with new-package-name = - { dependencies = - [ "dependency1" - , "dependency2" - ] - , repo = - "https://example.com/path/to/git/repo.git" - , version = - "" - } -------------------------------- - -Example: -------------------------------- -let upstream = -- -in upstream - with benchotron = - { dependencies = - [ "arrays" - , "exists" - , "profunctor" - , "strings" - , "quickcheck" - , "lcg" - , "transformers" - , "foldable-traversable" - , "exceptions" - , "node-fs" - , "node-buffer" - , "node-readline" - , "datetime" - , "now" - ] - , repo = - "https://github.com/hdgarrood/purescript-benchotron.git" - , version = - "v7.0.0" - } -------------------------------- --} let upstream = https://github.com/purescript/package-sets/releases/download/psc-0.15.4-20230105/packages.dhall sha256:3e9fbc9ba03e9a1fcfd895f65e2d50ee2f5e86c4cd273f3d5c841b655a0e1bda @@ -144,7 +38,7 @@ let additions = , "untagged-union" ] , repo = "https://github.com/mlabs-haskell/purescript-aeson.git" - , version = "v2.0.0" + , version = "v2.0.1" } , bignumber = { dependencies = @@ -193,6 +87,7 @@ let additions = { dependencies = [ "aff" , "aff-promise" + , "bytearrays" , "effect" , "prelude" , "spec" @@ -201,7 +96,7 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-noble-secp256k1.git" - , version = "a3c0f67e9fdb0086016d7aebfad35d09a08b4ecd" + , version = "v2.0.0" } , js-bigints = { dependencies = [ "integers", "maybe", "prelude" ] @@ -223,7 +118,7 @@ let additions = , "untagged-union" ] , repo = "https://github.com/mlabs-haskell/purescript-cip30" - , version = "8f1b34b48825fcec5e9c67f33e255770b1e0bc45" + , version = "v1.0.0" } , cip30-typesafe = { dependencies = @@ -241,7 +136,343 @@ let additions = , "variant" ] , repo = "https://github.com/mlabs-haskell/purescript-cip30-typesafe" - , version = "d72e51fbc0255eb3246c9132d295de7f65e16a99" + , version = "v1.0.0" + } + , cip95 = + { dependencies = + [ "aff" + , "aff-promise" + , "cip30" + , "console" + , "effect" + , "newtype" + , "prelude" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cip95" + , version = "v1.0.0" + } + , cip95-typesafe = + { dependencies = + [ "aff" + , "bifunctors" + , "cip30" + , "cip30-typesafe" + , "cip95" + , "console" + , "control" + , "effect" + , "either" + , "exceptions" + , "maybe" + , "prelude" + , "spec" + , "transformers" + , "variant" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cip95-typesafe" + , version = "v1.0.0" + } + , bytearrays = + { dependencies = + [ "aeson" + , "aff" + , "arraybuffer-types" + , "effect" + , "either" + , "foldable-traversable" + , "maybe" + , "newtype" + , "prelude" + , "quickcheck" + , "quickcheck-laws" + , "spec" + , "strings" + ] + , repo = "https://github.com/mlabs-haskell/purescript-bytearrays" + , version = "v1.0.0" + } + , cardano-serialization-lib = + { dependencies = + [ "aeson" + , "aff" + , "argonaut" + , "bifunctors" + , "bytearrays" + , "effect" + , "either" + , "enums" + , "maybe" + , "nullable" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor" + , "spec" + , "transformers" + , "tuples" + , "unsafe-coerce" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib" + , version = "v1.0.0" + } + , cardano-plutus-data-schema = + { dependencies = [ "prelude" ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-plutus-data-schema" + , version = "v1.0.0" + } + , plutus-types = + { dependencies = + [ "aeson" + , "argonaut-codecs" + , "arrays" + , "bifunctors" + , "bytearrays" + , "cardano-plutus-data-schema" + , "cardano-types" + , "console" + , "effect" + , "either" + , "foldable-traversable" + , "gen" + , "js-bigints" + , "lattice" + , "maybe" + , "monad-logger" + , "newtype" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor-lenses" + , "quickcheck" + , "these" + , "tuples" + ] + , repo = "https://github.com/mlabs-haskell/purescript-plutus-types" + , version = "v1.0.1" + } + , cip30-mock = + { dependencies = + [ "aff-promise", "console", "effect", "functions", "prelude" ] + , repo = "https://github.com/mlabs-haskell/purescript-cip30-mock" + , version = "v1.1.0" + } + , cardano-collateral-select = + { dependencies = + [ "arrays" + , "cardano-types" + , "console" + , "effect" + , "exceptions" + , "foldable-traversable" + , "lists" + , "maybe" + , "newtype" + , "ordered-collections" + , "partial" + , "prelude" + , "tuples" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-collateral-select" + , version = "v1.0.0" + } + , cardano-key-wallet = + { dependencies = + [ "aeson" + , "aff" + , "arrays" + , "cardano-collateral-select" + , "cardano-message-signing" + , "cardano-types" + , "console" + , "effect" + , "either" + , "foldable-traversable" + , "maybe" + , "newtype" + , "ordered-collections" + , "prelude" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-key-wallet" + , version = "v2.0.0" + } + , uplc-apply-args = + { dependencies = + [ "aff" + , "bytearrays" + , "cardano-serialization-lib" + , "cardano-types" + , "effect" + , "either" + , "foldable-traversable" + , "foreign-object" + , "js-bigints" + , "lists" + , "maybe" + , "mote" + , "mote-testplan" + , "partial" + , "prelude" + , "profunctor" + , "spec" + , "transformers" + , "tuples" + ] + , repo = "https://github.com/mlabs-haskell/purescript-uplc-apply-args" + , version = "v1.0.0" + } + , cardano-types = + { dependencies = + [ "aeson" + , "aff" + , "arraybuffer-types" + , "arrays" + , "bifunctors" + , "bytearrays" + , "cardano-plutus-data-schema" + , "cardano-serialization-lib" + , "control" + , "datetime" + , "effect" + , "either" + , "encoding" + , "exceptions" + , "foldable-traversable" + , "foreign-object" + , "integers" + , "js-bigints" + , "lattice" + , "lists" + , "literals" + , "maybe" + , "monad-logger" + , "mote" + , "mote-testplan" + , "newtype" + , "nonempty" + , "nullable" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor" + , "profunctor-lenses" + , "quickcheck" + , "rationals" + , "record" + , "safe-coerce" + , "spec" + , "these" + , "tuples" + , "typelevel-prelude" + , "uint" + , "unfoldable" + , "unsafe-coerce" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" + , version = "v2.0.1" + } + , cardano-message-signing = + { dependencies = + [ "bytearrays" + , "cardano-types" + , "console" + , "effect" + , "newtype" + , "prelude" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-message-signing" + , version = "v1.0.0" + } + , cardano-hd-wallet = + { dependencies = + [ "cardano-serialization-lib" + , "cardano-types" + , "console" + , "effect" + , "either" + , "prelude" + , "uint" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cardano-hd-wallet" + , version = "cc1073ddf8bce72407ef6671e3decb59f422e304" + } + , cardano-transaction-builder = + { dependencies = + [ "aeson" + , "aff" + , "arraybuffer-types" + , "arrays" + , "bifunctors" + , "bytearrays" + , "cardano-plutus-data-schema" + , "cardano-serialization-lib" + , "cardano-types" + , "console" + , "control" + , "datetime" + , "effect" + , "either" + , "encoding" + , "exceptions" + , "foldable-traversable" + , "foreign-object" + , "integers" + , "js-bigints" + , "lattice" + , "lists" + , "literals" + , "maybe" + , "monad-logger" + , "mote" + , "mote-testplan" + , "newtype" + , "nonempty" + , "nullable" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor" + , "profunctor-lenses" + , "quickcheck" + , "rationals" + , "record" + , "safe-coerce" + , "spec" + , "strings" + , "these" + , "transformers" + , "tuples" + , "typelevel-prelude" + , "uint" + , "unfoldable" + , "unsafe-coerce" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder" + , version = "a9c033b9a2bb78b134ae5309209f73e47f3d5791" + } + , mote-testplan = + { dependencies = + [ "aff" + , "console" + , "datetime" + , "effect" + , "foldable-traversable" + , "maybe" + , "mote" + , "newtype" + , "numbers" + , "ordered-collections" + , "prelude" + , "spec" + , "transformers" + ] + , repo = "https://github.com/mlabs-haskell/purescript-mote-testplan" + , version = "v1.0.0" } } diff --git a/plutip-server/.gitignore b/plutip-server/.gitignore deleted file mode 100644 index 838458f209..0000000000 --- a/plutip-server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/dist/ \ No newline at end of file diff --git a/plutip-server/LICENSE b/plutip-server/LICENSE deleted file mode 100644 index 2d81c86b8e..0000000000 --- a/plutip-server/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) 2022 MLabs Ltd. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/plutip-server/README.md b/plutip-server/README.md deleted file mode 100644 index d07d943d70..0000000000 --- a/plutip-server/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# plutip-server - -Plutip-server is a simple HTTP interface for [Plutip](https://github.com/mlabs-haskell/plutip) to start and stop local plutip clusters on demand. - -CTL handles communication with Plutip via this server and there's usually no need to use it directly, though `plutip-server` can be useful if you need to control Plutip from a different service (although [`plutip-local-cluster`](https://github.com/mlabs-haskell/plutip/tree/master/local-cluster), which is a CLI program, is probably more convenient for that). - -Server exposes two POST endpoints for starting and stopping clusters (only up to one active cluster is allowed at a time). - -You can configure cluster parameters like slot length, max tx size, etc. and specify how many wallets to create, including Ada UTxO distribution in each wallet (see [here](../doc/plutip-testing.md#cluster-configuration-options) for how to configure this via CTL). - -On a successful cluster startup `plutip-server` responds with a list of keys of the newly created wallets, node configuration, directory with public and private keys for the wallets and a path to the socket of one of the nodes from the cluster (usually it's the one that finished startup the first). - -`plutip-server` uses Plutip as a [Haskell library](https://github.com/mlabs-haskell/plutip/tree/master#as-a-library) in Servant API handlers via `startFundedCluster` and `stopCluster` functions. diff --git a/plutip-server/cabal.project b/plutip-server/cabal.project deleted file mode 100644 index c1a038651d..0000000000 --- a/plutip-server/cabal.project +++ /dev/null @@ -1,114 +0,0 @@ -repository cardano-haskell-packages - url: https://input-output-hk.github.io/cardano-haskell-packages - secure: True - root-keys: - 3e0cce471cf09815f930210f7827266fd09045445d65923e6d0238a6cd15126f - 443abb7fb497a134c343faf52f0b659bd7999bc06b7f63fa76dc99d631f9bea1 - a86a1f6ce86c449c46666bda44268677abf29b5b2d2eb5ec7af903ec2f117a82 - bcec67e8e99cabfa7764d75ad9b158d72bfacf70ca1d0ec8bc6b4406d1bf8413 - c00aae8461a256275598500ea0e187588c35a5d5d7454fb57eac18d9edb86a56 - d4a35cd3121aa00d18544bb0ac01c3e1691d618f462c46129271bccf39f7e8ee - --- Align index-states with cardano-wallet -index-state: 2023-06-06T00:00:00Z - -packages: ./. - -tests: true -benchmarks: true -test-show-details: direct -constraints: - -- TH Name shadowing warnings nconstraints: - bimap >= 0.4.0 - , openapi3 >= 3.2.0 - , libsystemd-journal >= 1.4.4 - , systemd >= 2.3.0 - -- dependency of systemd-2.3.0 - , network >= 3.1.1.1 - -- choose versions that work with base >= 4.12 - , hjsonpointer >= 1.5.0 - , hjsonschema >= 1.10.0 - , Cabal >= 3.4.0.0 - , async-timer >= 0.2.0.0 - , unliftio-core >= 0.2.0.1 - , generic-arbitrary >= 0.2.2 - , iohk-monitoring >= 0.1.11 - - -- lower versions of katip won't build with the Win32-2.12.0.1 - -- which is shipped with the ghc-9.2.8 - , katip >= 0.8.7.4 - - -- Cardano Node dependencies: - , cardano-api ^>=8.2 - , cardano-slotting >= 0.1 - , ouroboros-network ^>= 0.8.1.0 - , persistent == 2.13.3.3 - -package cardano-wallet - optimization: False -package cardano-wallet-core - optimization: False -package cardano-wallet-cli - optimization: False -package cardano-wallet-launcher - optimization: False -package cardano-wallet-core-integration - optimization: False - -allow-newer: - hjsonschema:* - , hjsonpointer:* - , *:aeson - , *:hashable - , async-timer:unliftio-core - , ekg:* - , ntp-client:* - , libsystemd-journal:base - -source-repository-package - type: git - location: https://github.com/cardano-foundation/cardano-wallet - tag: ae6e90b99ff14eda88769211218aaae2b0fe528b - --sha256: 060r6z9sy9r1jr8iinlyirprw4k3s54malp9sz732vl7byh6vylf - subdir: - lib/application-extras - lib/balance-tx - lib/crypto-hash-extra - lib/coin-selection - lib/delta-store - lib/delta-table - lib/delta-types - lib/iohk-monitoring-extra - lib/launcher - lib/local-cluster - lib/numeric - lib/primitive - lib/read - lib/temporary-extra - lib/test-utils - lib/text-class - lib/wai-middleware-logging - lib/wallet-benchmarks - lib/wallet - lib/wallet-e2e - -source-repository-package - type: git - location: https://github.com/input-output-hk/cardano-addresses - tag: 44d5a9eb3505b6bfbf281d40fa88531c3253b771 - --sha256: 16rja48ryfjw3531kf15w0h3cdmscqgs8l1z1i2mvahq1vlhr2y6 - subdir: command-line - core - -source-repository-package - type: git - location: https://github.com/cardano-foundation/cardano-wallet-client.git - tag: 353412ca621dc28af53e4a19795338b19bab1b7b - --sha256: 04q58c82wy6x9nkwqbvcxbv6s61fx08h5kf62sb511aqp08id4bb - subdir: generated - -source-repository-package - type: git - location: https://github.com/mlabs-haskell/plutip.git - tag: 1bf0b547cd3689c727586abb8385c008fb2a3d1c - --sha256: sha256-7ZhZUDhlFvV2us4G27iAk6lHezKS/4WA07NQn88VtQU= diff --git a/plutip-server/default.nix b/plutip-server/default.nix deleted file mode 100644 index f6bcc4a107..0000000000 --- a/plutip-server/default.nix +++ /dev/null @@ -1,59 +0,0 @@ -{ pkgs, system, src, plutip, CHaP, cardano-node }: -let - haskellModules = - plutip.haskellModules.${system} ++ [ - ({ config, pkgs, ... }: - let - nodeExes = cardano-node.packages.${system}; - in - { - packages.plutip-server.components.exes.plutip-server = { - pkgconfig = [ [ pkgs.makeWrapper ] ]; - postInstall = with pkgs; '' - wrapProgram $out/bin/plutip-server \ - --prefix PATH : "${lib.makeBinPath [ - nodeExes.cardano-node - nodeExes.cardano-cli - ]}" - ''; - }; - }) - ]; -in -pkgs.haskell-nix.cabalProject { - name = "plutip-server"; - - inherit src; - - inputMap = { - "https://input-output-hk.github.io/cardano-haskell-packages" = CHaP; - }; - - compiler-nix-name = "ghc8107"; - - shell = { - withHoogle = true; - exactDeps = true; - - tools.haskell-language-server = "1.5.0.0"; # Newer versions failed to build - - nativeBuildInputs = with pkgs; [ - # Haskell Tools - haskellPackages.fourmolu - haskellPackages.cabal-install - haskellPackages.cabal-fmt - nixpkgs-fmt - hlint - entr - ghcid - git - fd - - # Cardano tools - cardano-node.packages.${system}.cardano-cli - cardano-node.packages.${system}.cardano-node - ]; - }; - - modules = haskellModules; -} diff --git a/plutip-server/fourmolu.yaml b/plutip-server/fourmolu.yaml deleted file mode 100644 index fc79883a8c..0000000000 --- a/plutip-server/fourmolu.yaml +++ /dev/null @@ -1,8 +0,0 @@ -indentation: 2 -comma-style: leading -record-brace-space: true -indent-wheres: true -diff-friendly-import-export: true -respectful: true -haddock-style: single-line -newlines-between-decls: 1 diff --git a/plutip-server/hie.yaml b/plutip-server/hie.yaml deleted file mode 100644 index 14f2798770..0000000000 --- a/plutip-server/hie.yaml +++ /dev/null @@ -1,4 +0,0 @@ -cradle: - cabal: - - path: "./src/" - component: "exe:plutip-server" diff --git a/plutip-server/plutip-server.cabal b/plutip-server/plutip-server.cabal deleted file mode 100644 index da121dc1b2..0000000000 --- a/plutip-server/plutip-server.cabal +++ /dev/null @@ -1,96 +0,0 @@ -cabal-version: 3.0 -name: plutip-server -version: 0.2 -license-file: LICENSE -author: mlabs -maintainer: TODO -build-type: Simple -extra-source-files: CHANGELOG.md - -common common-language - default-extensions: - BangPatterns - DataKinds - DeriveAnyClass - DeriveFoldable - DeriveFunctor - DeriveGeneric - DeriveLift - DeriveTraversable - DerivingStrategies - EmptyDataDecls - ExplicitForAll - FlexibleContexts - FlexibleInstances - GeneralizedNewtypeDeriving - ImportQualifiedPost - LambdaCase - MonoLocalBinds - MultiParamTypeClasses - NamedFieldPuns - NumericUnderscores - OverloadedStrings - QuasiQuotes - RankNTypes - RecordWildCards - ScopedTypeVariables - StandaloneDeriving - TemplateHaskell - TupleSections - TypeApplications - TypeFamilies - TypeOperators - TypeSynonymInstances - ViewPatterns - -common common-configs - default-language: Haskell2010 - -common common-ghc-options - ghc-options: - -fno-ignore-interface-pragmas -fno-omit-interface-pragmas - -fno-specialize -fno-strictness -fno-warn-orphans -fobject-code - -fplugin-opt PlutusTx.Plugin:defer-errors - -executable plutip-server - import: common-language - import: common-ghc-options - main-is: Main.hs - hs-source-dirs: src - default-language: Haskell2010 - build-depends: - , aeson - , async - , base - , base16-bytestring - , bytestring - , cardano-api - , cardano-ledger-core - , cardano-wallet - , cardano-wallet-launcher - , data-default - , directory - , exceptions - , extra - , filepath - , http-types - , mtl - , optparse-applicative - , plutip-core - , positive - , servant-server - , stm - , text - , time - , unliftio - , wai - , wai-cors - , wai-logger - , warp - - other-modules: - Api - Api.Handlers - Types - - ghc-options: -Wall -threaded -rtsopts diff --git a/plutip-server/src/Api.hs b/plutip-server/src/Api.hs deleted file mode 100644 index b3c6fcc938..0000000000 --- a/plutip-server/src/Api.hs +++ /dev/null @@ -1,67 +0,0 @@ -module Api where - -import Api.Handlers ( - startClusterHandler, - stopClusterHandler, - ) -import Control.Monad.IO.Class (liftIO) -import Control.Monad.Reader (runReaderT) -import Data.Kind (Type) -import Network.Wai.Middleware.Cors qualified as Cors -import Servant ( - Application, - Handler, - JSON, - Post, - Proxy (Proxy), - ReqBody, - Server, - ServerT, - hoistServer, - serve, - (:<|>) ((:<|>)), - (:>), - ) -import Types ( - AppM (AppM), - Env (Env), - ServerOptions, - StartClusterRequest, - StartClusterResponse, - StopClusterRequest, - StopClusterResponse, - options, - ) - -type Api = - "start" - :> ReqBody '[JSON] StartClusterRequest - :> Post '[JSON] StartClusterResponse - :<|> "stop" - :> ReqBody '[JSON] StopClusterRequest - :> Post '[JSON] StopClusterResponse - -app :: Env -> Application -app = Cors.cors (const $ Just policy) . serve api . appServer - where - policy :: Cors.CorsResourcePolicy - policy = - Cors.simpleCorsResourcePolicy - { Cors.corsRequestHeaders = ["Content-Type"] - , Cors.corsMethods = ["OPTIONS", "GET", "POST"] - } - -api :: Proxy Api -api = Proxy - -server :: ServerOptions -> ServerT Api AppM -server serverOptions = - startClusterHandler serverOptions - :<|> stopClusterHandler - -appServer :: Env -> Server Api -appServer env@Env {options} = - hoistServer api appHandler (server options) - where - appHandler :: forall (a :: Type). AppM a -> Handler a - appHandler (AppM x) = liftIO $ runReaderT x env diff --git a/plutip-server/src/Api/Handlers.hs b/plutip-server/src/Api/Handlers.hs deleted file mode 100644 index 33452b14ac..0000000000 --- a/plutip-server/src/Api/Handlers.hs +++ /dev/null @@ -1,118 +0,0 @@ -module Api.Handlers ( - startClusterHandler, - stopClusterHandler, -) where - -import Cardano.Launcher.Node (nodeSocketFile) - -import Control.Concurrent.MVar (isEmptyMVar, putMVar, tryTakeMVar) -import Control.Monad (unless) -import Control.Monad.Except (runExceptT, throwError) -import Control.Monad.Extra (unlessM) -import Control.Monad.IO.Class (liftIO) -import Control.Monad.Reader (asks) -import Data.Default (def) -import Data.Foldable (for_) -import Data.Maybe (fromMaybe) -import Plutip.Cluster (startFundedCluster, stopCluster) -import Plutip.Config ( - ExtraConfig (ExtraConfig, ecEpochSize, ecMaxTxSize, ecSlotLength), - PlutipConfig (extraConfig), - ecRaiseExUnitsToMax, - ) -import Plutip.Keys (signKeyCBORHex) -import Plutip.Types (ClusterEnv (runningNode), RunningNode (RunningNode), keysDir) -import System.Directory (doesFileExist) -import System.FilePath (replaceFileName) -import Types ( - AppM, - ClusterStartupFailureReason ( - ClusterIsRunningAlready, - NegativeLovelaces, - NodeConfigNotFound - ), - ClusterStartupParameters ( - ClusterStartupParameters, - keysDirectory, - nodeConfigPath, - nodeSocketPath, - privateKeys - ), - Env (status), - Lovelace (unLovelace), - ServerOptions, - StartClusterRequest ( - StartClusterRequest, - epochSize, - keysToGenerate, - maxTxSize, - raiseExUnitsToMax, - slotLength - ), - StartClusterResponse ( - ClusterStartupFailure, - ClusterStartupSuccess - ), - StopClusterRequest (StopClusterRequest), - StopClusterResponse (StopClusterFailure, StopClusterSuccess), - ) - -startClusterHandler :: ServerOptions -> StartClusterRequest -> AppM StartClusterResponse -startClusterHandler - _ - StartClusterRequest - { keysToGenerate - , slotLength - , epochSize - , maxTxSize - , raiseExUnitsToMax - } = interpret $ do - -- Check that lovelace amounts are positive - for_ keysToGenerate $ \lovelaceAmounts -> - for_ lovelaceAmounts $ \lovelaces -> - unless (unLovelace lovelaces > 0) $ - throwError NegativeLovelaces - statusMVar <- asks status - isClusterDown <- liftIO $ isEmptyMVar statusMVar - unless isClusterDown $ throwError ClusterIsRunningAlready - let cfg = def {extraConfig = extraConf} - keysToGenerate' = map fromIntegral <$> keysToGenerate - (statusTVar, (clusterEnv, keys)) <- liftIO $ startFundedCluster cfg keysToGenerate' (curry pure) - liftIO $ putMVar statusMVar statusTVar - - let nodeConfigPath = getNodeConfigFile clusterEnv - -- safeguard against directory tree structure changes - unlessM (liftIO $ doesFileExist nodeConfigPath) $ throwError NodeConfigNotFound - pure $ - ClusterStartupSuccess $ - ClusterStartupParameters - { privateKeys = signKeyCBORHex <$> keys - , nodeSocketPath = getNodeSocketFile clusterEnv - , nodeConfigPath = nodeConfigPath - , keysDirectory = keysDir clusterEnv - } - where - getNodeSocketFile (runningNode -> RunningNode conn _ _) = nodeSocketFile conn - getNodeConfigFile = - -- assumption is that node.config lies in the same directory as node.socket - flip replaceFileName "node.config" . getNodeSocketFile - interpret = fmap (either ClusterStartupFailure id) . runExceptT - - extraConf :: ExtraConfig - extraConf = - let defConfig = def - in ExtraConfig - (fromMaybe (ecSlotLength defConfig) slotLength) - (fromMaybe (ecEpochSize defConfig) epochSize) - (fromMaybe (ecMaxTxSize defConfig) maxTxSize) - (fromMaybe (ecRaiseExUnitsToMax defConfig) raiseExUnitsToMax) - -stopClusterHandler :: StopClusterRequest -> AppM StopClusterResponse -stopClusterHandler StopClusterRequest = do - statusMVar <- asks status - maybeClusterStatus <- liftIO $ tryTakeMVar statusMVar - case maybeClusterStatus of - Nothing -> pure $ StopClusterFailure "Cluster is not running" - Just statusTVar -> do - liftIO $ stopCluster statusTVar - pure StopClusterSuccess diff --git a/plutip-server/src/Main.hs b/plutip-server/src/Main.hs deleted file mode 100644 index 35f26c573f..0000000000 --- a/plutip-server/src/Main.hs +++ /dev/null @@ -1,59 +0,0 @@ -module Main (main) where - -import Api (app) -import Control.Applicative ((<**>)) -import Control.Concurrent.MVar (newEmptyMVar) -import Data.Function ((&)) -import Network.HTTP.Types (Status) -import Network.Wai (Request) -import Network.Wai.Handler.Warp ( - Port, - Settings, - defaultSettings, - runSettings, - setLogger, - setPort, - ) -import Network.Wai.Logger (withStdoutLogger) -import Options.Applicative qualified as Options -import System.Exit (die) -import Types (Env (Env, options, status), ServerOptions (ServerOptions, port)) - -main :: IO () -main = do - serverOptions@ServerOptions {port} <- Options.execParser opts - withStdoutLogger $ \logger -> do - putStrLn $ "Plutip server starting on port " <> show port - runSettings (mkSettings port logger) - . app - =<< either die pure - =<< newEnvIO serverOptions - where - mkSettings :: - Port -> (Request -> Status -> Maybe Integer -> IO ()) -> Settings - mkSettings port logger = defaultSettings & setPort port & setLogger logger - -newEnvIO :: ServerOptions -> IO (Either String Env) -newEnvIO options = do - status <- newEmptyMVar - pure . Right $ Env {status, options} - -opts :: Options.ParserInfo ServerOptions -opts = - Options.info (serverOptionsParser <**> Options.helper) $ - Options.fullDesc - <> Options.progDesc - "plutip-server is used for integration with cardano-transaction-lib" - -serverOptionsParser :: Options.Parser ServerOptions -serverOptionsParser = - ServerOptions - <$> Options.option - Options.auto - ( Options.long "port" - <> Options.short 'p' - <> Options.help "Server port" - <> Options.showDefault - <> Options.value 8082 - <> Options.metavar "INT" - ) diff --git a/plutip-server/src/Types.hs b/plutip-server/src/Types.hs deleted file mode 100644 index 9d7d5227c3..0000000000 --- a/plutip-server/src/Types.hs +++ /dev/null @@ -1,135 +0,0 @@ -module Types ( - AppM (AppM), - ClusterStartupFailureReason ( - ClusterIsRunningAlready, - NegativeLovelaces, - NodeConfigNotFound - ), - Env (Env, status, options), - ErrorMessage, - Lovelace (unLovelace), - PrivateKey, - ServerOptions (ServerOptions, port), - StartClusterRequest ( - StartClusterRequest, - keysToGenerate, - slotLength, - epochSize, - maxTxSize, - raiseExUnitsToMax - ), - StartClusterResponse ( - ClusterStartupSuccess, - ClusterStartupFailure - ), - ClusterStartupParameters ( - ClusterStartupParameters, - keysDirectory, - nodeSocketPath, - privateKeys, - nodeConfigPath - ), - StopClusterRequest (StopClusterRequest), - StopClusterResponse (StopClusterSuccess, StopClusterFailure), -) where - -import Cardano.Ledger.Slot (EpochSize) -import Control.Concurrent.MVar (MVar) -import Control.Monad.Catch (MonadThrow) -import Control.Monad.IO.Class (MonadIO) -import Control.Monad.Reader (MonadReader, ReaderT) -import Data.Aeson (FromJSON, ToJSON, parseJSON) -import Data.Kind (Type) -import Data.Text (Text) -import GHC.Generics (Generic) -import Network.Wai.Handler.Warp (Port) -import Numeric.Natural (Natural) -import Plutip.Config (NominalDiffTimeMicro) -import Plutip.Cluster (StopClusterRef) - --- TVar is used for signaling by 'startCluster'/'stopCluster' (STM is used --- for blocking). --- MVar is used by plutip-server to store current TVar (we allow maximum of one --- cluster at any given moment). --- This MVar is used by start/stop handlers. --- The payload of ClusterStatus is irrelevant. -type ClusterStatusRef = MVar StopClusterRef - -data Env = Env - { status :: ClusterStatusRef - , options :: ServerOptions - } - -data ServerOptions = ServerOptions - { port :: Port - } - deriving stock (Generic) - -newtype AppM (a :: Type) = AppM (ReaderT Env IO a) - deriving newtype - ( Functor - , Applicative - , Monad - , MonadIO - , MonadReader Env - , MonadThrow - ) - -type ErrorMessage = Text - -newtype Lovelace = Lovelace {unLovelace :: Integer} - deriving stock (Show, Eq, Generic) - deriving newtype (ToJSON, Num, Enum, Ord, Real, Integral) - -instance FromJSON Lovelace where - parseJSON json = do - Lovelace <$> parseJSON json - -data StartClusterRequest = StartClusterRequest - { keysToGenerate :: [[Lovelace]] - -- ^ Lovelace amounts for each UTXO of each wallet - , slotLength :: Maybe NominalDiffTimeMicro - -- ^ Set the SlotLength. If set to Nothing use the default - , epochSize :: Maybe EpochSize - -- ^ Set the EpochSize. If set to Nothing use the default - , maxTxSize :: Maybe Natural - -- ^ Set The maxTxSize. If set to Nothing use the default - , raiseExUnitsToMax :: Maybe Bool - -- ^ Raise the execution units to the maximum when true. - -- If set to Nothing use the default - } - deriving stock (Show, Eq, Generic) - deriving anyclass (FromJSON, ToJSON) - --- CborHex -type PrivateKey = Text - -data ClusterStartupFailureReason - = ClusterIsRunningAlready - | NegativeLovelaces - | NodeConfigNotFound - deriving stock (Show, Eq, Generic) - deriving anyclass (FromJSON, ToJSON) - -data ClusterStartupParameters = ClusterStartupParameters - { privateKeys :: [PrivateKey] - , nodeSocketPath :: FilePath - , nodeConfigPath :: FilePath - , keysDirectory :: FilePath - } - deriving stock (Show, Eq, Generic) - deriving anyclass (FromJSON, ToJSON) - -data StartClusterResponse - = ClusterStartupFailure ClusterStartupFailureReason - | ClusterStartupSuccess ClusterStartupParameters - deriving stock (Show, Eq, Generic) - deriving anyclass (FromJSON, ToJSON) - -data StopClusterRequest = StopClusterRequest - deriving stock (Show, Eq, Generic) - deriving anyclass (FromJSON, ToJSON) - -data StopClusterResponse = StopClusterSuccess | StopClusterFailure ErrorMessage - deriving stock (Show, Eq, Generic) - deriving anyclass (FromJSON, ToJSON) diff --git a/scripts/import-fixer.sh b/scripts/import-fixer.sh new file mode 100755 index 0000000000..368ab577a5 --- /dev/null +++ b/scripts/import-fixer.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +if [[ "${TRACE-0}" == "1" ]]; then + set -o xtrace +fi + +if [[ "${1-}" =~ ^-*h(elp)?$ ]]; then + echo 'Usage: ./scripts/import-fixer.sh +This script attempts to fix imports from implicit (Something(..)) to explicit (Something(SomeConstructor, OtherConstructor)) based on a set of hardcoded types +' + exit +fi + +# cd "$(dirname "$0")" + +declare -A constrs + +constrs["Slot"]="Slot" +constrs["Value"]="Value" +constrs["Either"]="Left, Right" +constrs["PrivateKey"]="PrivateKey" +constrs["Credential"]="PubKeyHashCredential, ScriptHashCredential" +constrs["Address"]="BaseAddress, ByronAddress, EnterpriseAddress, RewardAddress, PointerAddress" +constrs["Proxy"]="Proxy" +constrs["ExUnits"]="ExUnits" +constrs["Transaction"]="Transaction" +constrs["CborBytes"]="CborBytes" +constrs["Coin"]="Coin" +constrs["Mint"]="Mint" +constrs["TransactionUnspentOutput"]="TransactionUnspentOutput" +constrs["TransactionOutput"]="TransactionOutput" +constrs["OutputDatum"]="OutputDatumHash, OutputDatum" +constrs["PoolPubKeyHash"]="PoolPubKeyHash" +constrs["Val"]="Val" +constrs["AssetClass"]="AssetClass" +constrs["NetworkId"]="MainnetId, TestnetId" +constrs["ScriptRef"]="NativeScriptRef, PlutusScriptRef" +constrs["RedeemerTag"]="Spend, Mint, Cert, Reward" +constrs["Maybe"]="Just, Nothing" +constrs["PaymentCredential"]="PaymentCredential" +constrs["StakeCredential"]="StakeCredential" +constrs["TransactionBuilderStep"]="SpendOutput, Pay, MintAsset, IssueCertificate, WithdrawStake" +constrs["OutputWitness"]="NativeScriptOutput, PlutusScriptOutput" +constrs["CredentialWitness"]="NativeScriptCredential, PlutusScriptCredential" +constrs["ScriptWitness"]="ScriptValue, ScriptReference" +constrs["DatumWitness"]="DatumValue, DatumReference" +constrs["RefInputAction"]="ReferenceInput, SpendInput" +constrs["ExpectedWitnessType"]="ScriptHashWitness, PubKeyHashWitness" +constrs["TxBuildError"]="WrongSpendWitnessType, IncorrectDatumHash, IncorrectScriptHash, WrongOutputType, WrongStakeCredentialType, DatumWitnessNotProvided, UnneededDatumWitness, UnneededDeregisterWitness, UnableToAddMints, RedeemerIndexingError, RedeemerIndexingInternalError, WrongNetworkId, ScriptHashAddressAndNoDatum, NoTransactionNetworkId" +constrs["Certificate"]="StakeRegistration, StakeDeregistration, StakeDelegation, PoolRegistration, PoolRetirement, GenesisKeyDelegation, MoveInstantaneousRewardsCert" +constrs["PlutusData"]="Constr, Map, List, Integer, Bytes" + +for d in "src" "test" "examples"; do + echo "processing $d" + pushd "./$d" + command='' + for key in "${!constrs[@]}"; do + command="$command"'s/\b'"$key"'(..)/'"$key(${constrs[$key]})"'/g;' + done + find -type f | grep '\.purs$' --color=never | xargs -I'{}' -exec sed -i -e "$command" '{}' + echo "$command" + popd +done; diff --git a/scripts/whitespace-check.sh b/scripts/whitespace-check.sh index 2e0f26cfb4..02df695f23 100755 --- a/scripts/whitespace-check.sh +++ b/scripts/whitespace-check.sh @@ -6,7 +6,7 @@ files=" *.md *.nix *.dhall -.eslintrc.json +eslint.config.js .mlc_config.json .tidyrc.json LICENSE diff --git a/spago-packages.nix b/spago-packages.nix index a8b01cd417..a2689809bd 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -7,11 +7,11 @@ let "aeson" = pkgs.stdenv.mkDerivation { name = "aeson"; - version = "v2.0.0"; + version = "v2.0.1"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-aeson.git"; - rev = "4fddd518a143de563299d484272a0ef18daa7dcd"; - sha256 = "1bz1z9l6nwf5yk45sbbjllmqvci0n1l92cvk3lgmni19g9silbrl"; + rev = "ac674dda5cf58c6544cb361a208bced4d06ee93a"; + sha256 = "1zx7d96rz86axqz8n28j5d4lkgx48via0nw9c7xid1z1pz215zsd"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -197,6 +197,114 @@ let installPhase = "ln -s $src $out"; }; + "bytearrays" = pkgs.stdenv.mkDerivation { + name = "bytearrays"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-bytearrays"; + rev = "e3991d562a04d8825472551d91a06407ad9c9112"; + sha256 = "0lyp1x8kgzg8ykv5yp8dd21ziypi9yzhzqpwv5l995kfm4mdglh2"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-collateral-select" = pkgs.stdenv.mkDerivation { + name = "cardano-collateral-select"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-collateral-select"; + rev = "193bf49be979b42aa1f0f9cb3d7582d6bc98e3b9"; + sha256 = "1jbl6k779brbqzf7jf80is63b23k3mqzf2mzr222qswd3wg8s5b0"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-hd-wallet" = pkgs.stdenv.mkDerivation { + name = "cardano-hd-wallet"; + version = "cc1073ddf8bce72407ef6671e3decb59f422e304"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-hd-wallet"; + rev = "cc1073ddf8bce72407ef6671e3decb59f422e304"; + sha256 = "0y51lp3x785yjjrr91rmpw1bhzjdfjb5fs27n1vlwihxjyfylxya"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-key-wallet" = pkgs.stdenv.mkDerivation { + name = "cardano-key-wallet"; + version = "v2.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-key-wallet"; + rev = "99d9bb7c8b291ad0bc9709d493ff7e02d14a89c0"; + sha256 = "11jw05s7vpgg6bdyi3zy4z1fcj53a8kaaja5717b7yjgflmhfn8s"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-message-signing" = pkgs.stdenv.mkDerivation { + name = "cardano-message-signing"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-message-signing"; + rev = "97f6f97a258ae3490df0be6b39fa6769677aa04f"; + sha256 = "1ns7m9awn4w5amvf9ffldxk7acm73fg8clw4hja4nnl61mskqr5w"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-plutus-data-schema" = pkgs.stdenv.mkDerivation { + name = "cardano-plutus-data-schema"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-plutus-data-schema"; + rev = "eb0bb78927c50c4bee364e932c9fa8cf94546191"; + sha256 = "118i6dlfqk7q0va3bd4vplsv9i6sh83cr51gshas6jjwc5qbriks"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-serialization-lib" = pkgs.stdenv.mkDerivation { + name = "cardano-serialization-lib"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib"; + rev = "903bf0adeefedc4d065ad6523ad079433bdd8e32"; + sha256 = "0jlfxrx037hyd4v0j7l2b16yxlm6nw6qlnr992hj9nzip36vbpfg"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-transaction-builder" = pkgs.stdenv.mkDerivation { + name = "cardano-transaction-builder"; + version = "a9c033b9a2bb78b134ae5309209f73e47f3d5791"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder"; + rev = "a9c033b9a2bb78b134ae5309209f73e47f3d5791"; + sha256 = "1xz6k56kwghq9nl0iwrqs6m05wja0xfj34iicmlhwvdp7k4nc65w"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-types" = pkgs.stdenv.mkDerivation { + name = "cardano-types"; + version = "v2.0.1"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-types"; + rev = "5b16e9571167e9889605d3aecdd0ccce24d38696"; + sha256 = "1052lknpkhcq86lj8aavfwzr9ybrirjighsjccpgrcaq2jn4kcmj"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "catenable-lists" = pkgs.stdenv.mkDerivation { name = "catenable-lists"; version = "v7.0.0"; @@ -223,7 +331,7 @@ let "cip30" = pkgs.stdenv.mkDerivation { name = "cip30"; - version = "8f1b34b48825fcec5e9c67f33e255770b1e0bc45"; + version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cip30"; rev = "8f1b34b48825fcec5e9c67f33e255770b1e0bc45"; @@ -233,9 +341,21 @@ let installPhase = "ln -s $src $out"; }; + "cip30-mock" = pkgs.stdenv.mkDerivation { + name = "cip30-mock"; + version = "v1.1.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cip30-mock"; + rev = "7ab1d872b550b60ee32df2a01feef3e8dce3f906"; + sha256 = "1bzkzs9rc9g46s0pivpzixd9l5ab010501hwgrg75psf7bim6d4c"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cip30-typesafe" = pkgs.stdenv.mkDerivation { name = "cip30-typesafe"; - version = "d72e51fbc0255eb3246c9132d295de7f65e16a99"; + version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cip30-typesafe"; rev = "d72e51fbc0255eb3246c9132d295de7f65e16a99"; @@ -245,6 +365,30 @@ let installPhase = "ln -s $src $out"; }; + "cip95" = pkgs.stdenv.mkDerivation { + name = "cip95"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cip95"; + rev = "2a27322aaaad116fd6f08832d171d8e5b43f290f"; + sha256 = "1jg6w27qvwkyvf1k83rpdn0d83bsfpfqsqzshv1ypnr90cy8brw5"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cip95-typesafe" = pkgs.stdenv.mkDerivation { + name = "cip95-typesafe"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cip95-typesafe"; + rev = "bee527d5bca9b8d9f7126f67160773196f492259"; + sha256 = "1cl4h65xc6px1bwldbi6vr3a5h682frasnslx7ryfdrinyx3fs0y"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "console" = pkgs.stdenv.mkDerivation { name = "console"; version = "v6.0.0"; @@ -521,6 +665,18 @@ let installPhase = "ln -s $src $out"; }; + "freet" = pkgs.stdenv.mkDerivation { + name = "freet"; + version = "v7.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/purescript-contrib/purescript-freet.git"; + rev = "21be6fba22599a25812430dda6ba2ca8135920a1"; + sha256 = "006wbr7f19k7vs1jg4wgkwyx1q4wvvs2wqscfcxsp8fzfpn2yqw8"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "functions" = pkgs.stdenv.mkDerivation { name = "functions"; version = "v6.0.0"; @@ -773,6 +929,18 @@ let installPhase = "ln -s $src $out"; }; + "mote-testplan" = pkgs.stdenv.mkDerivation { + name = "mote-testplan"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-mote-testplan"; + rev = "3d56986a32134fbd675e42ef6b6f55dc91ad678a"; + sha256 = "11vivzi1bs9mc8hx4v4zarb9r7x47zm6m6z1xvcn228m7lr69csy"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "newtype" = pkgs.stdenv.mkDerivation { name = "newtype"; version = "v5.0.0"; @@ -787,11 +955,11 @@ let "noble-secp256k1" = pkgs.stdenv.mkDerivation { name = "noble-secp256k1"; - version = "a3c0f67e9fdb0086016d7aebfad35d09a08b4ecd"; + version = "v2.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-noble-secp256k1.git"; - rev = "a3c0f67e9fdb0086016d7aebfad35d09a08b4ecd"; - sha256 = "0n2q83n210ih5l54p6wrrjqmy40xhhdd3mam5mzixgr2hszm8969"; + rev = "32a9b39f1734fe0d809b3a3b4854b9e4ad6056f1"; + sha256 = "0hrf7vgf2mh91803l4drygg6srmkg765x4gk6i6zqyr6398fyxw6"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -917,6 +1085,18 @@ let installPhase = "ln -s $src $out"; }; + "node-streams-aff" = pkgs.stdenv.mkDerivation { + name = "node-streams-aff"; + version = "v4.0.1"; + src = pkgs.fetchgit { + url = "https://github.com/purescript-node/purescript-node-streams-aff.git"; + rev = "5c9b6937d14d6fed2273e3ac8780e3d256763e7d"; + sha256 = "1vm5s6mlawdpqamnqfyh1vbsybjm2s972m02h8mza4m47zlca948"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "node-url" = pkgs.stdenv.mkDerivation { name = "node-url"; version = "v6.0.0"; @@ -1085,6 +1265,18 @@ let installPhase = "ln -s $src $out"; }; + "plutus-types" = pkgs.stdenv.mkDerivation { + name = "plutus-types"; + version = "v1.0.1"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-plutus-types"; + rev = "dfec05e2dee79ee8dafad3d698906966ea6628bb"; + sha256 = "0milz16kdl1pd0i6b8ibxpacdd2r7p6n96gl1g6h41v9bccs69p9"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "posix-types" = pkgs.stdenv.mkDerivation { name = "posix-types"; version = "v6.0.0"; @@ -1253,6 +1445,18 @@ let installPhase = "ln -s $src $out"; }; + "safely" = pkgs.stdenv.mkDerivation { + name = "safely"; + version = "v4.0.1"; + src = pkgs.fetchgit { + url = "https://github.com/paf31/purescript-safely.git"; + rev = "19f854737e17b4d058e5a1504a960821db36e4ab"; + sha256 = "1mrpz19smjsamz4cci287z89q715chzxna0gpbvdgivlca4z6879"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "spec" = pkgs.stdenv.mkDerivation { name = "spec"; version = "v7.2.0"; @@ -1469,6 +1673,18 @@ let installPhase = "ln -s $src $out"; }; + "uplc-apply-args" = pkgs.stdenv.mkDerivation { + name = "uplc-apply-args"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args"; + rev = "aa528d5310cbfbd01b4d94557f404d95cfb6bb3c"; + sha256 = "1r064ca2m16hkbcswrvlng032ax1ygbpr2gxrlaqmjlf2gnin280"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "variant" = pkgs.stdenv.mkDerivation { name = "variant"; version = "v8.0.0"; diff --git a/spago.dhall b/spago.dhall index 7c92449b8e..dd58114a56 100644 --- a/spago.dhall +++ b/spago.dhall @@ -12,14 +12,24 @@ You can edit this file as you like. , "ansi" , "argonaut" , "argonaut-codecs" - , "arraybuffer-types" , "arrays" , "avar" , "bifunctors" , "bignumber" + , "bytearrays" + , "cardano-hd-wallet" + , "cardano-key-wallet" + , "cardano-message-signing" + , "cardano-plutus-data-schema" + , "cardano-serialization-lib" + , "cardano-transaction-builder" + , "cardano-types" , "checked-exceptions" , "cip30" + , "cip30-mock" , "cip30-typesafe" + , "cip95" + , "cip95-typesafe" , "console" , "control" , "crypto" @@ -27,7 +37,6 @@ You can edit this file as you like. , "debug" , "effect" , "either" - , "encoding" , "enums" , "exceptions" , "foldable-traversable" @@ -35,7 +44,6 @@ You can edit this file as you like. , "foreign-object" , "formatters" , "functions" - , "gen" , "heterogeneous" , "http-methods" , "identity" @@ -44,10 +52,12 @@ You can edit this file as you like. , "js-date" , "lattice" , "lists" + , "literals" , "maybe" , "media-types" , "monad-logger" , "mote" + , "mote-testplan" , "newtype" , "noble-secp256k1" , "node-buffer" @@ -58,26 +68,30 @@ You can edit this file as you like. , "node-process" , "node-readline" , "node-streams" + , "node-streams-aff" , "nonempty" , "now" + , "nullable" , "numbers" , "optparse" , "ordered-collections" , "orders" , "parallel" + , "parsing" , "partial" + , "plutus-types" , "posix-types" , "prelude" , "profunctor" , "profunctor-lenses" , "quickcheck" , "quickcheck-combinators" - , "quickcheck-laws" , "random" , "rationals" , "record" , "refs" , "safe-coerce" + , "safely" , "spec" , "spec-quickcheck" , "strings" @@ -87,11 +101,12 @@ You can edit this file as you like. , "toppokki" , "transformers" , "tuples" - , "typelevel" , "typelevel-prelude" , "uint" , "unfoldable" + , "unsafe-coerce" , "untagged-union" + , "uplc-apply-args" , "variant" , "web-html" , "web-storage" @@ -99,8 +114,8 @@ You can edit this file as you like. , packages = ./packages.dhall , sources = [ "src/**/*.purs" - , "test/**/*.purs" , "examples/**/*.purs" + , "test/**/*.purs" , "templates/ctl-scaffold/src/**/*.purs" , "templates/ctl-scaffold/test/**/*.purs" , "templates/ctl-scaffold/exe/**/*.purs" diff --git a/src/Contract/Address.purs b/src/Contract/Address.purs index 0fbab38e0b..b9f37dde71 100644 --- a/src/Contract/Address.purs +++ b/src/Contract/Address.purs @@ -1,218 +1,58 @@ --- | A module for Address-related functionality. module Contract.Address - ( addressPaymentValidatorHash - , addressStakeValidatorHash - , getNetworkId - , addressWithNetworkTagFromBech32 - , addressWithNetworkTagToBech32 + ( getNetworkId , addressFromBech32 - , addressToBech32 + , mkAddress , module X - , module TypeAliases - , payPubKeyHashBaseAddress - , payPubKeyHashEnterpriseAddress - , payPubKeyHashRewardAddress - , pubKeyHashBaseAddress - , pubKeyHashEnterpriseAddress - , pubKeyHashRewardAddress - , stakePubKeyHashRewardAddress - , validatorHashBaseAddress - , validatorHashEnterpriseAddress ) where import Prelude -import Contract.Monad (Contract, liftContractM) -import Control.Monad.Error.Class (throwError) -import Control.Monad.Reader.Class (asks) -import Ctl.Internal.Address - ( addressPaymentValidatorHash - , addressStakeValidatorHash - ) as Address -import Ctl.Internal.Plutus.Conversion - ( fromPlutusAddress - , fromPlutusAddressWithNetworkTag - , toPlutusAddress - ) -import Ctl.Internal.Plutus.Types.Address +import Cardano.Types ( Address - , AddressWithNetworkTag(AddressWithNetworkTag) - ) -import Ctl.Internal.Plutus.Types.Address - ( Address - , AddressWithNetworkTag(AddressWithNetworkTag) - , pubKeyHashAddress - , scriptHashAddress - , toPubKeyHash - , toStakingCredential - , toValidatorHash - ) as X -import Ctl.Internal.Scripts - ( validatorHashBaseAddress - , validatorHashEnterpriseAddress - ) as Scripts -import Ctl.Internal.Serialization.Address - ( BlockId(BlockId) - , ByronProtocolMagic(ByronProtocolMagic) - , CertificateIndex(CertificateIndex) - , NetworkId(TestnetId, MainnetId) - , Pointer - , Slot(Slot) - , TransactionIndex(TransactionIndex) - ) as X -import Ctl.Internal.Serialization.Address - ( NetworkId(MainnetId) - , addressBech32 - , addressNetworkId + , Bech32String + , NetworkId + , PaymentCredential + , StakeCredential ) -import Ctl.Internal.Serialization.Address (addressFromBech32) as SA -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash) as X -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.Aliases (Bech32String) as TypeAliases -import Ctl.Internal.Types.PaymentPubKey (PaymentPubKey(PaymentPubKey)) as X -import Ctl.Internal.Types.PubKeyHash - ( PaymentPubKeyHash - , PubKeyHash - , StakePubKeyHash - ) -import Ctl.Internal.Types.PubKeyHash - ( PaymentPubKeyHash(PaymentPubKeyHash) - , PubKeyHash(PubKeyHash) +import Cardano.Types + ( Ed25519KeyHash + , PaymentPubKeyHash(PaymentPubKeyHash) , StakePubKeyHash(StakePubKeyHash) ) as X -import Ctl.Internal.Types.PubKeyHash - ( payPubKeyHashBaseAddress - , payPubKeyHashEnterpriseAddress - , payPubKeyHashRewardAddress - , pubKeyHashBaseAddress - , pubKeyHashEnterpriseAddress - , pubKeyHashRewardAddress - , stakePubKeyHashRewardAddress - ) as PubKeyHash -import Ctl.Internal.Types.Scripts (StakeValidatorHash, ValidatorHash) +import Cardano.Types.Address + ( Address + ( BaseAddress + , ByronAddress + , EnterpriseAddress + , RewardAddress + , PointerAddress + ) + ) as X +import Cardano.Types.Address (mkPaymentAddress) +import Cardano.Types.Address as Address +import Contract.Monad (Contract, liftContractM) +import Control.Monad.Error.Class (throwError) +import Control.Monad.Reader.Class (asks) import Data.Maybe (Maybe) import Effect.Exception (error) getNetworkId :: Contract NetworkId getNetworkId = asks _.networkId --------------------------------------------------------------------------------- --- Helpers via Cardano helpers, these are helpers from the CSL equivalent --- that convert either input or output to a Plutus Address. --- Helpers that deconstruct/construct the Plutus Address are exported under --- `module Address` --------------------------------------------------------------------------------- - --- | Convert `Address` to `Bech32String`, using given `NetworkId` to determine --- | Bech32 prefix. -addressWithNetworkTagToBech32 :: AddressWithNetworkTag -> Bech32String -addressWithNetworkTagToBech32 = fromPlutusAddressWithNetworkTag >>> - addressBech32 - --- | Convert `Bech32String` to `AddressWithNetworkTag`. -addressWithNetworkTagFromBech32 :: Bech32String -> Maybe AddressWithNetworkTag -addressWithNetworkTagFromBech32 str = do - cslAddress <- SA.addressFromBech32 str - address <- toPlutusAddress cslAddress - let networkId = addressNetworkId cslAddress - pure $ AddressWithNetworkTag { address, networkId } - --- | Convert `Address` to `Bech32String`, using current `NetworkId` provided by --- | `Contract` configuration to determine the network tag. -addressToBech32 :: Address -> Contract Bech32String -addressToBech32 address = do - networkId <- getNetworkId - pure $ addressWithNetworkTagToBech32 - (AddressWithNetworkTag { address, networkId }) - -- | Convert `Bech32String` to `Address`, asserting that the address `networkId` -- | corresponds to the contract environment `networkId` addressFromBech32 :: Bech32String -> Contract Address addressFromBech32 str = do networkId <- getNetworkId - cslAddress <- liftContractM "addressFromBech32: unable to read address" $ - SA.addressFromBech32 str - address <- - liftContractM "addressFromBech32: unable to convert to plutus address" $ - toPlutusAddress cslAddress - when (networkId /= addressNetworkId cslAddress) + addr <- liftContractM "addressFromBech32: unable to read address" $ + Address.fromBech32 str + when (networkId /= Address.getNetworkId addr) (throwError $ error "addressFromBech32: address has wrong NetworkId") - pure address - --- | Get the `ValidatorHash` component of a Plutus `Address` -addressPaymentValidatorHash :: Address -> Maybe ValidatorHash -addressPaymentValidatorHash = - -- Network id does not matter here (#484) - Address.addressPaymentValidatorHash - <<< fromPlutusAddress MainnetId - --- | Get the `ValidatorHash` component of a Plutus `Address` -addressStakeValidatorHash :: Address -> Maybe StakeValidatorHash -addressStakeValidatorHash = - -- Network id does not matter here (#484) - Address.addressStakeValidatorHash - <<< fromPlutusAddress MainnetId - --- | Converts a Plutus `ValidatorHash` to a `Address` as a Plutus (`BaseAddress`) --- | `Address` -validatorHashBaseAddress - :: NetworkId -> ValidatorHash -> Maybe Address -validatorHashBaseAddress networkId = - toPlutusAddress - <<< Scripts.validatorHashBaseAddress networkId - --- | Converts a Plutus `ValidatorHash` to a Plutus `Address` as an --- | `EnterpriseAddress`. This is likely what you will use since Plutus --- | currently uses `scriptHashAddress` on non-staking addresses which is --- | invoked in `validatorAddress` -validatorHashEnterpriseAddress - :: NetworkId -> ValidatorHash -> Maybe Address -validatorHashEnterpriseAddress networkId = - toPlutusAddress - <<< Scripts.validatorHashEnterpriseAddress networkId + pure addr -pubKeyHashBaseAddress - :: NetworkId -> PubKeyHash -> StakePubKeyHash -> Maybe Address -pubKeyHashBaseAddress networkId pkh = - toPlutusAddress - <<< PubKeyHash.pubKeyHashBaseAddress networkId pkh - -pubKeyHashRewardAddress - :: NetworkId -> PubKeyHash -> Maybe Address -pubKeyHashRewardAddress networkId = - toPlutusAddress - <<< PubKeyHash.pubKeyHashRewardAddress networkId - -pubKeyHashEnterpriseAddress - :: NetworkId -> PubKeyHash -> Maybe Address -pubKeyHashEnterpriseAddress networkId = - toPlutusAddress - <<< PubKeyHash.pubKeyHashEnterpriseAddress networkId - -payPubKeyHashRewardAddress - :: NetworkId -> PaymentPubKeyHash -> Maybe Address -payPubKeyHashRewardAddress networkId = - toPlutusAddress - <<< PubKeyHash.payPubKeyHashRewardAddress networkId - -payPubKeyHashBaseAddress - :: NetworkId - -> PaymentPubKeyHash - -> StakePubKeyHash - -> Maybe Address -payPubKeyHashBaseAddress networkId pkh = - toPlutusAddress - <<< PubKeyHash.payPubKeyHashBaseAddress networkId pkh - -payPubKeyHashEnterpriseAddress - :: NetworkId -> PaymentPubKeyHash -> Maybe Address -payPubKeyHashEnterpriseAddress networkId = - toPlutusAddress - <<< PubKeyHash.payPubKeyHashEnterpriseAddress networkId - -stakePubKeyHashRewardAddress - :: NetworkId -> StakePubKeyHash -> Maybe Address -stakePubKeyHashRewardAddress networkId = - toPlutusAddress - <<< PubKeyHash.stakePubKeyHashRewardAddress networkId +mkAddress + :: PaymentCredential -> Maybe StakeCredential -> Contract Address +mkAddress pc msc = do + networkId <- getNetworkId + pure $ mkPaymentAddress networkId pc msc diff --git a/src/Contract/AssocMap.purs b/src/Contract/AssocMap.purs deleted file mode 100644 index 419361f046..0000000000 --- a/src/Contract/AssocMap.purs +++ /dev/null @@ -1,22 +0,0 @@ --- | A module for a Plutus-style `AssocMap` -module Contract.AssocMap (module AssocMap) where - -import Ctl.Internal.Plutus.Types.AssocMap - ( Map(Map) - , delete - , elems - , empty - , filter - , insert - , keys - , lookup - , mapMaybe - , mapMaybeWithKey - , mapThese - , member - , null - , singleton - , union - , unionWith - , values - ) as AssocMap diff --git a/src/Contract/AuxiliaryData.purs b/src/Contract/AuxiliaryData.purs index 718ca81ad3..3edf6ae83b 100644 --- a/src/Contract/AuxiliaryData.purs +++ b/src/Contract/AuxiliaryData.purs @@ -7,76 +7,52 @@ module Contract.AuxiliaryData import Prelude -import Contract.Monad (Contract) -import Ctl.Internal.Cardano.Types.Transaction - ( AuxiliaryData(AuxiliaryData) - , AuxiliaryDataHash +import Cardano.Types + ( AuxiliaryData + , GeneralTransactionMetadata , Transaction - ) -import Ctl.Internal.Cardano.Types.Transaction - ( _auxiliaryData + , _auxiliaryData , _auxiliaryDataHash , _body - ) as Tx + ) +import Cardano.Types.AuxiliaryData (hashAuxiliaryData) import Ctl.Internal.Metadata.MetadataType ( class MetadataType , toGeneralTxMetadata ) -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx) -import Ctl.Internal.Serialization.AuxiliaryData (hashAuxiliaryData) -import Ctl.Internal.Types.TransactionMetadata (GeneralTransactionMetadata) -import Data.Lens (lens', (?~)) +import Data.Lens ((.~), (?~)) import Data.Lens.Getter (view) import Data.Lens.Iso.Newtype (_Newtype) import Data.Lens.Record (prop) -import Data.Lens.Types (Lens') -import Data.Maybe (Maybe, fromMaybe) -import Data.Tuple (Tuple(Tuple)) -import Effect.Class (liftEffect) +import Data.Maybe (Maybe(Just), fromMaybe) import Type.Proxy (Proxy(Proxy)) setAuxiliaryData - :: UnbalancedTx + :: Transaction -> AuxiliaryData - -> Contract UnbalancedTx -setAuxiliaryData tx auxData = liftEffect do - auxDataHash <- hashAuxiliaryData auxData - pure (tx # _auxiliaryData ?~ auxData # _auxiliaryDataHash ?~ auxDataHash) + -> Transaction +setAuxiliaryData tx auxData = + tx # _auxiliaryData .~ Just auxData + # _body <<< _auxiliaryDataHash ?~ hashAuxiliaryData auxData setGeneralTxMetadata - :: UnbalancedTx + :: Transaction -> GeneralTransactionMetadata - -> Contract UnbalancedTx + -> Transaction setGeneralTxMetadata tx generalMetadata = let - auxData = fromMaybe mempty (view _auxiliaryData tx) + auxData = view _auxiliaryData tx in - setAuxiliaryData tx (auxData # _metadata ?~ generalMetadata) + setAuxiliaryData tx + ( fromMaybe mempty auxData # + _Newtype <<< prop (Proxy :: Proxy "metadata") ?~ generalMetadata + ) setTxMetadata :: forall (m :: Type) . MetadataType m - => UnbalancedTx + => Transaction -> m - -> Contract UnbalancedTx + -> Transaction setTxMetadata tx = setGeneralTxMetadata tx <<< toGeneralTxMetadata - --------------------------------------------------------------------------------- --- Lenses --------------------------------------------------------------------------------- - -_transaction :: Lens' UnbalancedTx Transaction -_transaction = _Newtype <<< prop (Proxy :: Proxy "transaction") - -_auxiliaryData :: Lens' UnbalancedTx (Maybe AuxiliaryData) -_auxiliaryData = - _transaction <<< Tx._auxiliaryData - -_auxiliaryDataHash :: Lens' UnbalancedTx (Maybe AuxiliaryDataHash) -_auxiliaryDataHash = - _transaction <<< Tx._body <<< Tx._auxiliaryDataHash - -_metadata :: Lens' AuxiliaryData (Maybe GeneralTransactionMetadata) -_metadata = lens' \(AuxiliaryData rec@{ metadata }) -> - Tuple metadata \md -> AuxiliaryData rec { metadata = md } diff --git a/src/Contract/Backend/Ogmios.purs b/src/Contract/Backend/Ogmios.purs index fc74f77024..c5b5af454e 100644 --- a/src/Contract/Backend/Ogmios.purs +++ b/src/Contract/Backend/Ogmios.purs @@ -4,16 +4,16 @@ module Contract.Backend.Ogmios , submitTxE ) where -import Contract.Prelude +import Prelude +import Cardano.Types (PoolParams, PoolPubKeyHash) +import Cardano.Types.CborBytes (CborBytes) +import Cardano.Types.TransactionHash (TransactionHash) import Contract.Monad (Contract) -import Contract.Transaction (PoolPubKeyHash) -import Ctl.Internal.Cardano.Types.Transaction (PoolRegistrationParams) import Ctl.Internal.Contract.Monad (wrapQueryM) import Ctl.Internal.QueryM (submitTxOgmios) as QueryM -import Ctl.Internal.QueryM.Ogmios (SubmitTxR, TxHash) +import Ctl.Internal.QueryM.Ogmios (SubmitTxR) import Ctl.Internal.QueryM.Pools (getPoolParameters) as QueryM -import Ctl.Internal.Types.CborBytes (CborBytes) -- | **This function can only run with Ogmios backend** -- | @@ -21,9 +21,9 @@ import Ctl.Internal.Types.CborBytes (CborBytes) -- | https://github.com/blockfrost/blockfrost-backend-ryo/issues/82 getPoolParameters :: PoolPubKeyHash - -> Contract PoolRegistrationParams + -> Contract PoolParams getPoolParameters = wrapQueryM <<< QueryM.getPoolParameters -- | Error returning variant -submitTxE :: TxHash -> CborBytes -> Contract SubmitTxR +submitTxE :: TransactionHash -> CborBytes -> Contract SubmitTxR submitTxE txhash cbor = wrapQueryM $ QueryM.submitTxOgmios txhash cbor diff --git a/src/Contract/Backend/Ogmios/Mempool.purs b/src/Contract/Backend/Ogmios/Mempool.purs index 55bc13f3dd..95a0792033 100644 --- a/src/Contract/Backend/Ogmios/Mempool.purs +++ b/src/Contract/Backend/Ogmios/Mempool.purs @@ -14,11 +14,12 @@ module Contract.Backend.Ogmios.Mempool import Contract.Prelude +import Cardano.AsCbor (decodeCbor) +import Cardano.Types.Transaction (Transaction) +import Cardano.Types.TransactionHash (TransactionHash) import Contract.Monad (Contract) import Control.Monad.Error.Class (liftMaybe, try) -import Ctl.Internal.Cardano.Types.Transaction (Transaction) import Ctl.Internal.Contract.Monad (wrapQueryM) -import Ctl.Internal.Deserialization.Transaction (deserializeTransaction) import Ctl.Internal.QueryM ( acquireMempoolSnapshot , mempoolSnapshotHasTx @@ -30,11 +31,9 @@ import Ctl.Internal.QueryM.Ogmios ( MempoolSizeAndCapacity(MempoolSizeAndCapacity) , MempoolSnapshotAcquired , MempoolTransaction(MempoolTransaction) - , TxHash ) as Ogmios -import Ctl.Internal.Types.ByteArray (hexToByteArray) -import Ctl.Internal.Types.Transaction (TransactionHash) import Data.Array as Array +import Data.ByteArray (hexToByteArray) import Data.List (List(Cons)) import Data.Maybe (Maybe(Just, Nothing)) import Effect.Exception (error) @@ -48,8 +47,7 @@ acquireMempoolSnapshot = wrapQueryM QueryM.acquireMempoolSnapshot -- | Check to see if a TxHash is present in the current mempool snapshot. mempoolSnapshotHasTx :: Ogmios.MempoolSnapshotAcquired -> TransactionHash -> Contract Boolean -mempoolSnapshotHasTx ms = wrapQueryM <<< QueryM.mempoolSnapshotHasTx ms <<< - unwrap +mempoolSnapshotHasTx ms = wrapQueryM <<< QueryM.mempoolSnapshotHasTx ms -- | Get the first received TX in the current mempool snapshot. This function can -- | be recursively called to traverse the finger-tree of the mempool data set. @@ -63,8 +61,7 @@ mempoolSnapshotNextTx mempoolAcquired = do byteArray <- liftMaybe (error "Failed to decode transaction") $ hexToByteArray raw liftMaybe (error "Failed to decode tx") - $ hush - $ deserializeTransaction + $ decodeCbor $ wrap byteArray -- | The acquired snapshot’s size (in bytes), number of transactions, and diff --git a/src/Contract/BalanceTxConstraints.purs b/src/Contract/BalanceTxConstraints.purs index e86a23246b..b292cd321c 100644 --- a/src/Contract/BalanceTxConstraints.purs +++ b/src/Contract/BalanceTxConstraints.purs @@ -4,6 +4,8 @@ module Contract.BalanceTxConstraints (module BalanceTxConstraints) where import Ctl.Internal.BalanceTx.Constraints ( BalanceTxConstraintsBuilder + , BalancerConfig(BalancerConfig) + , BalancerConstraints(BalancerConstraints) , UtxoPredicate , mustGenChangeOutsWithMaxTokenQuantity , mustNotSpendUtxoWithOutRef diff --git a/src/Contract/CborBytes.purs b/src/Contract/CborBytes.purs index bcc9765998..1bd9f198c6 100644 --- a/src/Contract/CborBytes.purs +++ b/src/Contract/CborBytes.purs @@ -1,16 +1,57 @@ -- | A module with CBOR-related functionality. -module Contract.CborBytes (module CborBytes) where - -import Ctl.Internal.Types.CborBytes - ( CborBytes(CborBytes) - , cborByteLength - , cborBytesFromAscii - , cborBytesFromByteArray +module Contract.CborBytes + ( module CborBytes + , cborBytesToIntArray , cborBytesFromIntArray , cborBytesFromIntArrayUnsafe - , cborBytesToByteArray , cborBytesToHex - , cborBytesToIntArray + , cborByteLength , hexToCborBytes , hexToCborBytesUnsafe - ) as CborBytes + , cborBytesToByteArray + , cborBytesFromByteArray + , cborBytesFromAscii + , rawBytesAsCborBytes + ) where + +import Prelude + +import Cardano.Types (CborBytes, RawBytes) +import Cardano.Types.CborBytes (CborBytes(CborBytes)) as CborBytes +import Data.ByteArray (ByteArray) +import Data.ByteArray as ByteArray +import Data.Maybe (Maybe) +import Data.Newtype (unwrap, wrap) + +cborBytesToIntArray :: CborBytes -> Array Int +cborBytesToIntArray = ByteArray.byteArrayToIntArray <<< unwrap + +cborBytesFromIntArray :: Array Int -> Maybe CborBytes +cborBytesFromIntArray = map wrap <<< ByteArray.byteArrayFromIntArray + +cborBytesFromIntArrayUnsafe :: Array Int -> CborBytes +cborBytesFromIntArrayUnsafe = wrap <<< ByteArray.byteArrayFromIntArrayUnsafe + +cborBytesToHex :: CborBytes -> String +cborBytesToHex = ByteArray.byteArrayToHex <<< unwrap + +cborByteLength :: CborBytes -> Int +cborByteLength = ByteArray.byteLength <<< unwrap + +hexToCborBytes :: String -> Maybe CborBytes +hexToCborBytes = map wrap <<< ByteArray.hexToByteArray + +hexToCborBytesUnsafe :: String -> CborBytes +hexToCborBytesUnsafe = wrap <<< ByteArray.hexToByteArrayUnsafe + +cborBytesToByteArray :: CborBytes -> ByteArray +cborBytesToByteArray = unwrap + +cborBytesFromByteArray :: ByteArray -> CborBytes +cborBytesFromByteArray = wrap + +cborBytesFromAscii :: String -> Maybe CborBytes +cborBytesFromAscii = map wrap <<< ByteArray.byteArrayFromAscii + +rawBytesAsCborBytes :: RawBytes -> CborBytes +rawBytesAsCborBytes = wrap <<< unwrap diff --git a/src/Contract/ClientError.purs b/src/Contract/ClientError.purs index cbac2a82e2..f6633e2e11 100644 --- a/src/Contract/ClientError.purs +++ b/src/Contract/ClientError.purs @@ -13,4 +13,5 @@ import Ctl.Internal.Service.Error ( ServiceBlockfrostError , ServiceOtherError ) + , pprintClientError ) as X diff --git a/src/Contract/Config.purs b/src/Contract/Config.purs index 9bf4a5dee5..cc50b759ff 100644 --- a/src/Contract/Config.purs +++ b/src/Contract/Config.purs @@ -1,35 +1,24 @@ -- | Exposes some pre-defined Contract configurations. Re-exports all modules needed to modify `ContractParams`. module Contract.Config ( testnetConfig - , testnetNamiConfig - , testnetGeroConfig - , testnetFlintConfig - , testnetEternlConfig - , testnetLodeConfig - , testnetNuFiConfig - , testnetLaceConfig , mainnetConfig - , mainnetNamiConfig - , mainnetGeroConfig - , mainnetFlintConfig - , mainnetEternlConfig - , mainnetLodeConfig - , mainnetNuFiConfig - , mainnetLaceConfig , defaultSynchronizationParams , strictSynchronizationParams + , softSynchronizationParams , defaultTimeParams - , module Contract.Address , module Data.Log.Level , module Data.Log.Message - , module Ctl.Internal.Deserialization.Keys , module Ctl.Internal.ServerConfig , module Ctl.Internal.Wallet.Spec - , module Ctl.Internal.Wallet.Key + , module Cardano.Wallet.Key , module X ) where -import Contract.Address (NetworkId(MainnetId, TestnetId)) +import Cardano.Types (NetworkId(MainnetId, TestnetId)) +import Cardano.Wallet.Key + ( PrivatePaymentKey(PrivatePaymentKey) + , PrivateStakeKey(PrivateStakeKey) + ) import Ctl.Internal.BalanceTx.Sync ( disabledSynchronizationParams ) as X @@ -59,7 +48,6 @@ import Ctl.Internal.Contract.QueryBackend , mkSelfHostedBlockfrostBackendParams ) as X import Ctl.Internal.Contract.QueryBackend (mkCtlBackendParams) -import Ctl.Internal.Deserialization.Keys (privateKeyFromBytes) import Ctl.Internal.ServerConfig ( Host , ServerConfig @@ -70,32 +58,19 @@ import Ctl.Internal.ServerConfig , defaultKupoServerConfig , defaultOgmiosWsConfig ) -import Ctl.Internal.Wallet.Key - ( PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey(PrivateStakeKey) - ) import Ctl.Internal.Wallet.Spec ( Cip1852DerivationPath + , KnownWallet(Nami, Gero, Flint, Eternl, Lode, Lace, NuFi) , MnemonicSource(MnemonicString, MnemonicFile) , PrivatePaymentKeySource(PrivatePaymentKeyFile, PrivatePaymentKeyValue) , PrivateStakeKeySource(PrivateStakeKeyFile, PrivateStakeKeyValue) , StakeKeyPresence(WithStakeKey, WithoutStakeKey) - , WalletSpec - ( UseKeys - , UseMnemonic - , ConnectToNami - , ConnectToGero - , ConnectToFlint - , ConnectToEternl - , ConnectToLode - , ConnectToNuFi - , ConnectToLace - , ConnectToGenericCip30 - ) + , WalletSpec(UseKeys, UseMnemonic, ConnectToGenericCip30) + , walletName ) import Data.Log.Level (LogLevel(Trace, Debug, Info, Warn, Error)) import Data.Log.Message (Message) -import Data.Maybe (Maybe(Just, Nothing)) +import Data.Maybe (Maybe(Nothing)) import Data.Number (infinity) import Data.Time.Duration (Milliseconds(Milliseconds), Seconds(Seconds)) @@ -115,6 +90,9 @@ testnetConfig = , synchronizationParams: defaultSynchronizationParams } +mainnetConfig :: ContractParams +mainnetConfig = testnetConfig { networkId = MainnetId } + -- | - `syncWallet` specifies delay and timeout for `syncWalletWithTransaction` -- | and `syncWalletWithTxInputs` synchronization primitives. -- | See `doc/query-layers.md` for more info. @@ -139,11 +117,25 @@ defaultTimeParams = , waitUntilSlot: { delay: Milliseconds 1_000.0 } } --- | Default synchronization parameters with all synchronization primitives --- | enabled. `errorOnTimeout` options are all set to `false`. +-- | Default synchronization parameters with all synchronizations +-- | disabled. -- | See `doc/query-layers.md` for more info. defaultSynchronizationParams :: ContractSynchronizationParams defaultSynchronizationParams = + { syncBackendWithWallet: + { errorOnTimeout: false + , beforeCip30Methods: false + , beforeBalancing: false + } + , syncWalletWithTxInputs: { errorOnTimeout: false, beforeCip30Sign: false } + , syncWalletWithTransaction: + { errorOnTimeout: false, beforeTxConfirmed: false } + } + +-- | Attempt to synchronize, but do not throw an exception on failure. Used to be the default option in CTL up to and including v8. +-- | See `doc/query-layers.md` for more info. +softSynchronizationParams :: ContractSynchronizationParams +softSynchronizationParams = { syncBackendWithWallet: { errorOnTimeout: false, beforeCip30Methods: true, beforeBalancing: true } , syncWalletWithTxInputs: { errorOnTimeout: false, beforeCip30Sign: true } @@ -161,48 +153,3 @@ strictSynchronizationParams = , syncWalletWithTxInputs: { errorOnTimeout: true, beforeCip30Sign: true } , syncWalletWithTransaction: { errorOnTimeout: true, beforeTxConfirmed: true } } - -testnetNamiConfig :: ContractParams -testnetNamiConfig = testnetConfig { walletSpec = Just ConnectToNami } - -testnetGeroConfig :: ContractParams -testnetGeroConfig = testnetConfig { walletSpec = Just ConnectToGero } - -testnetFlintConfig :: ContractParams -testnetFlintConfig = testnetConfig { walletSpec = Just ConnectToFlint } - -testnetEternlConfig :: ContractParams -testnetEternlConfig = testnetConfig { walletSpec = Just ConnectToEternl } - -testnetLodeConfig :: ContractParams -testnetLodeConfig = testnetConfig { walletSpec = Just ConnectToLode } - -testnetNuFiConfig :: ContractParams -testnetNuFiConfig = testnetConfig { walletSpec = Just ConnectToNuFi } - -testnetLaceConfig :: ContractParams -testnetLaceConfig = testnetConfig { walletSpec = Just ConnectToLace } - -mainnetConfig :: ContractParams -mainnetConfig = testnetConfig { networkId = MainnetId } - -mainnetNamiConfig :: ContractParams -mainnetNamiConfig = mainnetConfig { walletSpec = Just ConnectToNami } - -mainnetGeroConfig :: ContractParams -mainnetGeroConfig = mainnetConfig { walletSpec = Just ConnectToGero } - -mainnetFlintConfig :: ContractParams -mainnetFlintConfig = mainnetConfig { walletSpec = Just ConnectToFlint } - -mainnetEternlConfig :: ContractParams -mainnetEternlConfig = mainnetConfig { walletSpec = Just ConnectToEternl } - -mainnetLodeConfig :: ContractParams -mainnetLodeConfig = mainnetConfig { walletSpec = Just ConnectToLode } - -mainnetNuFiConfig :: ContractParams -mainnetNuFiConfig = mainnetConfig { walletSpec = Just ConnectToNuFi } - -mainnetLaceConfig :: ContractParams -mainnetLaceConfig = mainnetConfig { walletSpec = Just ConnectToLace } diff --git a/src/Contract/Credential.purs b/src/Contract/Credential.purs index e190dbb4dc..a02f205ac7 100644 --- a/src/Contract/Credential.purs +++ b/src/Contract/Credential.purs @@ -1,7 +1,5 @@ --- | A module for Plutus-style `Credential`s -module Contract.Credential (module Credential) where +module Contract.Credential (module X) where -import Ctl.Internal.Plutus.Types.Credential - ( Credential(PubKeyCredential, ScriptCredential) - , StakingCredential(StakingHash, StakingPtr) - ) as Credential +import Cardano.Types.Credential + ( Credential(PubKeyHashCredential, ScriptHashCredential) + ) as X diff --git a/src/Contract/Crypto/Secp256k1/ECDSA.purs b/src/Contract/Crypto/Secp256k1/ECDSA.purs index 82414448ca..6c553e259e 100644 --- a/src/Contract/Crypto/Secp256k1/ECDSA.purs +++ b/src/Contract/Crypto/Secp256k1/ECDSA.purs @@ -14,9 +14,9 @@ module Contract.Crypto.Secp256k1.ECDSA import Prelude import Contract.Crypto.Secp256k1 (Secp256k1PrivateKey) -import Ctl.Internal.Types.ByteArray (ByteArray) +import Data.ByteArray (ByteArray) import Data.Maybe (Maybe) -import Data.Newtype (unwrap, wrap) +import Data.Newtype (unwrap) import Effect.Aff (Aff) import Noble.Secp256k1.ECDSA (ECDSAPublicKey, ECDSASignature, MessageHash) as X import Noble.Secp256k1.ECDSA @@ -57,17 +57,17 @@ deriveEcdsaSecp256k1PublicKey = unwrap >>> flip ECDSA.getECDSAPublicKey true -- | Construct a public key from its byte representation. mkECDSAPublicKey :: ByteArray -> Maybe ECDSAPublicKey -mkECDSAPublicKey = unwrap >>> ECDSA.mkECDSAPublicKey +mkECDSAPublicKey = ECDSA.mkECDSAPublicKey unECDSAPublicKey :: ECDSAPublicKey -> ByteArray -unECDSAPublicKey = ECDSA.unECDSAPublicKey >>> wrap +unECDSAPublicKey = ECDSA.unECDSAPublicKey -- | Construct a message hash from its byte representation. -- | -- | This function **DOES NOT** compute the hash. -- | Use `Contract.Crypto.Utils.hashMessageSha256` for that. mkMessageHash :: ByteArray -> Maybe MessageHash -mkMessageHash = unwrap >>> ECDSA.mkMessageHash +mkMessageHash = ECDSA.mkMessageHash unMessageHash :: MessageHash -> ByteArray -unMessageHash = wrap <<< ECDSA.unMessageHash +unMessageHash = ECDSA.unMessageHash diff --git a/src/Contract/Crypto/Secp256k1/Schnorr.purs b/src/Contract/Crypto/Secp256k1/Schnorr.purs index 7af5e64601..e567fb6593 100644 --- a/src/Contract/Crypto/Secp256k1/Schnorr.purs +++ b/src/Contract/Crypto/Secp256k1/Schnorr.purs @@ -12,9 +12,9 @@ module Contract.Crypto.Secp256k1.Schnorr import Prelude import Contract.Crypto.Secp256k1 (Secp256k1PrivateKey) -import Ctl.Internal.Types.ByteArray (ByteArray) +import Data.ByteArray (ByteArray) import Data.Maybe (Maybe) -import Data.Newtype (unwrap, wrap) +import Data.Newtype (unwrap) import Effect.Aff (Aff) import Noble.Secp256k1.Schnorr (SchnorrPublicKey, SchnorrSignature) as X import Noble.Secp256k1.Schnorr @@ -33,12 +33,12 @@ import Noble.Secp256k1.Schnorr (mkSchnorrPublicKey, unSchnorrPublicKey) as ECDSA verifySchnorrSecp256k1Signature :: SchnorrPublicKey -> ByteArray -> SchnorrSignature -> Aff Boolean verifySchnorrSecp256k1Signature publicKey message signature = - verifySchnorr signature (unwrap message) publicKey + verifySchnorr signature message publicKey -- | Sign a message using Schnorr signature scheme. signSchnorrSecp256k1 :: Secp256k1PrivateKey -> ByteArray -> Aff SchnorrSignature signSchnorrSecp256k1 privateKey message = - signSchnorr (unwrap message) (unwrap privateKey) + signSchnorr message (unwrap privateKey) deriveSchnorrSecp256k1PublicKey :: Secp256k1PrivateKey -> SchnorrPublicKey deriveSchnorrSecp256k1PublicKey = unwrap >>> getSchnorrPublicKey @@ -46,7 +46,7 @@ deriveSchnorrSecp256k1PublicKey = unwrap >>> getSchnorrPublicKey -- | Construct a public key from its byte representation. mkSchnorrPublicKey :: ByteArray -> Maybe SchnorrPublicKey -mkSchnorrPublicKey = unwrap >>> ECDSA.mkSchnorrPublicKey +mkSchnorrPublicKey = ECDSA.mkSchnorrPublicKey unSchnorrPublicKey :: SchnorrPublicKey -> ByteArray -unSchnorrPublicKey = wrap <<< ECDSA.unSchnorrPublicKey +unSchnorrPublicKey = ECDSA.unSchnorrPublicKey diff --git a/src/Contract/Crypto/Secp256k1/Utils.purs b/src/Contract/Crypto/Secp256k1/Utils.purs index 9f5e030967..dc81204eb4 100644 --- a/src/Contract/Crypto/Secp256k1/Utils.purs +++ b/src/Contract/Crypto/Secp256k1/Utils.purs @@ -9,7 +9,7 @@ module Contract.Crypto.Secp256k1.Utils import Prelude import Contract.Crypto.Secp256k1 (Secp256k1PrivateKey) -import Ctl.Internal.Types.ByteArray (ByteArray) +import Data.ByteArray (ByteArray) import Data.Maybe (Maybe) import Data.Newtype (unwrap, wrap) import Effect (Effect) @@ -25,7 +25,7 @@ randomSecp256k1PrivateKey = wrap <$> Utils.randomPrivateKey -- | Hash a byte array using sha256, for use with `signEcdsaSecp256k1` -- | and `verifyEcdsaSecp256k1Signature`. hashMessageSha256 :: ByteArray -> Aff MessageHash -hashMessageSha256 = unwrap >>> sha256 +hashMessageSha256 = sha256 -- | Deterministically derive a private key given an array of bytes. -- | Array size must be between 40 and 1024 bytes. @@ -38,7 +38,7 @@ deriveSecp256k1PrivateKey = unwrap >>> hashToPrivateKey >>> map wrap -- | Attempt to convert a byte array containing a byte-representation of a -- | private key to a private key. Invalid values will be rejected. mkSecp256k1PrivateKey :: ByteArray -> Maybe Secp256k1PrivateKey -mkSecp256k1PrivateKey = unwrap >>> ECDSA.mkPrivateKey >>> map wrap +mkSecp256k1PrivateKey = ECDSA.mkPrivateKey >>> map wrap unSecp256k1PrivateKey :: Secp256k1PrivateKey -> ByteArray -unSecp256k1PrivateKey = wrap <<< ECDSA.unPrivateKey <<< unwrap +unSecp256k1PrivateKey = ECDSA.unPrivateKey <<< unwrap diff --git a/src/Contract/Hashing.purs b/src/Contract/Hashing.purs index b17ae3854e..bab5ee7af6 100644 --- a/src/Contract/Hashing.purs +++ b/src/Contract/Hashing.purs @@ -1,49 +1,39 @@ -module Contract.Hashing - ( module X - , transactionHash - , publicKeyHash - , auxiliaryDataHash - ) where +module Contract.Hashing where -import Prelude - -import Contract.Scripts (plutusScriptStakeValidatorHash) as X -import Ctl.Internal.Cardano.Types.Transaction - ( AuxiliaryData - , AuxiliaryDataHash +import Cardano.Types + ( DataHash + , Ed25519KeyHash + , NativeScript + , PlutusData , PublicKey - , Transaction - , convertPubKey ) -import Ctl.Internal.Hashing - ( blake2b224Hash - , blake2b224HashHex - , blake2b256Hash - , blake2b256HashHex - , datumHash - , md5HashHex - , plutusScriptHash - , scriptRefHash - , sha256Hash - , sha256HashHex - , sha3_256Hash - , sha3_256HashHex - ) as X -import Ctl.Internal.Hashing (transactionHash) as Internal -import Ctl.Internal.NativeScripts (nativeScriptHash) as X -import Ctl.Internal.Serialization (convertTransaction) -import Ctl.Internal.Serialization (publicKeyHash) as Internal -import Ctl.Internal.Serialization.AuxiliaryData (hashAuxiliaryData) -import Ctl.Internal.Types.PubKeyHash (PubKeyHash) -import Ctl.Internal.Types.Transaction (TransactionHash) -import Data.Newtype (wrap) -import Effect (Effect) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.NativeScript as NativeScript +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.PublicKey as PublicKey +import Cardano.Types.ScriptHash (ScriptHash) +import Cardano.Types.ScriptRef (ScriptRef(PlutusScriptRef, NativeScriptRef)) +import Prim.TypeError (class Warn, Text) + +nativeScriptHash + :: Warn (Text "deprecated: publicKeyHash. use Cardano.Types.PublicKey.hash") + => NativeScript + -> ScriptHash +nativeScriptHash = NativeScript.hash -transactionHash :: Transaction -> Effect TransactionHash -transactionHash tx = Internal.transactionHash <$> convertTransaction tx +publicKeyHash + :: Warn (Text "deprecated: publicKeyHash. use Cardano.Types.PublicKey.hash") + => PublicKey + -> Ed25519KeyHash +publicKeyHash = PublicKey.hash -publicKeyHash :: PublicKey -> PubKeyHash -publicKeyHash pk = wrap $ Internal.publicKeyHash $ convertPubKey pk +datumHash + :: Warn + (Text "deprecated: datumHash. use Cardano.Types.DataHash.hashPlutusData") + => PlutusData + -> DataHash +datumHash = hashPlutusData -auxiliaryDataHash :: AuxiliaryData -> Effect AuxiliaryDataHash -auxiliaryDataHash = hashAuxiliaryData +scriptRefHash :: ScriptRef -> ScriptHash +scriptRefHash (PlutusScriptRef ps) = PlutusScript.hash ps +scriptRefHash (NativeScriptRef ns) = NativeScript.hash ns diff --git a/src/Contract/Keys.purs b/src/Contract/Keys.purs index ba09afeb5c..5163011bad 100644 --- a/src/Contract/Keys.purs +++ b/src/Contract/Keys.purs @@ -1,9 +1,27 @@ -- | Exposes constructors for `PublicKey` and `Ed25519Signature` types module Contract.Keys - ( module Keys + ( privateKeyFromBech32 + , privateKeyFromBytes + , publicKeyFromBech32 + , publicKeyFromBytes ) where -import Ctl.Internal.Cardano.Types.Transaction - ( mkEd25519Signature - , mkPublicKey - ) as Keys +import Cardano.Types (Bech32String, RawBytes) +import Cardano.Types.PrivateKey (PrivateKey) +import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Types.PublicKey (PublicKey) +import Cardano.Types.PublicKey as PublicKey +import Data.Maybe (Maybe) + +privateKeyFromBytes :: RawBytes -> Maybe PrivateKey +privateKeyFromBytes = PrivateKey.fromRawBytes + +privateKeyFromBech32 :: Bech32String -> Maybe PrivateKey +privateKeyFromBech32 = PrivateKey.fromBech32 + +publicKeyFromBytes :: RawBytes -> Maybe PublicKey +publicKeyFromBytes = + PublicKey.fromRawBytes + +publicKeyFromBech32 :: Bech32String -> Maybe PublicKey +publicKeyFromBech32 = PublicKey.fromBech32 diff --git a/src/Contract/Metadata.purs b/src/Contract/Metadata.purs index e2e1ba134d..79ad77753e 100644 --- a/src/Contract/Metadata.purs +++ b/src/Contract/Metadata.purs @@ -1,24 +1,8 @@ module Contract.Metadata - ( module Cip25Metadata - , module Cip25String - , module TransactionMetadata + ( module X ) where -import Ctl.Internal.Metadata.Cip25.Cip25String - ( Cip25String - , mkCip25String - , unCip25String - ) as Cip25String -import Ctl.Internal.Metadata.Cip25.V2 - ( Cip25Metadata(Cip25Metadata) - , Cip25MetadataEntry(Cip25MetadataEntry) - , Cip25MetadataFile(Cip25MetadataFile) - , Cip25TokenName(Cip25TokenName) - , nftMetadataLabel - ) as Cip25Metadata -import Ctl.Internal.Types.TransactionMetadata - ( GeneralTransactionMetadata(GeneralTransactionMetadata) - , TransactionMetadatum(Bytes, Int, MetadataList, MetadataMap, Text) - , TransactionMetadatumLabel(TransactionMetadatumLabel) - ) as TransactionMetadata - +import Cardano.Types (GeneralTransactionMetadata(GeneralTransactionMetadata)) as X +import Cardano.Types.TransactionMetadatum + ( TransactionMetadatum(Map, List, Int, Bytes, Text) + ) as X diff --git a/src/Contract/Monad.purs b/src/Contract/Monad.purs index 9bdddc400b..2d750e0bcb 100644 --- a/src/Contract/Monad.purs +++ b/src/Contract/Monad.purs @@ -2,7 +2,6 @@ module Contract.Monad ( module ExportAff , module ExportContract - , module ExportLogTag , liftContractAffM , liftContractE , liftContractE' @@ -32,15 +31,6 @@ import Ctl.Internal.Contract.Monad , stopContractEnv ) as Contract import Data.Either (Either, either, hush) -import Data.Log.Tag - ( TagSet - , booleanTag - , intTag - , jsDateTag - , numberTag - , tag - , tagSetTag - ) as ExportLogTag import Data.Maybe (Maybe, maybe) import Effect.Aff (Aff) import Effect.Aff (Aff, launchAff_) as ExportAff @@ -124,4 +114,3 @@ liftedM str = (=<<) (liftContractM str) -- | and lifting into the `Contract` monad. throwContractError :: forall (e :: Type) (a :: Type). Show e => e -> Contract a throwContractError = liftEffect <<< throw <<< show - diff --git a/src/Contract/Numeric/BigNum.purs b/src/Contract/Numeric/BigNum.purs index e8e986728a..a3836a9e97 100644 --- a/src/Contract/Numeric/BigNum.purs +++ b/src/Contract/Numeric/BigNum.purs @@ -1,14 +1,23 @@ module Contract.Numeric.BigNum (module X) where -import Ctl.Internal.Types.BigNum - ( BigNum +import Cardano.Types.BigNum + ( BigNum(BigNum) + , abs , add + , divFloor , fromBigInt , fromInt , fromString + , fromStringUnsafe , fromUInt + , max , maxValue , mul , one + , sub + , toBigInt + , toInt + , toString + , toUInt , zero ) as X diff --git a/src/Contract/Numeric/NatRatio.purs b/src/Contract/Numeric/NatRatio.purs deleted file mode 100644 index a5d8fe747f..0000000000 --- a/src/Contract/Numeric/NatRatio.purs +++ /dev/null @@ -1,15 +0,0 @@ --- | A module for constructing well-defined ratios of natural numbers (with --- | non-zero denominator), potentially via cancellation of negative sign. -module Contract.Numeric.NatRatio (module NatRatio) where - -import Ctl.Internal.Types.NatRatio - ( NatRatio - , denominator - , denominatorAsNat - , fromBigInts - , fromNaturals - , fromRational - , numerator - , numeratorAsNat - , toRational - ) as NatRatio diff --git a/src/Contract/Numeric/Natural.purs b/src/Contract/Numeric/Natural.purs deleted file mode 100644 index 4d3f6aee09..0000000000 --- a/src/Contract/Numeric/Natural.purs +++ /dev/null @@ -1,15 +0,0 @@ --- | Arbitrary precision natural numbers (backed by `BigInt`). -module Contract.Numeric.Natural (module Natural) where - -import Ctl.Internal.Types.Natural - ( Natural - , binaryOnBigInt - , fromBigInt - , fromBigInt' - , fromInt - , fromInt' - , fromString - , minus - , toBigInt - , (^-) - ) as Natural diff --git a/src/Contract/Numeric/Rational.purs b/src/Contract/Numeric/Rational.purs index 21cc61ca00..f689ad39c0 100644 --- a/src/Contract/Numeric/Rational.purs +++ b/src/Contract/Numeric/Rational.purs @@ -7,7 +7,6 @@ import Ctl.Internal.Types.Rational ( class RationalComponent , Rational , denominator - , denominatorAsNat , numerator , recip , reduce diff --git a/src/Contract/Plutarch/Types.purs b/src/Contract/Plutarch/Types.purs index 68cd2fbf49..977d4e8b4c 100644 --- a/src/Contract/Plutarch/Types.purs +++ b/src/Contract/Plutarch/Types.purs @@ -58,4 +58,3 @@ denominator = unwrap >>> R.denominator recip :: PRational -> Maybe PRational recip = unwrap >>> R.recip >>> map wrap - diff --git a/src/Contract/PlutusData.purs b/src/Contract/PlutusData.purs index 1d5334ea04..3ba133791f 100644 --- a/src/Contract/PlutusData.purs +++ b/src/Contract/PlutusData.purs @@ -1,32 +1,19 @@ --- | This module that defines query functionality via Ogmios to get `PlutusData` --- | from `DatumHash` along with related `PlutusData` newtype wrappers such as --- | `Datum` and `Redeemer`. It also contains typeclasses like `FromData` and --- | `ToData` plus everything related to `PlutusSchema`. +-- | This module that defines query functionality to get `PlutusData` +-- | from `DatumHash`. module Contract.PlutusData ( getDatumByHash , getDatumsByHashes , getDatumsByHashesWithErrors - , module DataSchema - , module Datum - , module Hashing - , module IsData - , module Nat - , module PlutusData - , module Serialization - , module Deserialization - , module Redeemer - , module FromData - , module ToData - , module OutputDatum + , unitDatum + , unitRedeemer + , module X + , Datum + , Redeemer ) where import Prelude -import Contract.Monad (Contract) -import Control.Parallel (parTraverse) -import Ctl.Internal.Contract.Monad (getQueryHandle) -import Ctl.Internal.Deserialization.PlutusData (deserializeData) as Deserialization -import Ctl.Internal.FromData +import Cardano.FromData ( class FromData , class FromDataArgs , class FromDataArgsRL @@ -43,10 +30,8 @@ import Ctl.Internal.FromData , fromDataArgsRec , fromDataWithSchema , genericFromData - ) as FromData -import Ctl.Internal.Hashing (datumHash) as Hashing -import Ctl.Internal.IsData (class IsData) as IsData -import Ctl.Internal.Plutus.Types.DataSchema + ) as X +import Cardano.Plutus.DataSchema ( class AllUnique2 , class HasPlutusSchema , class PlutusSchemaToRowListI @@ -67,9 +52,8 @@ import Ctl.Internal.Plutus.Types.DataSchema , PCons , PNil , PSchema - ) as DataSchema -import Ctl.Internal.Serialization (serializeData) as Serialization -import Ctl.Internal.ToData + ) as X +import Cardano.ToData ( class ToData , class ToDataArgs , class ToDataArgsRL @@ -81,31 +65,33 @@ import Ctl.Internal.ToData , toDataArgsRec , toDataArgsRec' , toDataWithSchema - ) as ToData -import Ctl.Internal.TypeLevel.Nat (Nat, S, Z) as Nat -import Ctl.Internal.Types.Datum (DataHash, Datum) -import Ctl.Internal.Types.Datum (DataHash(DataHash), Datum(Datum), unitDatum) as Datum -import Ctl.Internal.Types.OutputDatum - ( OutputDatum(NoOutputDatum, OutputDatumHash, OutputDatum) - ) as OutputDatum -import Ctl.Internal.Types.PlutusData - ( PlutusData(Constr, Map, List, Integer, Bytes) - ) as PlutusData -import Ctl.Internal.Types.Redeemer - ( Redeemer(Redeemer) - , RedeemerHash(RedeemerHash) - , redeemerHash - , unitRedeemer - ) as Redeemer + ) as X +import Cardano.Types (DataHash) +import Cardano.Types + ( DataHash(DataHash) + , PlutusData(Constr, Map, List, Integer, Bytes) + ) as X +import Cardano.Types.OutputDatum + ( OutputDatum(OutputDatumHash, OutputDatum) + ) as X +import Cardano.Types.PlutusData (PlutusData) +import Cardano.Types.PlutusData as Datum +import Cardano.Types.RedeemerDatum (RedeemerDatum) +import Cardano.Types.RedeemerDatum (RedeemerDatum(RedeemerDatum)) as X +import Cardano.Types.RedeemerDatum as Redeemer +import Contract.Monad (Contract) +import Control.Parallel (parTraverse) +import Ctl.Internal.Contract.Monad (getQueryHandle) import Data.Either (Either(Left, Right), hush) import Data.Map (Map) import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing)) import Data.Tuple (Tuple(Tuple)) import Effect.Aff.Class (liftAff) +import Prim.TypeError (class Warn, Text) -- | Retrieve the full resolved datum associated to a given datum hash. -getDatumByHash :: DataHash -> Contract (Maybe Datum) +getDatumByHash :: DataHash -> Contract (Maybe PlutusData) getDatumByHash dataHash = do queryHandle <- getQueryHandle liftAff $ join <<< hush <$> queryHandle.getDatumByHash dataHash @@ -113,14 +99,14 @@ getDatumByHash dataHash = do -- | Retrieve full resolved datums associated with given datum hashes. -- | The resulting `Map` will only contain datums that have been successfully -- | resolved. -getDatumsByHashes :: Array DataHash -> Contract (Map DataHash Datum) +getDatumsByHashes :: Array DataHash -> Contract (Map DataHash PlutusData) getDatumsByHashes hashes = Map.mapMaybe hush <$> getDatumsByHashesWithErrors hashes -- | Retrieve full resolved datums associated with given datum hashes. -- | Errors are returned per datum. getDatumsByHashesWithErrors - :: Array DataHash -> Contract (Map DataHash (Either String Datum)) + :: Array DataHash -> Contract (Map DataHash (Either String PlutusData)) getDatumsByHashesWithErrors hashes = do queryHandle <- getQueryHandle liftAff $ Map.fromFoldable <$> flip parTraverse hashes @@ -128,3 +114,20 @@ getDatumsByHashesWithErrors hashes = do Right (Just datum) -> Right datum Right Nothing -> Left "Datum not found" Left err -> Left $ show err + +unitDatum + :: Warn (Text "Deprecated: unitDatum. use Cardano.Types.PlutusData.unit") + => PlutusData +unitDatum = Datum.unit + +unitRedeemer + :: Warn + (Text "Deprecated: unitRedeemer. use Cardano.Types.RedeemerDatum.unit") + => RedeemerDatum +unitRedeemer = Redeemer.unit + +-- | DEPRECATED. Use `Cardano.Types.PlutusData` +type Datum = PlutusData + +-- | DEPRECATED. Use `Contract.PlutusData.RedeemerDatum` +type Redeemer = RedeemerDatum diff --git a/src/Contract/Prim/Any.purs b/src/Contract/Prim/Any.purs deleted file mode 100644 index 098dfd710b..0000000000 --- a/src/Contract/Prim/Any.purs +++ /dev/null @@ -1,5 +0,0 @@ --- | For converting a subset of polymorphic types to that which will work with --- | `PlutusData`. -module Contract.Prim.Any (module Any) where - -import Ctl.Internal.Types.Any (Any) as Any diff --git a/src/Contract/Prim/ByteArray.purs b/src/Contract/Prim/ByteArray.purs index 51c34288ec..4301db35d4 100644 --- a/src/Contract/Prim/ByteArray.purs +++ b/src/Contract/Prim/ByteArray.purs @@ -3,9 +3,24 @@ module Contract.Prim.ByteArray ( module ByteArray , module CborBytes , module RawBytes + , rawBytesToByteArray + , rawBytesFromByteArray + , rawBytesToIntArray + , rawBytesFromIntArray + , rawBytesFromIntArrayUnsafe + , rawBytesFromAscii + , rawBytesToHex + , hexToRawBytes + , hexToRawBytesUnsafe ) where -import Ctl.Internal.Types.ByteArray +import Prelude + +import Cardano.Types.CborBytes (CborBytes(CborBytes)) as CborBytes +import Cardano.Types.RawBytes (RawBytes) +import Cardano.Types.RawBytes (RawBytes(RawBytes)) as RawBytes +import Data.ByteArray (ByteArray) +import Data.ByteArray ( ByteArray(ByteArray) , byteArrayFromAscii , byteArrayFromIntArray @@ -16,28 +31,33 @@ import Ctl.Internal.Types.ByteArray , hexToByteArray , hexToByteArrayUnsafe ) as ByteArray -import Ctl.Internal.Types.CborBytes - ( CborBytes(CborBytes) - , cborBytesFromAscii - , cborBytesFromByteArray - , cborBytesFromIntArray - , cborBytesFromIntArrayUnsafe - , cborBytesToByteArray - , cborBytesToHex - , cborBytesToIntArray - , hexToCborBytes - , hexToCborBytesUnsafe - , rawBytesAsCborBytes - ) as CborBytes -import Ctl.Internal.Types.RawBytes - ( RawBytes(RawBytes) - , hexToRawBytes - , hexToRawBytesUnsafe - , rawBytesFromAscii - , rawBytesFromByteArray - , rawBytesFromIntArray - , rawBytesFromIntArrayUnsafe - , rawBytesToByteArray - , rawBytesToHex - , rawBytesToIntArray - ) as RawBytes +import Data.ByteArray as BytesArray +import Data.Maybe (Maybe) +import Data.Newtype (unwrap, wrap) + +rawBytesToIntArray :: RawBytes -> Array Int +rawBytesToIntArray = BytesArray.byteArrayToIntArray <<< unwrap + +rawBytesFromIntArray :: Array Int -> Maybe RawBytes +rawBytesFromIntArray = map wrap <<< BytesArray.byteArrayFromIntArray + +rawBytesFromIntArrayUnsafe :: Array Int -> RawBytes +rawBytesFromIntArrayUnsafe = wrap <<< BytesArray.byteArrayFromIntArrayUnsafe + +rawBytesToHex :: RawBytes -> String +rawBytesToHex = BytesArray.byteArrayToHex <<< unwrap + +hexToRawBytes :: String -> Maybe RawBytes +hexToRawBytes = map wrap <<< BytesArray.hexToByteArray + +hexToRawBytesUnsafe :: String -> RawBytes +hexToRawBytesUnsafe = wrap <<< BytesArray.hexToByteArrayUnsafe + +rawBytesToByteArray :: RawBytes -> ByteArray +rawBytesToByteArray = unwrap + +rawBytesFromByteArray :: ByteArray -> RawBytes +rawBytesFromByteArray = wrap + +rawBytesFromAscii :: String -> Maybe RawBytes +rawBytesFromAscii = map wrap <<< BytesArray.byteArrayFromAscii diff --git a/src/Contract/RewardAddress.purs b/src/Contract/RewardAddress.purs deleted file mode 100644 index 316654b09b..0000000000 --- a/src/Contract/RewardAddress.purs +++ /dev/null @@ -1,11 +0,0 @@ -module Contract.RewardAddress (module X) where - -import Ctl.Internal.Types.RewardAddress - ( RewardAddress - , rewardAddressFromBech32 - , rewardAddressFromBytes - , rewardAddressToBech32 - , rewardAddressToBytes - , stakePubKeyHashRewardAddress - , stakeValidatorHashRewardAddress - ) as X diff --git a/src/Contract/ScriptLookups.purs b/src/Contract/ScriptLookups.purs index 3e489fba0a..08a7ff7ccc 100644 --- a/src/Contract/ScriptLookups.purs +++ b/src/Contract/ScriptLookups.purs @@ -2,18 +2,13 @@ -- | transaction. module Contract.ScriptLookups (module X) where -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx(UnbalancedTx)) as X import Ctl.Internal.Types.ScriptLookups ( ScriptLookups(ScriptLookups) , datum - , mintingPolicy - , mintingPolicyM + , nativeMintingPolicy , ownPaymentPubKeyHash - , ownPaymentPubKeyHashM , ownStakePubKeyHash - , ownStakePubKeyHashM + , plutusMintingPolicy , unspentOutputs - , unspentOutputsM , validator - , validatorM ) as X diff --git a/src/Contract/Scripts.purs b/src/Contract/Scripts.purs index 6a19018d8e..3bc346e6d1 100644 --- a/src/Contract/Scripts.purs +++ b/src/Contract/Scripts.purs @@ -4,19 +4,20 @@ module Contract.Scripts ( getScriptByHash , getScriptsByHashes - , module ExportScripts - , module Hash - , module NativeScript - , module TypesScripts , module X + , Validator + , ValidatorHash + , validatorHash ) where import Prelude -import Contract.Monad (Contract) -import Control.Parallel (parTraverse) -import Ctl.Internal.ApplyArgs (ApplyArgsError(ApplyArgsError), applyArgs) as X -import Ctl.Internal.Cardano.Types.NativeScript +import Cardano.Types + ( PlutusScript(PlutusScript) + , ScriptHash + ) as X +import Cardano.Types (ScriptHash) +import Cardano.Types.NativeScript ( NativeScript ( ScriptPubkey , ScriptAll @@ -25,35 +26,21 @@ import Ctl.Internal.Cardano.Types.NativeScript , TimelockStart , TimelockExpiry ) - ) as NativeScript -import Ctl.Internal.Cardano.Types.ScriptRef (ScriptRef) + ) as X +import Cardano.Types.PlutusScript (PlutusScript) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.ScriptRef (ScriptRef) +import Contract.Monad (Contract) +import Control.Parallel (parTraverse) import Ctl.Internal.Contract.Monad (getQueryHandle) -import Ctl.Internal.NativeScripts (NativeScriptHash(NativeScriptHash)) as X -import Ctl.Internal.Scripts - ( mintingPolicyHash - , nativeScriptStakeValidatorHash - , plutusScriptStakeValidatorHash - , validatorHash - ) as ExportScripts -import Ctl.Internal.Serialization.Hash (ScriptHash) -import Ctl.Internal.Serialization.Hash (ScriptHash) as Hash import Ctl.Internal.Service.Error (ClientError) -import Ctl.Internal.Types.Scripts - ( MintingPolicy(PlutusMintingPolicy, NativeMintingPolicy) - , MintingPolicyHash(MintingPolicyHash) - , NativeScriptStakeValidator(NativeScriptStakeValidator) - , PlutusScript(PlutusScript) - , PlutusScriptStakeValidator(PlutusScriptStakeValidator) - , StakeValidatorHash(StakeValidatorHash) - , Validator(Validator) - , ValidatorHash(ValidatorHash) - ) as TypesScripts import Data.Either (Either) import Data.Map (Map) import Data.Map as Map import Data.Maybe (Maybe) import Data.Tuple (Tuple(Tuple)) import Effect.Aff.Class (liftAff) +import Prim.TypeError (class Warn, Text) -- | Retrieve a `ScriptRef` given the hash getScriptByHash :: ScriptHash -> Contract (Either ClientError (Maybe ScriptRef)) @@ -69,3 +56,16 @@ getScriptsByHashes hashes = do queryHandle <- getQueryHandle liftAff $ Map.fromFoldable <$> flip parTraverse hashes \sh -> queryHandle.getScriptByHash sh <#> Tuple sh + +-- | Deprecated. Use `Cardano.Types.PlutusScript` +type Validator = PlutusScript + +-- | Deprecated. Use `Cardano.Types.ScriptHash` +type ValidatorHash = ScriptHash + +validatorHash + :: Warn + (Text "Deprecated: validatorHash. Use Cardano.Types.PlutusScript.hash") + => PlutusScript + -> ScriptHash +validatorHash = PlutusScript.hash diff --git a/src/Contract/Staking.purs b/src/Contract/Staking.purs index 0cef956ff1..067a75525e 100644 --- a/src/Contract/Staking.purs +++ b/src/Contract/Staking.purs @@ -2,21 +2,27 @@ module Contract.Staking ( getPoolIds , getPubKeyHashDelegationsAndRewards , getValidatorHashDelegationsAndRewards + , getStakeCredentialDelegationsAndRewards , module X ) where import Prelude +import Cardano.Types + ( Credential(PubKeyHashCredential, ScriptHashCredential) + , Ed25519KeyHash + , PoolPubKeyHash + , ScriptHash + , StakeCredential(StakeCredential) + ) import Contract.Monad (Contract) import Control.Monad.Reader (asks) -import Ctl.Internal.Cardano.Types.Transaction (PoolPubKeyHash) import Ctl.Internal.Contract.Monad (getQueryHandle) -import Ctl.Internal.QueryM.Pools (DelegationsAndRewards) -import Ctl.Internal.QueryM.Pools (DelegationsAndRewards) as X -import Ctl.Internal.Types.PubKeyHash (StakePubKeyHash) -import Ctl.Internal.Types.Scripts (StakeValidatorHash) +import Ctl.Internal.Types.DelegationsAndRewards (DelegationsAndRewards) +import Ctl.Internal.Types.DelegationsAndRewards (DelegationsAndRewards) as X import Data.Either (either) import Data.Maybe (Maybe) +import Data.Newtype (wrap) import Effect.Aff.Class (liftAff) import Effect.Class (liftEffect) import Effect.Exception (throw) @@ -28,18 +34,28 @@ getPoolIds = do queryHandle.getPoolIds >>= either (liftEffect <<< throw <<< show) pure +getStakeCredentialDelegationsAndRewards + :: StakeCredential + -> Contract (Maybe DelegationsAndRewards) +getStakeCredentialDelegationsAndRewards = case _ of + StakeCredential (PubKeyHashCredential pkh) -> + getPubKeyHashDelegationsAndRewards pkh + StakeCredential (ScriptHashCredential sh) -> + getValidatorHashDelegationsAndRewards sh + getPubKeyHashDelegationsAndRewards - :: StakePubKeyHash + :: Ed25519KeyHash -> Contract (Maybe DelegationsAndRewards) getPubKeyHashDelegationsAndRewards stakePubKeyHash = do queryHandle <- getQueryHandle networkId <- asks _.networkId liftAff do - queryHandle.getPubKeyHashDelegationsAndRewards networkId stakePubKeyHash + queryHandle.getPubKeyHashDelegationsAndRewards networkId + (wrap stakePubKeyHash) >>= either (liftEffect <<< throw <<< show) pure getValidatorHashDelegationsAndRewards - :: StakeValidatorHash + :: ScriptHash -> Contract (Maybe DelegationsAndRewards) getValidatorHashDelegationsAndRewards stakeValidatorHash = do queryHandle <- getQueryHandle diff --git a/src/Contract/Test/Assert.purs b/src/Contract/Test/Assert.purs index 1577e0e1e9..2531a5ad86 100644 --- a/src/Contract/Test/Assert.purs +++ b/src/Contract/Test/Assert.purs @@ -65,45 +65,46 @@ module Contract.Test.Assert import Prelude -import Contract.Address (Address) -import Contract.Monad (Contract) -import Contract.PlutusData (OutputDatum) -import Contract.Prelude (Effect) -import Contract.Transaction - ( ScriptRef +import Cardano.FromMetadata (fromMetadata) +import Cardano.Serialization.Lib (toBytes) +import Cardano.Types + ( Address + , Asset(Asset) + , AssetName + , ExUnits(ExUnits) + , OutputDatum + , ScriptHash + , ScriptRef + , Transaction , TransactionHash - , TransactionOutputWithRefScript - , getTxMetadata + , TransactionOutput + , Value + , _amount + , _datum + , _redeemers + , _scriptRef + , _witnessSet ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Value as Value +import Contract.Monad (Contract) +import Contract.Prelude (Effect) +import Contract.Transaction (getTxAuxiliaryData) import Contract.Utxos (utxosAt) -import Contract.Value (CurrencySymbol, TokenName, Value, valueOf, valueToCoin') import Contract.Wallet (getWalletBalance, getWalletUtxos) import Control.Monad.Error.Class (liftEither, throwError) import Control.Monad.Error.Class as E import Control.Monad.Reader (ReaderT, ask, local, mapReaderT, runReaderT) import Control.Monad.Trans.Class (lift) -import Ctl.Internal.Cardano.Types.Transaction - ( ExUnits - , Transaction - , _redeemers - , _witnessSet - ) import Ctl.Internal.Contract.Monad (ContractEnv) -import Ctl.Internal.Metadata.FromMetadata (fromMetadata) import Ctl.Internal.Metadata.MetadataType (class MetadataType, metadataLabel) -import Ctl.Internal.Plutus.Types.Transaction - ( _amount - , _datum - , _output - , _scriptRef - ) -import Ctl.Internal.Types.ByteArray (byteArrayToHex) import Data.Array (foldr) import Data.Array (fromFoldable, length, mapWithIndex, partition) as Array +import Data.ByteArray (byteArrayToHex) import Data.Either (Either, either, hush) -import Data.Foldable (fold, foldMap, null, sum) +import Data.Foldable (fold, foldMap, null) import Data.Generic.Rep (class Generic) -import Data.Lens (non, to, traversed, view, (%~), (^.), (^..)) +import Data.Lens (to, view, (%~), (^.)) import Data.Lens.Record (prop) import Data.List (List(Cons, Nil)) import Data.Map (empty, filterKeys, lookup, values) as Map @@ -118,6 +119,7 @@ import Effect.Exception (Error, error, message, throw, try) import Effect.Ref (Ref) import Effect.Ref as Ref import JS.BigInt (BigInt) +import Partial.Unsafe (unsafePartial) import Type.Proxy (Proxy(Proxy)) -- | Monad allowing for accumulation of assertion failures. @@ -132,13 +134,13 @@ data ContractAssertionFailure = CouldNotGetTxByHash TransactionHash | CouldNotParseMetadata Label | TransactionHasNoMetadata TransactionHash (Maybe Label) - | UnexpectedDatumInOutput (Labeled TransactionOutputWithRefScript) - (ExpectedActual OutputDatum) + | UnexpectedDatumInOutput (Labeled TransactionOutput) + (ExpectedActual (Maybe OutputDatum)) | UnexpectedLovelaceDelta (Maybe (Labeled Address)) (ExpectedActual BigInt) | UnexpectedMetadataValue Label (ExpectedActual String) - | UnexpectedRefScriptInOutput (Labeled TransactionOutputWithRefScript) + | UnexpectedRefScriptInOutput (Labeled TransactionOutput) (ExpectedActual (Maybe ScriptRef)) - | UnexpectedTokenDelta (Maybe (Labeled Address)) TokenName + | UnexpectedTokenDelta (Maybe (Labeled Address)) AssetName (ExpectedActual BigInt) | FailedToGetExpectedValue String | MaxExUnitsExceeded (ExpectedActual ExUnits) @@ -229,13 +231,21 @@ printContractAssertionFailure = case _ of "Error while trying to get expected value: " <> err MaxExUnitsExceeded expectedActual -> - "ExUnits limit exceeded: " <> printExpectedActual expectedActual + "ExUnits limit exceeded: " <> printExpectedActualWith printExUnits + expectedActual CustomFailure msg -> msg SkippedTest msg -> msg showTxHash :: TransactionHash -> String -showTxHash = byteArrayToHex <<< unwrap +showTxHash = byteArrayToHex <<< toBytes <<< unwrap + +printExUnits :: ExUnits -> String +printExUnits (ExUnits { mem, steps }) = + "{ mem: " <> BigNum.toString mem + <> ", steps: " + <> BigNum.toString steps + <> " }" type Label = String @@ -273,8 +283,15 @@ instance Show a => Show (ExpectedActual a) where derive instance Functor ExpectedActual printExpectedActual :: forall (a :: Type). Show a => ExpectedActual a -> String -printExpectedActual (ExpectedActual expected actual) = - " Expected: " <> show expected <> ", Actual: " <> show actual <> " " +printExpectedActual = printExpectedActualWith show + +printExpectedActualWith + :: forall (a :: Type) + . (a -> String) + -> ExpectedActual a + -> String +printExpectedActualWith format (ExpectedActual expected actual) = + " Expected: " <> format expected <> ", Actual: " <> format actual <> " " -------------------------------------------------------------------------------- -- Different types of assertions, Assertion composition, Basic functions @@ -402,7 +419,7 @@ assertNewUtxosAtAddress :: forall (a :: Type) . Labeled Address -> TransactionHash - -> (Array TransactionOutputWithRefScript -> ContractAssertion a) + -> (Array TransactionOutput -> ContractAssertion a) -> ContractAssertion a assertNewUtxosAtAddress addr txHash check = lift (utxosAt $ unlabel addr) >>= \utxos -> @@ -413,7 +430,7 @@ assertNewUtxosAtAddress addr txHash check = assertNewUtxosInWallet :: forall (a :: Type) . TransactionHash - -> (Array TransactionOutputWithRefScript -> ContractAssertion a) + -> (Array TransactionOutput -> ContractAssertion a) -> ContractAssertion a assertNewUtxosInWallet txHash check = lift getWalletUtxos >>= fromMaybe Map.empty >>> \utxos -> @@ -432,18 +449,21 @@ checkExUnitsNotExceed . ExUnits -> ContractCheck a checkExUnitsNotExceed maxExUnits contract = do - (ref :: Ref ExUnits) <- liftEffect $ Ref.new { mem: zero, steps: zero } + (ref :: Ref ExUnits) <- liftEffect $ Ref.new $ ExUnits + { mem: BigNum.zero, steps: BigNum.zero } let submitHook :: Transaction -> Effect Unit submitHook tx = do let - (newExUnits :: ExUnits) = sum $ tx ^.. - _witnessSet - <<< _redeemers - <<< non [] - <<< traversed - <<< to (unwrap >>> _.exUnits) - Ref.modify_ (add newExUnits) ref + (newExUnits :: ExUnits) = + unsafePartial + $ foldr append (ExUnits { mem: BigNum.zero, steps: BigNum.zero }) + $ tx + ^. + _witnessSet + <<< _redeemers + <<< to (map (unwrap >>> _.exUnits)) + Ref.modify_ (unsafePartial $ append newExUnits) ref setSubmitHook :: ContractEnv -> ContractEnv setSubmitHook = @@ -459,7 +479,9 @@ checkExUnitsNotExceed maxExUnits contract = do finalize = do exUnits <- liftEffect $ Ref.read ref assertContract (MaxExUnitsExceeded (ExpectedActual maxExUnits exUnits)) - (maxExUnits.mem >= exUnits.mem && maxExUnits.steps >= exUnits.steps) + ( (unwrap maxExUnits).mem >= (unwrap exUnits).mem && + (unwrap maxExUnits).steps >= (unwrap exUnits).steps + ) pure (mapReaderT (local setSubmitHook) contract /\ finalize) @@ -505,7 +527,8 @@ checkLovelaceDeltaAtAddress addr getExpected comp contract = do \expected -> do let actual :: BigInt - actual = valueToCoin' valueAfter - valueToCoin' valueBefore + actual = BigNum.toBigInt (unwrap (Value.getCoin valueAfter)) - + BigNum.toBigInt (unwrap $ Value.getCoin valueBefore) unexpectedLovelaceDelta :: ContractAssertionFailure unexpectedLovelaceDelta = @@ -556,7 +579,7 @@ checkLossAtAddress' addr minLoss = checkTokenDeltaAtAddress :: forall (a :: Type) . Labeled Address - -> (CurrencySymbol /\ TokenName) + -> (ScriptHash /\ AssetName) -> (Maybe a -> Contract BigInt) -> (BigInt -> BigInt -> Boolean) -> ContractCheck a @@ -570,7 +593,9 @@ checkTokenDeltaAtAddress addr (cs /\ tn) getExpected comp contract = \expected -> do let actual :: BigInt - actual = valueOf valueAfter cs tn - valueOf valueBefore cs tn + actual = + (BigNum.toBigInt $ Value.valueOf (Asset cs tn) valueAfter) - + (BigNum.toBigInt $ Value.valueOf (Asset cs tn) valueBefore) unexpectedTokenDelta :: ContractAssertionFailure unexpectedTokenDelta = @@ -583,7 +608,7 @@ checkTokenDeltaAtAddress addr (cs /\ tn) getExpected comp contract = checkTokenGainAtAddress :: forall (a :: Type) . Labeled Address - -> (CurrencySymbol /\ TokenName) + -> (ScriptHash /\ AssetName) -> (Maybe a -> Contract BigInt) -> ContractCheck a checkTokenGainAtAddress addr token getMinGain = @@ -594,7 +619,7 @@ checkTokenGainAtAddress addr token getMinGain = checkTokenGainAtAddress' :: forall (a :: Type) . Labeled Address - -> (CurrencySymbol /\ TokenName /\ BigInt) + -> (ScriptHash /\ AssetName /\ BigInt) -> ContractCheck a checkTokenGainAtAddress' addr (cs /\ tn /\ minGain) = checkTokenGainAtAddress addr (cs /\ tn) (const $ pure minGain) @@ -604,7 +629,7 @@ checkTokenGainAtAddress' addr (cs /\ tn /\ minGain) = checkTokenLossAtAddress :: forall (a :: Type) . Labeled Address - -> (CurrencySymbol /\ TokenName) + -> (ScriptHash /\ AssetName) -> (Maybe a -> Contract BigInt) -> ContractCheck a checkTokenLossAtAddress addr token getMinLoss = @@ -615,7 +640,7 @@ checkTokenLossAtAddress addr token getMinLoss = checkTokenLossAtAddress' :: forall (a :: Type) . Labeled Address - -> (CurrencySymbol /\ TokenName /\ BigInt) + -> (ScriptHash /\ AssetName /\ BigInt) -> ContractCheck a checkTokenLossAtAddress' addr (cs /\ tn /\ minLoss) = checkTokenLossAtAddress addr (cs /\ tn) (const $ pure minLoss) @@ -629,11 +654,11 @@ checkValueDeltaInWallet . (Maybe a -> Value -> Value -> ContractAssertion Unit) -> ContractCheck a checkValueDeltaInWallet check contract = do - valueBefore <- lift $ getWalletBalance <#> fold + valueBefore <- lift $ unsafePartial $ getWalletBalance <#> fold ref <- liftEffect $ Ref.new Nothing let finalize = do - valueAfter <- lift $ getWalletBalance <#> fold + valueAfter <- unsafePartial $ lift $ getWalletBalance <#> fold liftEffect (Ref.read ref) >>= \res -> check res valueBefore valueAfter run = do res <- contract @@ -656,7 +681,8 @@ checkLovelaceDeltaInWallet getExpected comp contract = do \expected -> do let actual :: BigInt - actual = valueToCoin' valueAfter - valueToCoin' valueBefore + actual = BigNum.toBigInt (unwrap (Value.getCoin valueAfter)) - + BigNum.toBigInt (unwrap (Value.getCoin valueBefore)) unexpectedLovelaceDelta :: ContractAssertionFailure unexpectedLovelaceDelta = @@ -702,7 +728,7 @@ checkLossInWallet' minLoss = checkTokenDeltaInWallet :: forall (a :: Type) - . (CurrencySymbol /\ TokenName) + . (ScriptHash /\ AssetName) -> (Maybe a -> Contract BigInt) -> (BigInt -> BigInt -> Boolean) -> ContractCheck a @@ -716,7 +742,8 @@ checkTokenDeltaInWallet (cs /\ tn) getExpected comp contract = \expected -> do let actual :: BigInt - actual = valueOf valueAfter cs tn - valueOf valueBefore cs tn + actual = BigNum.toBigInt (Value.valueOf (Asset cs tn) valueAfter) - + BigNum.toBigInt (Value.valueOf (Asset cs tn) valueBefore) unexpectedTokenDelta :: ContractAssertionFailure unexpectedTokenDelta = @@ -728,7 +755,7 @@ checkTokenDeltaInWallet (cs /\ tn) getExpected comp contract = -- | by calling the contract. checkTokenGainInWallet :: forall (a :: Type) - . (CurrencySymbol /\ TokenName) + . (ScriptHash /\ AssetName) -> (Maybe a -> Contract BigInt) -> ContractCheck a checkTokenGainInWallet token getMinGain = @@ -738,7 +765,7 @@ checkTokenGainInWallet token getMinGain = -- | by calling the contract. checkTokenGainInWallet' :: forall (a :: Type) - . (CurrencySymbol /\ TokenName /\ BigInt) + . (ScriptHash /\ AssetName /\ BigInt) -> ContractCheck a checkTokenGainInWallet' (cs /\ tn /\ minGain) = checkTokenGainInWallet (cs /\ tn) (const $ pure minGain) @@ -747,7 +774,7 @@ checkTokenGainInWallet' (cs /\ tn /\ minGain) = -- | by calling the contract. checkTokenLossInWallet :: forall (a :: Type) - . (CurrencySymbol /\ TokenName) + . (ScriptHash /\ AssetName) -> (Maybe a -> Contract BigInt) -> ContractCheck a checkTokenLossInWallet token getMinLoss = @@ -757,21 +784,21 @@ checkTokenLossInWallet token getMinLoss = -- | by calling the contract. checkTokenLossInWallet' :: forall (a :: Type) - . (CurrencySymbol /\ TokenName /\ BigInt) + . (ScriptHash /\ AssetName /\ BigInt) -> ContractCheck a checkTokenLossInWallet' (cs /\ tn /\ minLoss) = checkTokenLossInWallet (cs /\ tn) (const $ pure minLoss) --------------------- Datums and scripts ---------------------------------------- --- | Requires that the transaction output contains the specified datum or --- | datum hash. +-- | Requires that the transaction output contains the specified datum, +-- | datum hash or does not contain anything. assertOutputHasDatum - :: OutputDatum - -> Labeled TransactionOutputWithRefScript + :: Maybe OutputDatum + -> Labeled TransactionOutput -> ContractAssertion Unit assertOutputHasDatum expectedDatum txOutput = do - let actualDatum = unlabel txOutput ^. _output <<< _datum + let actualDatum = unlabel txOutput ^. _datum assertContractExpectedActual (UnexpectedDatumInOutput txOutput) expectedDatum actualDatum @@ -780,7 +807,7 @@ assertOutputHasDatum expectedDatum txOutput = do -- | script. assertOutputHasRefScript :: ScriptRef - -> Labeled TransactionOutputWithRefScript + -> Labeled TransactionOutput -> ContractAssertion Unit assertOutputHasRefScript expectedRefScript txOutput = do let actualRefScript = unlabel txOutput ^. _scriptRef @@ -802,11 +829,14 @@ assertTxHasMetadata assertTxHasMetadata mdLabel txHash expectedMetadata = do generalMetadata <- assertContractMaybe (TransactionHasNoMetadata txHash Nothing) - =<< lift (hush <$> getTxMetadata txHash) + =<< lift + ( map ((=<<) (_.metadata <<< unwrap)) $ hush <$> getTxAuxiliaryData + txHash + ) rawMetadata <- assertContractMaybe (TransactionHasNoMetadata txHash (Just mdLabel)) - ( Map.lookup (metadataLabel (Proxy :: Proxy metadata)) + ( Map.lookup (unwrap $ metadataLabel (Proxy :: Proxy metadata)) (unwrap generalMetadata) ) @@ -823,7 +853,7 @@ assertTxHasMetadata mdLabel txHash expectedMetadata = do getValueAtAddress :: Labeled Address -> ContractAssertion Value -getValueAtAddress = map (foldMap (view (_output <<< _amount))) <<< lift +getValueAtAddress = map (unsafePartial $ foldMap (view (_amount))) <<< lift <<< utxosAt <<< unlabel diff --git a/src/Contract/Test/Blockfrost.purs b/src/Contract/Test/Blockfrost.purs index b446c56754..ca11d7985e 100644 --- a/src/Contract/Test/Blockfrost.purs +++ b/src/Contract/Test/Blockfrost.purs @@ -102,6 +102,7 @@ runContractTestsWithBlockfrost { backendParams = BlockfrostBackendParams backendParams mbCtlBackendParams , walletSpec = Just $ UseKeys privateKeySources.payment privateKeySources.stake + Nothing } -- | Reads environment variables containing Blockfrost test suite configuration diff --git a/src/Contract/Test/Cip30Mock.purs b/src/Contract/Test/Cip30Mock.purs index 33883c3847..d0fd45f0d3 100644 --- a/src/Contract/Test/Cip30Mock.purs +++ b/src/Contract/Test/Cip30Mock.purs @@ -4,6 +4,5 @@ module Contract.Test.Cip30Mock ) where import Ctl.Internal.Wallet.Cip30Mock - ( WalletMock(MockFlint, MockGero, MockNami, MockLode) - , withCip30Mock + ( withCip30Mock ) as X diff --git a/src/Contract/Test/Mote.purs b/src/Contract/Test/Mote.purs index 0acc810d10..b49e71b5dd 100644 --- a/src/Contract/Test/Mote.purs +++ b/src/Contract/Test/Mote.purs @@ -1,6 +1,6 @@ module Contract.Test.Mote (module X) where -import Ctl.Internal.Test.TestPlanM +import Mote.TestPlanM ( TestPlanM , interpret , interpretWithConfig diff --git a/src/Contract/Test/Plutip.purs b/src/Contract/Test/Plutip.purs deleted file mode 100644 index 47df5ee5c0..0000000000 --- a/src/Contract/Test/Plutip.purs +++ /dev/null @@ -1,75 +0,0 @@ --- | This module contains everything needed for `Contract` testing in Plutip --- | environment. -module Contract.Test.Plutip - ( testPlutipContracts - , defaultPlutipConfig - , module X - , PlutipTest - ) where - -import Prelude - -import Contract.Monad (runContractInEnv) as X -import Contract.Wallet (withKeyWallet) as X -import Ctl.Internal.Contract.Hooks (emptyHooks) -import Ctl.Internal.Plutip.Server (runPlutipContract, withPlutipContractEnv) as X -import Ctl.Internal.Plutip.Server (testPlutipContracts) as Server -import Ctl.Internal.Plutip.Types (PlutipConfig) -import Ctl.Internal.Plutip.Types (PlutipConfig) as X -import Ctl.Internal.Test.ContractTest (ContractTest) -import Ctl.Internal.Test.ContractTest (ContractTest) as Server -import Ctl.Internal.Test.ContractTest (noWallet, withWallets) as X -import Ctl.Internal.Test.UtxoDistribution - ( class UtxoDistribution - , InitialUTxODistribution - , InitialUTxOs - , InitialUTxOsWithStakeKey(InitialUTxOsWithStakeKey) - , UtxoAmount - , withStakeKey - ) as X -import Data.Log.Level (LogLevel(Trace)) -import Data.Maybe (Maybe(Nothing)) -import Data.Time.Duration (Seconds(Seconds)) -import Data.UInt as UInt -import Effect.Aff (Aff) -import Mote (MoteT) - --- | Run `Contract`s in tests in a single Plutip instance. -testPlutipContracts - :: PlutipConfig - -> MoteT Aff Server.ContractTest Aff Unit - -> MoteT Aff (Aff Unit) Aff Unit -testPlutipContracts = Server.testPlutipContracts - --- | Type synonym for backwards compatibility. -type PlutipTest = ContractTest - --- | A default value for `PlutipConfig` type. -defaultPlutipConfig :: PlutipConfig -defaultPlutipConfig = - { host: "127.0.0.1" - , port: UInt.fromInt 8082 - , logLevel: Trace - -- Server configs are used to deploy the corresponding services. - , ogmiosConfig: - { port: UInt.fromInt 1338 - , host: "127.0.0.1" - , secure: false - , path: Nothing - } - , kupoConfig: - { port: UInt.fromInt 1443 - , host: "127.0.0.1" - , secure: false - , path: Nothing - } - , suppressLogs: true - , customLogger: Nothing - , hooks: emptyHooks - , clusterConfig: - { slotLength: Seconds 0.1 - , epochSize: Nothing - , maxTxSize: Nothing - , raiseExUnitsToMax: false - } - } diff --git a/src/Contract/Test/Testnet.purs b/src/Contract/Test/Testnet.purs new file mode 100644 index 0000000000..ade0ca6409 --- /dev/null +++ b/src/Contract/Test/Testnet.purs @@ -0,0 +1,71 @@ +module Contract.Test.Testnet + ( defaultTestnetConfig + , module X + ) where + +import Contract.Monad (runContractInEnv) as X +import Contract.Wallet (withKeyWallet) as X +import Ctl.Internal.Contract.Hooks (emptyHooks) +import Ctl.Internal.Test.ContractTest + ( ContractTest + , ContractTestPlan(ContractTestPlan) + , noWallet + , sameWallets + , withWallets + ) as X +import Ctl.Internal.Test.UtxoDistribution + ( class UtxoDistribution + , InitialUTxODistribution + , InitialUTxOs + , InitialUTxOsWithStakeKey(InitialUTxOsWithStakeKey) + , UtxoAmount + , withStakeKey + ) as X +import Ctl.Internal.Testnet.Contract + ( runTestnetContract + , runTestnetTestPlan + , testTestnetContracts + ) as X +import Ctl.Internal.Testnet.Types + ( Era + ( Byron + , Shelley + , Allegra + , Mary + , Alonzo + , Babbage + , Conway + ) + , TestnetConfig + ) as X +import Ctl.Internal.Testnet.Types (Era(Conway), TestnetConfig) +import Data.Log.Level (LogLevel(Trace)) +import Data.Maybe (Maybe(Nothing)) +import Data.Time.Duration (Seconds(Seconds)) +import Data.UInt (fromInt) as UInt + +defaultTestnetConfig :: TestnetConfig +defaultTestnetConfig = + { logLevel: Trace + , ogmiosConfig: + { port: UInt.fromInt 1338 + , host: "127.0.0.1" + , secure: false + , path: Nothing + } + , kupoConfig: + { port: UInt.fromInt 1443 + , host: "127.0.0.1" + , secure: false + , path: Nothing + } + , customLogger: Nothing + , suppressLogs: true + , hooks: emptyHooks + , clusterConfig: + { testnetMagic: 2 + , era: Conway + , slotLength: Seconds 0.1 + , epochSize: Nothing + } + } diff --git a/src/Contract/Test/Utils.purs b/src/Contract/Test/Utils.purs index 8ad509696d..d02298aa18 100644 --- a/src/Contract/Test/Utils.purs +++ b/src/Contract/Test/Utils.purs @@ -18,7 +18,7 @@ import Node.Process as Process foreign import exitCode :: Int -> Effect Unit -- | Attaches a custom handler on SIGINT to kill the fiber. --- | see https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/doc/plutip-testing.md#note-on-sigint +-- | see https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/doc/cardano-testnet-testing.md#note-on-sigint interruptOnSignal :: forall a. Signal -> Fiber a -> Effect Unit interruptOnSignal signal fiber = Process.onSignal signal do launchAff_ do diff --git a/src/Contract/TextEnvelope.purs b/src/Contract/TextEnvelope.purs index 6ba9e01fcb..2411a2856b 100644 --- a/src/Contract/TextEnvelope.purs +++ b/src/Contract/TextEnvelope.purs @@ -7,11 +7,11 @@ import Ctl.Internal.Cardano.TextEnvelope , TextEnvelopeType ( PlutusScriptV1 , PlutusScriptV2 + , PlutusScriptV3 , PaymentSigningKeyShelleyed25519 , StakeSigningKeyShelleyed25519 , Other ) , decodeTextEnvelope - , plutusScriptV1FromEnvelope - , plutusScriptV2FromEnvelope + , plutusScriptFromEnvelope ) as X diff --git a/src/Contract/Time.purs b/src/Contract/Time.purs index 0fc4016508..afa40d744c 100644 --- a/src/Contract/Time.purs +++ b/src/Contract/Time.purs @@ -10,16 +10,18 @@ module Contract.Time , module ExportOgmios , module ExportSystemStart , module Interval - , module SerializationAddress + , module X ) where import Prelude +import Cardano.Types (BigNum, Epoch(Epoch), Slot) +import Cardano.Types (Slot(Slot)) as X +import Cardano.Types.BigNum as BigNum import Contract.Chain (getTip) as Chain import Contract.Log (logInfo') import Contract.Monad (Contract, liftContractM, liftedE) import Control.Monad.Reader.Class (asks) -import Ctl.Internal.Cardano.Types.Transaction (Epoch(Epoch)) import Ctl.Internal.Contract (getChainTip) import Ctl.Internal.Contract.Monad (getQueryHandle) import Ctl.Internal.Helpers (liftM) @@ -28,8 +30,6 @@ import Ctl.Internal.QueryM.Ogmios ( CurrentEpoch(CurrentEpoch) , OgmiosEraSummaries(OgmiosEraSummaries) ) as ExportOgmios -import Ctl.Internal.Serialization.Address (BlockId(BlockId), Slot(Slot)) as SerializationAddress -import Ctl.Internal.Serialization.Address (Slot) import Ctl.Internal.Types.Chain ( BlockHeaderHash(BlockHeaderHash) , ChainTip(ChainTip) @@ -44,10 +44,7 @@ import Ctl.Internal.Types.EraSummaries , SafeZone(SafeZone) , SlotLength(SlotLength) ) as ExportEraSummaries -import Ctl.Internal.Types.EraSummaries - ( EraSummaries - , EraSummary - ) +import Ctl.Internal.Types.EraSummaries (EraSummaries, EraSummary) import Ctl.Internal.Types.Interval ( AbsTime(AbsTime) , Closure @@ -77,7 +74,6 @@ import Ctl.Internal.Types.Interval , after , always , before - , beginningOfTime , contains , findSlotEraSummary , findTimeEraSummary @@ -178,10 +174,10 @@ normalizeTimeInterval = case _ of getCurrentEpoch :: Contract Epoch getCurrentEpoch = do queryHandle <- getQueryHandle - CurrentEpoch bigInt <- liftAff $ queryHandle.getCurrentEpoch + CurrentEpoch bigNum <- liftAff $ queryHandle.getCurrentEpoch map Epoch $ liftM (error "Unable to convert CurrentEpoch") $ UInt.fromString - $ BigInt.toString (bigInt :: BigInt.BigInt) + $ BigNum.toString (bigNum :: BigNum) -- | Get `EraSummaries` as used for Slot arithemetic. -- | diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index ecbb798923..b98d9d144a 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -1,55 +1,75 @@ -- | A module that defines the different transaction data types, balancing -- | functionality, transaction fees, signing and submission. module Contract.Transaction - ( BalancedSignedTransaction(BalancedSignedTransaction) - , balanceTx + ( balanceTx , balanceTxE - , balanceTxWithConstraints - , balanceTxWithConstraintsE , balanceTxs - , balanceTxsWithConstraints - , calculateMinFee , createAdditionalUtxos - , getTxFinalFee - , getTxMetadata + , getTxAuxiliaryData , module BalanceTxError - , module FinalizedTransaction - , module NativeScript - , module OutputDatum - , module PTransaction - , module PTransactionUnspentOutput - , module ScriptRef - , module Scripts - , module Transaction , module X - , signTransaction , submit , submitE , submitTxFromConstraints - , submitTxFromConstraintsReturningFee , withBalancedTx - , withBalancedTxWithConstraints , withBalancedTxs - , withBalancedTxsWithConstraints + , lookupTxHash + , mkPoolPubKeyHash + , hashTransaction + , buildTx + , submitTxFromBuildPlan ) where import Prelude -import Aeson (class EncodeAeson) -import Contract.ClientError (ClientError) -import Contract.Metadata (GeneralTransactionMetadata) -import Contract.Monad - ( Contract - , liftContractM - , runContractInEnv +import Cardano.Transaction.Builder + ( TransactionBuilderStep + , buildTransaction + , explainTxBuildError ) -import Contract.TxConstraints (TxConstraints) +import Cardano.Types + ( Bech32String + , PoolPubKeyHash(PoolPubKeyHash) + , Transaction(Transaction) + , TransactionHash + , TransactionInput(TransactionInput) + , TransactionOutput + , TransactionUnspentOutput(TransactionUnspentOutput) + , UtxoMap + , _body + , _outputs + ) +import Cardano.Types + ( DataHash(DataHash) + , Epoch(Epoch) + , NativeScript + ( ScriptPubkey + , ScriptAll + , ScriptAny + , ScriptNOfK + , TimelockStart + , TimelockExpiry + ) + , TransactionHash(TransactionHash) + , TransactionInput(TransactionInput) + , TransactionOutput(TransactionOutput) + , TransactionUnspentOutput(TransactionUnspentOutput) + ) as X +import Cardano.Types.AuxiliaryData (AuxiliaryData) +import Cardano.Types.Ed25519KeyHash as Ed25519KeyHash +import Cardano.Types.OutputDatum (OutputDatum(OutputDatum, OutputDatumHash)) as X +import Cardano.Types.PoolPubKeyHash (PoolPubKeyHash(PoolPubKeyHash)) as X +import Cardano.Types.ScriptRef (ScriptRef(NativeScriptRef, PlutusScriptRef)) as X +import Cardano.Types.Transaction (Transaction(Transaction), empty) as X +import Cardano.Types.Transaction as Transaction +import Contract.Log (logTrace') +import Contract.Monad (Contract, runContractInEnv) import Contract.UnbalancedTx (mkUnbalancedTx) import Control.Monad.Error.Class (catchError, liftEither, throwError) import Control.Monad.Reader (ReaderT, asks, runReaderT) import Control.Monad.Reader.Class (ask) -import Ctl.Internal.BalanceTx (balanceTxWithConstraints) as BalanceTx -import Ctl.Internal.BalanceTx.Constraints (BalanceTxConstraintsBuilder) +import Ctl.Internal.BalanceTx as B +import Ctl.Internal.BalanceTx.Constraints (BalancerConstraints) import Ctl.Internal.BalanceTx.Error ( Actual(Actual) , BalanceTxError @@ -69,102 +89,13 @@ import Ctl.Internal.BalanceTx.Error , Expected(Expected) , explainBalanceTxError ) as BalanceTxError -import Ctl.Internal.BalanceTx.Types (FinalizedTransaction) -import Ctl.Internal.BalanceTx.Types (FinalizedTransaction(FinalizedTransaction)) as FinalizedTransaction -import Ctl.Internal.BalanceTx.UnattachedTx (UnindexedTx) -import Ctl.Internal.Cardano.Types.NativeScript - ( NativeScript - ( ScriptPubkey - , ScriptAll - , ScriptAny - , ScriptNOfK - , TimelockStart - , TimelockExpiry - ) - ) as NativeScript -import Ctl.Internal.Cardano.Types.ScriptRef - ( ScriptRef(NativeScriptRef, PlutusScriptRef) - , scriptRefFromMintingPolicy - ) as ScriptRef -import Ctl.Internal.Cardano.Types.Transaction - ( AuxiliaryData(AuxiliaryData) - , AuxiliaryDataHash(AuxiliaryDataHash) - , BootstrapWitness - , Certificate - ( StakeRegistration - , StakeDeregistration - , StakeDelegation - , PoolRegistration - , PoolRetirement - , GenesisKeyDelegation - , MoveInstantaneousRewardsCert - ) - , CostModel(CostModel) - , Costmdls(Costmdls) - , Ed25519Signature - , Epoch(Epoch) - , ExUnitPrices - , ExUnits - , GenesisHash(GenesisHash) - , Mint(Mint) - , Nonce(IdentityNonce, HashNonce) - , PoolPubKeyHash(PoolPubKeyHash) - , ProposedProtocolParameterUpdates(ProposedProtocolParameterUpdates) - , ProtocolParamUpdate - , ProtocolVersion - , PublicKey - , Redeemer - , RequiredSigner(RequiredSigner) - , ScriptDataHash(ScriptDataHash) - , SubCoin - , Transaction(Transaction) - , TransactionWitnessSet(TransactionWitnessSet) - , TxBody(TxBody) - , URL(URL) - , UnitInterval - , Update - , Vkey(Vkey) - , Vkeywitness(Vkeywitness) - , _auxiliaryData - , _auxiliaryDataHash - , _body - , _bootstraps - , _certs - , _collateral - , _fee - , _inputs - , _isValid - , _mint - , _nativeScripts - , _networkId - , _outputs - , _plutusData - , _plutusScripts - , _referenceInputs - , _requiredSigners - , _scriptDataHash - , _ttl - , _update - , _validityStartInterval - , _vkeys - , _withdrawals - , _witnessSet - , mkPoolPubKeyHash - , poolPubKeyHashToBech32 - ) as Transaction -import Ctl.Internal.Cardano.Types.Transaction - ( Transaction - , TransactionOutput - , _body - , _outputs - ) import Ctl.Internal.Contract.AwaitTxConfirmed ( awaitTxConfirmed , awaitTxConfirmedWithTimeout , awaitTxConfirmedWithTimeoutSlots , isTxConfirmed ) as X -import Ctl.Internal.Contract.MinFee (calculateMinFee) as Contract +import Ctl.Internal.Contract.MinFee (calculateMinFee) as X import Ctl.Internal.Contract.Monad (getQueryHandle) import Ctl.Internal.Contract.QueryHandle.Error (GetTxMetadataError) import Ctl.Internal.Contract.QueryHandle.Error @@ -174,129 +105,78 @@ import Ctl.Internal.Contract.QueryHandle.Error , GetTxMetadataClientError ) ) as X -import Ctl.Internal.Contract.Sign (signTransaction) as Contract -import Ctl.Internal.Hashing (transactionHash) as Hashing -import Ctl.Internal.Plutus.Conversion - ( fromPlutusUtxoMap - , toPlutusCoin - , toPlutusTxOutputWithRefScript - ) -import Ctl.Internal.Plutus.Types.Transaction - ( TransactionOutput(TransactionOutput) - , TransactionOutputWithRefScript(TransactionOutputWithRefScript) - ) as PTransaction -import Ctl.Internal.Plutus.Types.Transaction (UtxoMap) -import Ctl.Internal.Plutus.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - , _input - , _output - , lookupTxHash - , mkTxUnspentOut - ) as PTransactionUnspentOutput -import Ctl.Internal.Plutus.Types.Value (Coin) -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx(UnbalancedTx)) -import Ctl.Internal.Serialization (convertTransaction) -import Ctl.Internal.Types.OutputDatum - ( OutputDatum(NoOutputDatum, OutputDatumHash, OutputDatum) - , outputDatumDataHash - , outputDatumDatum - ) as OutputDatum -import Ctl.Internal.Types.RewardAddress - ( RewardAddress - , rewardAddressFromBech32 - , rewardAddressFromBytes - , rewardAddressToBech32 - , rewardAddressToBytes - ) as X +import Ctl.Internal.Contract.Sign (signTransaction) +import Ctl.Internal.Contract.Sign (signTransaction) as X +import Ctl.Internal.Service.Error (ClientError) import Ctl.Internal.Types.ScriptLookups (ScriptLookups) -import Ctl.Internal.Types.Scripts - ( Language(PlutusV1, PlutusV2) - , plutusV1Script - , plutusV2Script - ) as Scripts -import Ctl.Internal.Types.Transaction - ( DataHash(DataHash) - , TransactionHash(TransactionHash) - , TransactionInput(TransactionInput) - ) as Transaction -import Ctl.Internal.Types.Transaction - ( TransactionHash - , TransactionInput(TransactionInput) - ) +import Ctl.Internal.Types.TxConstraints (TxConstraints) import Ctl.Internal.Types.UsedTxOuts ( UsedTxOuts , lockTransactionInputs , unlockTransactionInputs ) -import Ctl.Internal.Types.VRFKeyHash - ( VRFKeyHash - , vrfKeyHashFromBytes - , vrfKeyHashToBytes - ) as X +import Data.Array as Array import Data.Array.NonEmpty as NonEmptyArray import Data.Bifunctor (lmap) import Data.Either (Either(Left, Right)) import Data.Foldable (foldl, length) -import Data.Generic.Rep (class Generic) import Data.Lens.Getter (view) -import Data.Map (Map) -import Data.Map (empty, insert) as Map -import Data.Newtype (class Newtype, unwrap) -import Data.Show.Generic (genericShow) +import Data.Map (empty, insert, toUnfoldable) as Map +import Data.Maybe (Maybe(Nothing)) +import Data.Newtype (unwrap) +import Data.String.Utils (startsWith) import Data.Traversable (class Traversable, for_, traverse) -import Data.Tuple (Tuple(Tuple), fst) -import Data.Tuple.Nested (type (/\), (/\)) +import Data.Tuple (fst) +import Data.Tuple.Nested ((/\)) import Data.UInt (UInt) import Effect.Aff (bracket, error) import Effect.Aff.Class (liftAff) import Effect.Class (liftEffect) import Effect.Exception (try) -import JS.BigInt (BigInt) - --- | Signs a transaction with potential failure. -signTransaction - :: forall (tx :: Type) - . Newtype tx Transaction - => tx - -> Contract BalancedSignedTransaction -signTransaction = - map BalancedSignedTransaction - <<< Contract.signTransaction - <<< unwrap - --- | Submits a `BalancedSignedTransaction`, which is the output of +import Prim.Coerce (class Coercible) +import Prim.TypeError (class Warn, Text) +import Safe.Coerce (coerce) + +buildTx + :: Array TransactionBuilderStep + -> Contract Transaction +buildTx steps = do + case buildTransaction steps of + Left err -> do + throwError (error $ explainTxBuildError err) + Right res -> pure res + +hashTransaction + :: Warn + (Text "Deprecated: hashTransaction. Use Cardano.Types.Transaction.hash") + => Transaction + -> TransactionHash +hashTransaction = Transaction.hash + +-- | Submits a `Transaction`, which is the output of -- | `signTransaction`. submit - :: BalancedSignedTransaction + :: Transaction -> Contract TransactionHash submit tx = do + logTrace' $ "Submitting transaction: " <> show tx eiTxHash <- submitE tx liftEither $ flip lmap eiTxHash \err -> error $ "Failed to submit tx:\n" <> show err --- | Submits a `BalancedSignedTransaction`, which is the output of +-- | Submits a `Transaction` that normally should be retreived from -- | `signTransaction`. Preserves the errors returned by the backend in -- | the case they need to be inspected. submitE - :: BalancedSignedTransaction + :: Transaction -> Contract (Either ClientError TransactionHash) submitE tx = do queryHandle <- getQueryHandle - eiTxHash <- liftAff $ queryHandle.submitTx $ unwrap tx + eiTxHash <- liftAff $ queryHandle.submitTx tx void $ asks (_.hooks >>> _.onSubmit) >>= - traverse \hook -> liftEffect $ void $ try $ hook $ unwrap tx + traverse \hook -> liftEffect $ void $ try $ hook tx pure eiTxHash --- | Calculate the minimum transaction fee. -calculateMinFee - :: Transaction - -> UtxoMap - -> Contract Coin -calculateMinFee tx additionalUtxos = do - networkId <- asks _.networkId - let additionalUtxos' = fromPlutusUtxoMap networkId additionalUtxos - toPlutusCoin <$> Contract.calculateMinFee tx additionalUtxos' - -- | Helper to adapt to UsedTxOuts. withUsedTxOuts :: forall (a :: Type) @@ -347,22 +227,16 @@ withSingleTransaction prepare extract utx action = -- | in any other context. -- | After the function completes, the locks will be removed. -- | Errors will be thrown. -withBalancedTxsWithConstraints - :: forall (a :: Type) - . Array (UnbalancedTx /\ BalanceTxConstraintsBuilder) - -> (Array FinalizedTransaction -> Contract a) - -> Contract a -withBalancedTxsWithConstraints = - withTransactions balanceTxsWithConstraints unwrap - --- | Same as `withBalancedTxsWithConstraints`, but uses the default balancer --- | constraints. withBalancedTxs :: forall (a :: Type) - . Array UnbalancedTx - -> (Array FinalizedTransaction -> Contract a) + . Array + { transaction :: Transaction + , usedUtxos :: UtxoMap + , balancerConstraints :: BalancerConstraints + } + -> (Array Transaction -> Contract a) -> Contract a -withBalancedTxs = withTransactions balanceTxs unwrap +withBalancedTxs = withTransactions balanceTxs identity -- | Execute an action on a balanced transaction (`balanceTx` will -- | be called). Within this function, all transaction inputs @@ -370,79 +244,44 @@ withBalancedTxs = withTransactions balanceTxs unwrap -- | used in any other context. -- | After the function completes, the locks will be removed. -- | Errors will be thrown. -withBalancedTxWithConstraints - :: forall (a :: Type) - . UnbalancedTx - -> BalanceTxConstraintsBuilder - -> (FinalizedTransaction -> Contract a) - -> Contract a -withBalancedTxWithConstraints unbalancedTx = - withSingleTransaction balanceAndLockWithConstraints unwrap - <<< Tuple unbalancedTx - --- | Same as `withBalancedTxWithConstraints`, but uses the default balancer --- | constraints. withBalancedTx :: forall (a :: Type) - . UnbalancedTx - -> (FinalizedTransaction -> Contract a) + . Transaction + -> UtxoMap + -> BalancerConstraints + -> (Transaction -> Contract a) -> Contract a -withBalancedTx = withSingleTransaction balanceAndLock unwrap - -unUnbalancedTx - :: UnbalancedTx -> UnindexedTx /\ Map TransactionInput TransactionOutput -unUnbalancedTx - ( UnbalancedTx - { transaction - , datums - , redeemers - , usedUtxos - } - ) = - { transaction, datums, redeemers } /\ usedUtxos - --- | Attempts to balance an `UnbalancedTx` using the specified --- | balancer constraints. --- | --- | `balanceTxWithConstraints` is a throwing variant. -balanceTxWithConstraintsE - :: UnbalancedTx - -> BalanceTxConstraintsBuilder - -> Contract (Either BalanceTxError.BalanceTxError FinalizedTransaction) -balanceTxWithConstraintsE tx = - let - tx' /\ ix = unUnbalancedTx tx - in - BalanceTx.balanceTxWithConstraints tx' ix - --- | Attempts to balance an `UnbalancedTx` using the specified --- | balancer constraints. --- | --- | 'Throwing' variant of `balanceTxWithConstraintsE`. -balanceTxWithConstraints - :: UnbalancedTx - -> BalanceTxConstraintsBuilder - -> Contract FinalizedTransaction -balanceTxWithConstraints tx bcb = do - result <- balanceTxWithConstraintsE tx bcb - case result of - Left err -> throwError $ error $ BalanceTxError.explainBalanceTxError err - Right ftx -> pure ftx - --- | Balance a transaction without providing balancer constraints. --- | --- | `balanceTx` is a throwing variant. +withBalancedTx tx usedUtxos balancerConstraints = + withSingleTransaction + ( \transaction -> balanceAndLock + { transaction, usedUtxos, balancerConstraints } + ) + identity + tx + +-- | A variant of `balanceTx` that returns a balancer error value. balanceTxE - :: UnbalancedTx - -> Contract (Either BalanceTxError.BalanceTxError FinalizedTransaction) -balanceTxE = flip balanceTxWithConstraintsE mempty + :: Transaction + -> UtxoMap + -> BalancerConstraints + -> Contract (Either BalanceTxError.BalanceTxError Transaction) +balanceTxE tx utxos = B.balanceTxWithConstraints tx utxos --- | Balance a transaction without providing balancer constraints. +-- | Balance a single transaction. +-- | +-- | `UtxoMap` is a collection of UTxOs used as inputs that are coming from outside of the user wallet. -- | -- | `balanceTxE` is a non-throwing version of this function. -balanceTx :: UnbalancedTx -> Contract FinalizedTransaction -balanceTx utx = do - result <- balanceTxE utx +-- | +-- | Use `balanceTxs` to balance multiple transactions and prevent them from +-- | using the same input UTxOs. +balanceTx + :: Transaction + -> UtxoMap + -> BalancerConstraints + -> Contract Transaction +balanceTx utx utxos constraints = do + result <- balanceTxE utx utxos constraints case result of Left err -> throwError $ error $ BalanceTxError.explainBalanceTxError err Right ftx -> pure ftx @@ -450,111 +289,95 @@ balanceTx utx = do -- | Balances each transaction using specified balancer constraint sets and -- | locks the used inputs so that they cannot be reused by subsequent -- | transactions. -balanceTxsWithConstraints - :: forall (t :: Type -> Type) - . Traversable t - => t (UnbalancedTx /\ BalanceTxConstraintsBuilder) - -> Contract (t FinalizedTransaction) -balanceTxsWithConstraints unbalancedTxs = - unlockAllOnError $ traverse balanceAndLockWithConstraints unbalancedTxs +balanceTxs + :: Array + { transaction :: Transaction + , usedUtxos :: UtxoMap + , balancerConstraints :: BalancerConstraints + } + -> Contract (Array Transaction) +balanceTxs unbalancedTxs = + unlockAllOnError $ traverse balanceAndLock unbalancedTxs where unlockAllOnError :: forall (a :: Type). Contract a -> Contract a unlockAllOnError f = catchError f $ \e -> do for_ unbalancedTxs $ - withUsedTxOuts <<< unlockTransactionInputs <<< uutxToTx <<< fst + withUsedTxOuts <<< unlockTransactionInputs <<< _.transaction throwError e - uutxToTx :: UnbalancedTx -> Transaction - uutxToTx = _.transaction <<< unwrap - --- | Same as `balanceTxsWithConstraints`, but uses the default balancer --- | constraints. -balanceTxs - :: forall (t :: Type -> Type) - . Traversable t - => t UnbalancedTx - -> Contract (t FinalizedTransaction) -balanceTxs = balanceTxsWithConstraints <<< map (flip Tuple mempty) - -balanceAndLockWithConstraints - :: UnbalancedTx /\ BalanceTxConstraintsBuilder - -> Contract FinalizedTransaction -balanceAndLockWithConstraints (unbalancedTx /\ constraints) = do - balancedTx <- balanceTxWithConstraints unbalancedTx constraints - void $ withUsedTxOuts $ - lockTransactionInputs (unwrap balancedTx) - pure balancedTx - balanceAndLock - :: UnbalancedTx - -> Contract FinalizedTransaction -balanceAndLock = balanceAndLockWithConstraints <<< flip Tuple mempty - -newtype BalancedSignedTransaction = BalancedSignedTransaction Transaction - -derive instance Generic BalancedSignedTransaction _ -derive instance Newtype BalancedSignedTransaction _ -derive newtype instance Eq BalancedSignedTransaction -derive newtype instance EncodeAeson BalancedSignedTransaction - -instance Show BalancedSignedTransaction where - show = genericShow - -getTxFinalFee :: BalancedSignedTransaction -> BigInt -getTxFinalFee = - unwrap <<< view (Transaction._body <<< Transaction._fee) <<< unwrap + :: { transaction :: Transaction + , usedUtxos :: UtxoMap + , balancerConstraints :: BalancerConstraints + } + -> Contract Transaction +balanceAndLock { transaction, usedUtxos, balancerConstraints } = do + balancedTx <- balanceTx transaction usedUtxos balancerConstraints + void $ withUsedTxOuts $ lockTransactionInputs balancedTx + pure balancedTx --- | Fetch transaction metadata. --- | Returns `Right` when the transaction exists and metadata was non-empty -getTxMetadata +-- | Fetch transaction auxiliary data. +-- | Returns `Right` when the transaction exists and auxiliary data is not empty +getTxAuxiliaryData :: TransactionHash - -> Contract (Either GetTxMetadataError GeneralTransactionMetadata) -getTxMetadata th = do + -> Contract (Either GetTxMetadataError AuxiliaryData) +getTxAuxiliaryData txHash = do queryHandle <- getQueryHandle - liftAff $ queryHandle.getTxMetadata th + liftAff $ queryHandle.getTxAuxiliaryData txHash -- | Builds an expected utxo set from transaction outputs. Predicts output -- | references (`TransactionInput`s) for each output by calculating the -- | transaction hash and indexing the outputs in the order they appear in the -- | transaction. This function should be used for transaction chaining -- | in conjunction with `mustUseAdditionalUtxos` balancer constraint. --- | Throws an exception if conversion to Plutus outputs fails. createAdditionalUtxos :: forall (tx :: Type) - . Newtype tx Transaction + . Coercible tx Transaction => tx -> Contract UtxoMap createAdditionalUtxos tx = do - transactionId <- - liftEffect $ Hashing.transactionHash <$> convertTransaction (unwrap tx) + let transactionId = Transaction.hash $ coerce tx let txOutputs :: Array TransactionOutput - txOutputs = view (_body <<< _outputs) (unwrap tx) + txOutputs = view (_body <<< _outputs) $ coerce tx txIn :: UInt -> TransactionInput txIn index = TransactionInput { transactionId, index } - plutusOutputs <- - liftContractM "createAdditionalUtxos: Failed to convert to Plutus outputs" - (traverse toPlutusTxOutputWithRefScript txOutputs) - - pure $ plutusOutputs # + pure $ txOutputs # foldl (\utxo txOut -> Map.insert (txIn $ length utxo) txOut utxo) Map.empty -submitTxFromConstraintsReturningFee - :: ScriptLookups - -> TxConstraints - -> Contract { txHash :: TransactionHash, txFinalFee :: BigInt } -submitTxFromConstraintsReturningFee lookups constraints = do - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx - balancedSignedTx <- signTransaction balancedTx - txHash <- submit balancedSignedTx - pure { txHash, txFinalFee: getTxFinalFee balancedSignedTx } - submitTxFromConstraints :: ScriptLookups -> TxConstraints -> Contract TransactionHash -submitTxFromConstraints lookups constraints = - _.txHash <$> submitTxFromConstraintsReturningFee lookups constraints +submitTxFromConstraints lookups constraints = do + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balancedTx <- balanceTx unbalancedTx usedUtxos mempty + balancedSignedTx <- signTransaction balancedTx + submit balancedSignedTx + +submitTxFromBuildPlan + :: UtxoMap + -> BalancerConstraints + -> Array TransactionBuilderStep + -> Contract Transaction +submitTxFromBuildPlan usedUtxos balancerConstraints plan = do + unbalancedTx <- buildTx plan + balancedTx <- balanceTx unbalancedTx usedUtxos balancerConstraints + balancedSignedTx <- signTransaction balancedTx + void $ submit balancedSignedTx + pure balancedSignedTx + +lookupTxHash + :: TransactionHash -> UtxoMap -> Array TransactionUnspentOutput +lookupTxHash txHash utxos = + map (\(input /\ output) -> TransactionUnspentOutput { input, output }) + $ Array.filter (fst >>> unwrap >>> _.transactionId >>> eq txHash) + $ Map.toUnfoldable utxos + +mkPoolPubKeyHash :: Bech32String -> Maybe PoolPubKeyHash +mkPoolPubKeyHash str + | startsWith "pool" str = PoolPubKeyHash <$> + Ed25519KeyHash.fromBech32 str + | otherwise = Nothing diff --git a/src/Contract/TxConstraints.purs b/src/Contract/TxConstraints.purs index 0ccfdde20e..226d977532 100644 --- a/src/Contract/TxConstraints.purs +++ b/src/Contract/TxConstraints.purs @@ -7,8 +7,7 @@ import Ctl.Internal.Types.TxConstraints , InputConstraint(InputConstraint) , InputWithScriptRef(RefInput, SpendInput) , OutputConstraint(OutputConstraint) - , TxConstraints(TxConstraints) - , isSatisfiable + , TxConstraints , mustBeSignedBy , mustDelegateStakeNativeScript , mustDelegateStakePlutusScript @@ -41,15 +40,14 @@ import Ctl.Internal.Types.TxConstraints , mustPayToScriptAddressWithScriptRef , mustPayToScriptWithScriptRef , mustProduceAtLeast - , mustProduceAtLeastTotal , mustReferenceOutput + , mustRegisterDrep , mustRegisterPool , mustRegisterStakePubKey , mustRegisterStakeScript , mustRetirePool , mustSatisfyAnyOf , mustSpendAtLeast - , mustSpendAtLeastTotal , mustSpendNativeScriptOutput , mustSpendPubKeyOutput , mustSpendScriptOutput @@ -58,9 +56,4 @@ import Ctl.Internal.Types.TxConstraints , mustWithdrawStakeNativeScript , mustWithdrawStakePlutusScript , mustWithdrawStakePubKey - , pubKeyPayments - , requiredDatums - , requiredMonetaryPolicies - , requiredSignatories - , singleton ) as TxConstraints diff --git a/src/Contract/UnbalancedTx.purs b/src/Contract/UnbalancedTx.purs index 1bb9ceec51..e8f3491313 100644 --- a/src/Contract/UnbalancedTx.purs +++ b/src/Contract/UnbalancedTx.purs @@ -3,50 +3,22 @@ module Contract.UnbalancedTx ( mkUnbalancedTx , mkUnbalancedTxE - , module X ) where import Prelude +import Cardano.Types (Transaction, UtxoMap) import Contract.Monad (Contract) import Control.Monad.Error.Class (throwError) -import Ctl.Internal.ProcessConstraints (mkUnbalancedTxImpl) as PC +import Ctl.Internal.ProcessConstraints as PC import Ctl.Internal.ProcessConstraints.Error ( MkUnbalancedTxError , explainMkUnbalancedTxError ) -import Ctl.Internal.ProcessConstraints.Error - ( MkUnbalancedTxError - ( CannotFindDatum - , CannotQueryDatum - , CannotConvertPOSIXTimeRange - , CannotSolveTimeConstraints - , CannotGetMintingPolicyScriptIndex - , CannotGetValidatorHashFromAddress - , CannotMakeValue - , CannotWithdrawRewardsPubKey - , CannotWithdrawRewardsPlutusScript - , CannotWithdrawRewardsNativeScript - , DatumNotFound - , DatumWrongHash - , MintingPolicyHashNotCurrencySymbol - , MintingPolicyNotFound - , OwnPubKeyAndStakeKeyMissing - , TxOutRefNotFound - , TxOutRefWrongType - , WrongRefScriptHash - , ValidatorHashNotFound - , CannotSatisfyAny - , ExpectedPlutusScriptGotNativeScript - , CannotMintZero - ) - , explainMkUnbalancedTxError - ) as X -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx) -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx(UnbalancedTx)) as X import Ctl.Internal.Types.ScriptLookups (ScriptLookups) import Ctl.Internal.Types.TxConstraints (TxConstraints) import Data.Either (Either(Left, Right)) +import Data.Tuple.Nested (type (/\)) import Effect.Exception (error) -- | Create an `UnbalancedTx` given `ScriptLookups` and @@ -58,11 +30,14 @@ import Effect.Exception (error) mkUnbalancedTxE :: ScriptLookups -> TxConstraints - -> Contract (Either MkUnbalancedTxError UnbalancedTx) + -> Contract (Either MkUnbalancedTxError (Transaction /\ UtxoMap)) mkUnbalancedTxE = PC.mkUnbalancedTxImpl -- | As `mkUnbalancedTxE`, but 'throwing'. -mkUnbalancedTx :: ScriptLookups -> TxConstraints -> Contract UnbalancedTx +mkUnbalancedTx + :: ScriptLookups + -> TxConstraints + -> Contract (Transaction /\ UtxoMap) mkUnbalancedTx lookups constraints = mkUnbalancedTxE lookups constraints >>= case _ of Left err -> throwError $ error $ explainMkUnbalancedTxError err diff --git a/src/Contract/Utxos.purs b/src/Contract/Utxos.purs index 6064192d14..958f7ee57d 100644 --- a/src/Contract/Utxos.purs +++ b/src/Contract/Utxos.purs @@ -9,21 +9,13 @@ module Contract.Utxos import Prelude +import Cardano.Types (Address, TransactionOutput, UtxoMap) +import Cardano.Types (UtxoMap) as X +import Cardano.Types.TransactionInput (TransactionInput) import Contract.Log (logWarn') -import Contract.Monad (Contract, liftContractM, liftedE) -import Contract.Prelude (for) -import Control.Monad.Reader.Class (asks) +import Contract.Monad (Contract, liftedE) import Ctl.Internal.BalanceTx.Sync (getControlledAddresses, isCip30Wallet) import Ctl.Internal.Contract.Monad (getQueryHandle) -import Ctl.Internal.Plutus.Conversion - ( fromPlutusAddress - , toPlutusTxOutput - , toPlutusUtxoMap - ) -import Ctl.Internal.Plutus.Types.Address (class PlutusAddress, getAddress) -import Ctl.Internal.Plutus.Types.Transaction (TransactionOutput, UtxoMap) -import Ctl.Internal.Plutus.Types.Transaction (UtxoMap) as X -import Ctl.Internal.Types.Transaction (TransactionInput) import Data.Maybe (Maybe) import Data.Set (member) as Set import Effect.Aff.Class (liftAff) @@ -38,13 +30,9 @@ import Effect.Aff.Class (liftAff) -- | potential problems. This function will raise a warning in the logs if -- | wallet address is used. utxosAt - :: forall (address :: Type) - . PlutusAddress address - => address + :: Address -> Contract UtxoMap -utxosAt addressAny = do - networkId <- asks _.networkId - let address = fromPlutusAddress networkId $ getAddress addressAny +utxosAt address = do queryHandle <- getQueryHandle whenM isCip30Wallet do walletAddresses <- getControlledAddresses @@ -56,9 +44,7 @@ utxosAt addressAny = do <> "that are available on wallet addresses are actually spendable. " <> "See the docs for UTxO locking in `doc/query-layers.md`. Using " <> "`getWalletUtxos` is a way to avoid the potential problems." - cardanoUtxoMap <- liftedE $ liftAff $ queryHandle.utxosAt address - liftContractM "utxosAt: failed to convert utxos" - $ toPlutusUtxoMap cardanoUtxoMap + liftedE $ liftAff $ queryHandle.utxosAt address -- | Queries for an utxo given a transaction input. -- | Returns `Nothing` if the output has already been spent. @@ -67,6 +53,4 @@ getUtxo -> Contract (Maybe TransactionOutput) getUtxo oref = do queryHandle <- getQueryHandle - cardanoTxOutput <- liftedE $ liftAff $ queryHandle.getUtxoByOref oref - for cardanoTxOutput - (liftContractM "getUtxo: failed to convert tx output" <<< toPlutusTxOutput) + liftedE $ liftAff $ queryHandle.getUtxoByOref oref diff --git a/src/Contract/Value.purs b/src/Contract/Value.purs index 0c9fb2cb79..0f04cc104c 100644 --- a/src/Contract/Value.purs +++ b/src/Contract/Value.purs @@ -1,51 +1,47 @@ --- | A module that defines tokens in Cardano and helpers. module Contract.Value - ( module CurrencySymbol - , module Scripts - , module TokenName - , module Value + ( module X + , CurrencySymbol + , TokenName ) where -import Ctl.Internal.Plutus.Types.CurrencySymbol - ( CurrencySymbol - , adaSymbol - , currencyMPSHash - , getCurrencySymbol - , mkCurrencySymbol - , mpsSymbol - , scriptHashAsCurrencySymbol - ) as CurrencySymbol -import Ctl.Internal.Plutus.Types.Value - ( Coin(Coin) - , Value +import Cardano.Types (AssetName, ScriptHash) +import Cardano.Types.AssetName (AssetName(AssetName)) as X +import Cardano.Types.Coin (Coin(Coin)) as X +import Cardano.Types.ScriptHash (ScriptHash(ScriptHash)) as X +import Cardano.Types.Value + ( Value(Value) + , add + , assetToValue + , checkBinRel + , checkPred , coinToValue - , flattenNonAdaAssets - , flattenValue + , empty + , fromCsl , geq - , getLovelace - , getValue + , getAssetQuantity + , getCoin + , getMultiAsset , gt - , isCoinZero + , isPositive , isZero , leq , lovelaceValueOf , lt - , negation - , scale + , minus + , mkValue + , pprintValue , singleton - , singleton' - , split - , symbols + , sum + , toCsl , unionWith + , valueAssetClasses + , valueAssets , valueOf , valueToCoin - , valueToCoin' - ) as Value -import Ctl.Internal.Scripts (scriptCurrencySymbol) as Scripts -import Ctl.Internal.Types.TokenName - ( TokenName - , adaToken - , getTokenName - , mkTokenName - , mkTokenNames - ) as TokenName + ) as X + +-- | Deprecated, use `Cardano.Types.ScriptHash` +type CurrencySymbol = ScriptHash + +-- | Deprecated, use `Cardano.Types.AssetName` +type TokenName = AssetName diff --git a/src/Contract/Wallet.purs b/src/Contract/Wallet.purs index cf2dbeeadd..118c0fda54 100644 --- a/src/Contract/Wallet.purs +++ b/src/Contract/Wallet.purs @@ -9,28 +9,26 @@ module Contract.Wallet , getWalletUtxos , getWalletCollateral , getWalletAddress - , getWalletAddresses - , getWalletAddressWithNetworkTag - , getWalletAddressesWithNetworkTag , module X ) where import Prelude -import Contract.Address - ( Address - , AddressWithNetworkTag - , PaymentPubKeyHash - , StakePubKeyHash - ) +import Cardano.Types (Address, StakePubKeyHash, UtxoMap, Value) +import Cardano.Types.PaymentPubKeyHash (PaymentPubKeyHash) +import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput) +import Cardano.Types.Value as Value +import Cardano.Wallet.Key + ( KeyWallet + , PrivatePaymentKey(PrivatePaymentKey) + , PrivateStakeKey(PrivateStakeKey) + , privateKeysToKeyWallet + ) as X +import Cardano.Wallet.Key (PrivateDrepKey) import Contract.Config (PrivatePaymentKey, PrivateStakeKey) import Contract.Log (logTrace') -import Contract.Monad (Contract, liftContractM, liftedM) +import Contract.Monad (Contract) import Contract.Sync (syncBackendWithWallet, withoutSync) -import Contract.Transaction (TransactionUnspentOutput) -import Contract.Utxos (UtxoMap) -import Contract.Value (Value) -import Contract.Value as Value import Contract.Wallet.Key (KeyWallet, privateKeysToKeyWallet) import Control.Monad.Error.Class (liftEither) import Control.Monad.Reader (asks, local) @@ -39,45 +37,30 @@ import Ctl.Internal.Contract.Wallet , getRewardAddresses , getUnusedAddresses , getWallet + , getWalletAddresses + , ownDrepPubKey + , ownDrepPubKeyHash , ownPaymentPubKeyHashes + , ownRegisteredPubStakeKeys , ownStakePubKeyHashes + , ownUnregisteredPubStakeKeys , signData ) as X -import Ctl.Internal.Contract.Wallet (getWalletUtxos) as Wallet import Ctl.Internal.Contract.Wallet - ( ownPaymentPubKeyHashes + ( getWalletAddresses + , ownPaymentPubKeyHashes , ownStakePubKeyHashes ) +import Ctl.Internal.Contract.Wallet (getWalletUtxos) as Wallet import Ctl.Internal.Contract.Wallet as Contract -import Ctl.Internal.Deserialization.Keys (privateKeyFromBytes) as X import Ctl.Internal.Helpers (liftM) -import Ctl.Internal.Plutus.Conversion - ( toPlutusAddress - , toPlutusTxUnspentOutput - , toPlutusUtxoMap - ) -import Ctl.Internal.Plutus.Conversion.Address (toPlutusAddressWithNetworkTag) -import Ctl.Internal.Wallet (Wallet(KeyWallet)) as Wallet import Ctl.Internal.Wallet - ( Wallet(KeyWallet, GenericCip30) + ( Cip30Extensions + , Wallet(KeyWallet, GenericCip30) , WalletExtension - ( NamiWallet - , GeroWallet - , FlintWallet - , EternlWallet - , LodeWallet - , LaceWallet - , NuFiWallet - , GenericCip30Wallet - ) , isWalletAvailable ) as X -import Ctl.Internal.Wallet.Key - ( KeyWallet - , PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey(PrivateStakeKey) - , privateKeysToKeyWallet - ) as X +import Ctl.Internal.Wallet (Wallet(KeyWallet)) as Wallet import Ctl.Internal.Wallet.KeyFile (formatPaymentKey, formatStakeKey) as X import Ctl.Internal.Wallet.Spec ( Cip1852DerivationPath @@ -85,29 +68,20 @@ import Ctl.Internal.Wallet.Spec , mkKeyWalletFromMnemonic ) import Ctl.Internal.Wallet.Spec - ( MnemonicSource(MnemonicString, MnemonicFile) + ( KnownWallet(Nami, Gero, Flint, Eternl, Lode, Lace, NuFi) + , MnemonicSource(MnemonicString, MnemonicFile) , PrivatePaymentKeySource(PrivatePaymentKeyFile, PrivatePaymentKeyValue) , PrivateStakeKeySource(PrivateStakeKeyFile, PrivateStakeKeyValue) - , WalletSpec - ( UseKeys - , UseMnemonic - , ConnectToNami - , ConnectToGero - , ConnectToFlint - , ConnectToLode - , ConnectToLace - , ConnectToEternl - , ConnectToNuFi - , ConnectToGenericCip30 - ) + , WalletSpec(UseKeys, UseMnemonic, ConnectToGenericCip30) + , walletName ) as X import Data.Array (head) +import Data.Array as Array import Data.Bifunctor (lmap) -import Data.Foldable (fold, foldr) +import Data.Foldable (fold) import Data.Map as Map import Data.Maybe (Maybe(Just), fromMaybe) import Data.Newtype (unwrap) -import Data.Traversable (for, traverse) import Data.Tuple.Nested ((/\)) import Effect.Exception (error) import Prim.TypeError (class Warn, Text) @@ -135,52 +109,22 @@ withKeyWalletFromMnemonic mnemonic derivationPath stakeKeyPresence contract = do addNote = append "withKeyWalletFromMnemonic: " mkKeyWalletFromPrivateKeys - :: PrivatePaymentKey -> Maybe PrivateStakeKey -> KeyWallet + :: PrivatePaymentKey + -> Maybe PrivateStakeKey + -> Maybe PrivateDrepKey + -> KeyWallet mkKeyWalletFromPrivateKeys payment mbStake = privateKeysToKeyWallet payment mbStake --- | Get an `Address` of the browser wallet. +-- | Get the first `Address` of the wallet. getWalletAddress :: Warn ( Text - "This function returns only one `Adress` even in case multiple `Adress`es are available. Use `getWalletAdresses` instead" + "This function returns only one `Address` even in case multiple `Address`es are available. Use `getWalletAddresses` instead" ) => Contract (Maybe Address) getWalletAddress = head <$> getWalletAddresses --- | Get all the `Address`es of the browser wallet. -getWalletAddresses :: Contract (Array Address) -getWalletAddresses = do - addresses <- Contract.getWalletAddresses - traverse - ( liftM - (error "getWalletAddresses: failed to deserialize `Address`") - <<< toPlutusAddress - ) - addresses - --- | Get an `AddressWithNetworkTag` of the browser wallet. -getWalletAddressWithNetworkTag - :: Warn - ( Text - "This function returns only one `AddressWithNetworkTag` even in case multiple `AddressWithNetworkTag` are available. Use `getWalletAddressesWithNetworkTag` instead" - ) - => Contract (Maybe AddressWithNetworkTag) -getWalletAddressWithNetworkTag = head <$> getWalletAddressesWithNetworkTag - --- | Get all the `AddressWithNetworkTag`s of the browser wallet discarding errors. -getWalletAddressesWithNetworkTag :: Contract (Array AddressWithNetworkTag) -getWalletAddressesWithNetworkTag = do - addresses <- Contract.getWalletAddresses - traverse - ( liftM - ( error - "getWalletAddressesWithNetworkTag: failed to deserialize `Address`" - ) - <<< toPlutusAddressWithNetworkTag - ) - addresses - -- | Gets a wallet `PaymentPubKeyHash` via `getWalletAddresses`. ownPaymentPubKeyHash :: Warn @@ -215,10 +159,7 @@ getWalletUtxos = do >>> _.beforeCip30Methods ) syncBackendWithWallet - mCardanoUtxos <- Wallet.getWalletUtxos - for mCardanoUtxos $ - liftContractM "getWalletUtxos: unable to deserialize UTxOs" <<< - toPlutusUtxoMap + Wallet.getWalletUtxos getWalletBalance :: Contract (Maybe Value) @@ -231,13 +172,16 @@ getWalletBalance = do ) syncBackendWithWallet let - getUtxoValue = unwrap >>> _.output >>> unwrap >>> _.amount - sumValues = foldr (Value.unionWith add) mempty + getUtxoValue = unwrap >>> _.amount -- include both spendable UTxOs and collateral utxos <- getWalletUtxos <#> fromMaybe Map.empty collateralUtxos <- withoutSync getWalletCollateral <#> fold >>> toUtxoMap let allUtxos = Map.union utxos collateralUtxos - pure $ pure $ sumValues $ map getUtxoValue $ Map.values allUtxos + let + mbValueSum = Value.sum $ map getUtxoValue $ Array.fromFoldable $ Map.values + allUtxos + pure <$> liftM (error "getWalletBalance: overflow when summing `Value`s") + mbValueSum where toUtxoMap = Map.fromFoldable <<< map (unwrap >>> \({ input, output }) -> input /\ output) @@ -259,9 +203,4 @@ getWalletCollateral = do ) ) syncBackendWithWallet - mtxUnspentOutput <- Contract.getWalletCollateral - for mtxUnspentOutput $ traverse $ - liftedM - "getWalletCollateral: failed to deserialize TransactionUnspentOutput" - <<< pure - <<< toPlutusTxUnspentOutput + Contract.getWalletCollateral diff --git a/src/Contract/Wallet/Key.purs b/src/Contract/Wallet/Key.purs index cf5c334410..d461402134 100644 --- a/src/Contract/Wallet/Key.purs +++ b/src/Contract/Wallet/Key.purs @@ -4,15 +4,12 @@ module Contract.Wallet.Key , publicKeyFromPrivateKey ) where -import Prelude - -import Ctl.Internal.Cardano.Types.Transaction (PublicKey, mkFromCslPubKey) -import Ctl.Internal.Serialization.Keys (publicKeyFromPrivateKey) as Internal -import Ctl.Internal.Serialization.Types (PrivateKey) -import Ctl.Internal.Wallet.Key +import Cardano.Types (PrivateKey, PublicKey) +import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Wallet.Key ( KeyWallet(KeyWallet) - , keyWalletPrivatePaymentKey - , keyWalletPrivateStakeKey + , getPrivatePaymentKey + , getPrivateStakeKey , privateKeysToKeyWallet ) as X import Ctl.Internal.Wallet.Spec @@ -20,6 +17,13 @@ import Ctl.Internal.Wallet.Spec , StakeKeyPresence(WithStakeKey, WithoutStakeKey) , mkKeyWalletFromMnemonic ) as X +import Prim.TypeError (class Warn, Text) -publicKeyFromPrivateKey :: PrivateKey -> PublicKey -publicKeyFromPrivateKey = mkFromCslPubKey <<< Internal.publicKeyFromPrivateKey +publicKeyFromPrivateKey + :: Warn + ( Text + "Deprecated: publicKeyFromPrivateKey. Use Cardano.Types.PrivateKey.toPublicKey" + ) + => PrivateKey + -> PublicKey +publicKeyFromPrivateKey = PrivateKey.toPublicKey diff --git a/src/Contract/Wallet/KeyFile.purs b/src/Contract/Wallet/KeyFile.purs index eeec865eb4..4ce0638d77 100644 --- a/src/Contract/Wallet/KeyFile.purs +++ b/src/Contract/Wallet/KeyFile.purs @@ -6,7 +6,7 @@ module Contract.Wallet.KeyFile import Prelude -import Ctl.Internal.Wallet.Key (KeyWallet, privateKeysToKeyWallet) +import Cardano.Wallet.Key (KeyWallet, privateKeysToKeyWallet) import Ctl.Internal.Wallet.KeyFile ( privatePaymentKeyFromFile , privatePaymentKeyFromTextEnvelope @@ -19,7 +19,7 @@ import Ctl.Internal.Wallet.KeyFile ( privatePaymentKeyFromFile , privateStakeKeyFromFile ) -import Data.Maybe (Maybe) +import Data.Maybe (Maybe(Nothing)) import Data.Traversable (traverse) import Effect.Aff (Aff) import Node.Path (FilePath) @@ -37,3 +37,5 @@ mkKeyWalletFromFiles paymentKeyFile mbStakeKeyFile = privateKeysToKeyWallet <$> privatePaymentKeyFromFile paymentKeyFile <*> traverse privateStakeKeyFromFile mbStakeKeyFile + -- FIXME: allow to provide drep key + <*> pure Nothing diff --git a/src/Internal/Address.purs b/src/Internal/Address.purs deleted file mode 100644 index 746c8b23fe..0000000000 --- a/src/Internal/Address.purs +++ /dev/null @@ -1,75 +0,0 @@ -module Ctl.Internal.Address - ( addressToOgmiosAddress - , addressPaymentValidatorHash - , addressStakeValidatorHash - , ogmiosAddressToAddress - ) where - -import Prelude - -import Control.Alt ((<|>)) -import Ctl.Internal.QueryM.Ogmios as Ogmios -import Ctl.Internal.Serialization.Address - ( Address - , addressBech32 - , addressFromBech32 - , baseAddressDelegationCred - , baseAddressFromAddress - , baseAddressPaymentCred - , enterpriseAddressFromAddress - , enterpriseAddressPaymentCred - , stakeCredentialToScriptHash - ) -import Ctl.Internal.Serialization.Hash (ScriptHash) -import Ctl.Internal.Types.Scripts - ( StakeValidatorHash(StakeValidatorHash) - , ValidatorHash(ValidatorHash) - ) -import Data.Maybe (Maybe) - --- | A module for address related helpers - --------------------------------------------------------------------------------- --- Conversion between various address types --------------------------------------------------------------------------------- --- JsonRpc2.Address is a bech32 string, so wrap to Transaction.Types.Bech32 --- | Converts an `JsonRpc2.Address` (bech32string) to internal `Address` -ogmiosAddressToAddress :: Ogmios.OgmiosAddress -> Maybe Address -ogmiosAddressToAddress = addressFromBech32 - --- | Converts an (internal) `Address` to `JsonRpc2.Address` (bech32string) -addressToOgmiosAddress :: Address -> Ogmios.OgmiosAddress -addressToOgmiosAddress = addressBech32 - --------------------------------------------------------------------------------- --- `Address` to `ValidatorHash` --------------------------------------------------------------------------------- - --- | Get the `ValidatorHash` of an address (base or enterprise). --- | The value is extracted from the payment component. -addressPaymentValidatorHash :: Address -> Maybe ValidatorHash -addressPaymentValidatorHash = map ValidatorHash <<< addressPaymentScriptHash - -addressPaymentScriptHash :: Address -> Maybe ScriptHash -addressPaymentScriptHash addr = - baseAddressPaymentScriptHash addr <|> enterpriseAddressPaymentScriptHash addr - -baseAddressPaymentScriptHash :: Address -> Maybe ScriptHash -baseAddressPaymentScriptHash = - stakeCredentialToScriptHash - <=< pure <<< baseAddressPaymentCred - <=< baseAddressFromAddress - -enterpriseAddressPaymentScriptHash :: Address -> Maybe ScriptHash -enterpriseAddressPaymentScriptHash = - stakeCredentialToScriptHash - <=< pure <<< enterpriseAddressPaymentCred - <=< enterpriseAddressFromAddress - --- | Get the `StakeValidatorHash` of a base address. --- | The value is extracted from the stake component. -addressStakeValidatorHash :: Address -> Maybe StakeValidatorHash -addressStakeValidatorHash = - map StakeValidatorHash <<< stakeCredentialToScriptHash - <=< pure <<< baseAddressDelegationCred - <=< baseAddressFromAddress diff --git a/src/Internal/Affjax.js b/src/Internal/Affjax.js index 83a9091df4..d8c4de3fb4 100644 --- a/src/Internal/Affjax.js +++ b/src/Internal/Affjax.js @@ -1,27 +1,17 @@ -/* global BROWSER_RUNTIME */ +export const driver = nodeDriver; -export const driver = async () => { - if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - return browserDriver; - } else { - return await nodeDriver(); - } -}; +// we rely on the bundler to inject polyfills for the browser -const browserDriver = { - newXHR: function () { - return new XMLHttpRequest(); - }, - fixupUrl: function (url) { - return url || "/"; - } -}; +let nodeDriverCache = null; async function nodeDriver() { + if (nodeDriverCache !== null) { + return nodeDriverCache; + } const { default: XHR } = await import("xhr2"); const { default: urllib } = await import("url"); - return { + nodeDriverCache = { newXHR: function () { return new XHR(); }, @@ -36,4 +26,6 @@ async function nodeDriver() { } } }; + + return nodeDriverCache; } diff --git a/src/Internal/ApplyArgs.js b/src/Internal/ApplyArgs.js deleted file mode 100644 index 9ff6702981..0000000000 --- a/src/Internal/ApplyArgs.js +++ /dev/null @@ -1,41 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -let apply_args; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); - apply_args = await import("apply-args-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); - apply_args = await import("apply-args-nodejs"); -} - -/** - * @param {} left - * @param {} right - * @param {PlutusData} args - * @param {PlutusScript} script - * @returns {Either String PlutusScript} - */ -export function apply_params_to_script(left) { - return right => args => script => { - let version = script.language_version(); - let appliedScript; - try { - let scriptBytes = script.bytes(); // raw bytes - let argsBytes = args.to_bytes(); // cbor - - try { - appliedScript = apply_args.apply_params_to_script_no_panic( - argsBytes, - scriptBytes - ); - } catch (e) { - return left("Error applying argument to script: ".concat(e.toString())); - } - } catch (e1) { - return left("Error serializing arguments: ".concat(e1.toString())); - } - return right(lib.PlutusScript.new_with_version(appliedScript, version)); - }; -} diff --git a/src/Internal/ApplyArgs.purs b/src/Internal/ApplyArgs.purs deleted file mode 100644 index 6c670300a0..0000000000 --- a/src/Internal/ApplyArgs.purs +++ /dev/null @@ -1,48 +0,0 @@ -module Ctl.Internal.ApplyArgs - ( ApplyArgsError(ApplyArgsError) - , applyArgs - ) where - -import Prelude - -import Aeson (class DecodeAeson, class EncodeAeson) -import Ctl.Internal.Deserialization.WitnessSet as D -import Ctl.Internal.Serialization.PlutusData (convertPlutusData) as S -import Ctl.Internal.Serialization.PlutusScript (convertPlutusScript) as S -import Ctl.Internal.Serialization.Types as CSL -import Ctl.Internal.Types.PlutusData (PlutusData(List)) -import Ctl.Internal.Types.Scripts (PlutusScript) -import Data.Either (Either(Left, Right)) -import Data.Generic.Rep (class Generic) -import Data.Newtype (class Newtype) -import Data.Profunctor.Choice (left) -import Data.Show.Generic (genericShow) - -foreign import apply_params_to_script - :: (forall (x :: Type). x -> Either x CSL.PlutusScript) - -> (forall (x :: Type). x -> Either String x) - -> CSL.PlutusData - -> CSL.PlutusScript - -> Either String CSL.PlutusScript - -apply_params_to_script_either - :: CSL.PlutusData -> CSL.PlutusScript -> Either String CSL.PlutusScript -apply_params_to_script_either = apply_params_to_script Left Right - -newtype ApplyArgsError = ApplyArgsError String - -derive instance Newtype ApplyArgsError _ -derive instance Generic ApplyArgsError _ -derive newtype instance EncodeAeson ApplyArgsError -derive newtype instance DecodeAeson ApplyArgsError - -instance Show ApplyArgsError where - show = genericShow - -applyArgs - :: PlutusScript -> Array PlutusData -> Either ApplyArgsError PlutusScript -applyArgs script paramsList = left ApplyArgsError do - let params = S.convertPlutusData (List paramsList) - appliedScript <- apply_params_to_script_either params - (S.convertPlutusScript script) - Right $ D.convertPlutusScript appliedScript diff --git a/src/Internal/BalanceTx/BalanceTx.purs b/src/Internal/BalanceTx/BalanceTx.purs index 2d9a382d76..18050d2a5e 100644 --- a/src/Internal/BalanceTx/BalanceTx.purs +++ b/src/Internal/BalanceTx/BalanceTx.purs @@ -4,8 +4,53 @@ module Ctl.Internal.BalanceTx import Prelude -import Contract.Log (logWarn') -import Control.Monad.Except.Trans (ExceptT(ExceptT), except, runExceptT) +import Cardano.Transaction.Edit (editTransaction) +import Cardano.Types + ( AssetClass(AssetClass) + , Certificate + ( StakeDeregistration + , StakeRegistration + , StakeRegDelegCert + , VoteRegDelegCert + , StakeVoteRegDelegCert + , RegDrepCert + , UnregDrepCert + ) + , Coin(Coin) + , Language(PlutusV1) + , PlutusScript(PlutusScript) + , Transaction + , TransactionBody + , TransactionOutput + , UtxoMap + , Value(Value) + , _amount + , _body + , _certs + , _fee + , _inputs + , _mint + , _networkId + , _outputs + , _plutusScripts + , _referenceInputs + , _withdrawals + , _witnessSet + ) +import Cardano.Types.Address (Address) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Coin as Coin +import Cardano.Types.OutputDatum (OutputDatum(OutputDatum)) +import Cardano.Types.TransactionBody (_votingProposals) +import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.TransactionUnspentOutput as TransactionUnspentOutputs +import Cardano.Types.TransactionWitnessSet (_redeemers) +import Cardano.Types.UtxoMap (pprintUtxoMap) +import Cardano.Types.Value (getMultiAsset, mkValue, pprintValue) +import Cardano.Types.Value as Value +import Contract.Log (logInfo', logWarn') +import Control.Monad.Except (class MonadError) +import Control.Monad.Except.Trans (except, runExceptT) import Control.Monad.Logger.Class (info) as Logger import Control.Monad.Reader (asks) import Control.Parallel (parTraverse) @@ -36,78 +81,28 @@ import Ctl.Internal.BalanceTx.Constraints ) as Constraints import Ctl.Internal.BalanceTx.Error ( BalanceTxError - ( UtxoLookupFailedFor - , UtxoMinAdaValueCalculationFailed - , ReindexRedeemersError - , InsufficientCollateralUtxos + ( CouldNotGetUtxos , CouldNotGetCollateral - , CouldNotGetUtxos + , InsufficientCollateralUtxos + , NumericOverflowError + , UtxoLookupFailedFor ) ) import Ctl.Internal.BalanceTx.ExUnitsAndMinFee ( evalExUnitsAndMinFee , finalizeTransaction ) -import Ctl.Internal.BalanceTx.RedeemerIndex - ( attachIndexedRedeemers - , indexRedeemers - , mkRedeemersContext - ) import Ctl.Internal.BalanceTx.Sync (isCip30Wallet, syncBackendWithWallet) import Ctl.Internal.BalanceTx.Types ( BalanceTxM - , FinalizedTransaction , askCoinsPerUtxoUnit , askNetworkId , asksConstraints , liftContract , liftEitherContract - , withBalanceTxConstraints - ) -import Ctl.Internal.BalanceTx.UnattachedTx - ( EvaluatedTx - , UnindexedTx - , _transaction - , indexTx + , withBalancerConstraints ) import Ctl.Internal.BalanceTx.UtxoMinAda (utxoMinAdaValue) -import Ctl.Internal.Cardano.Types.Transaction - ( Certificate(StakeRegistration, StakeDeregistration) - , Transaction - , TransactionOutput - , TxBody - , UtxoMap - , _body - , _certs - , _fee - , _inputs - , _mint - , _networkId - , _outputs - , _plutusScripts - , _referenceInputs - , _withdrawals - , _witnessSet - , pprintUtxoMap - ) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( transactionUnspentOutputsToUtxoMap - ) -import Ctl.Internal.Cardano.Types.Value - ( AssetClass - , Coin(Coin) - , Value(Value) - , coinToValue - , equipartitionValueWithTokenQuantityUpperBound - , getNonAdaAsset - , lovelaceValueOf - , minus - , mkValue - , posNonAdaAsset - , pprintValue - , valueToCoin' - ) -import Ctl.Internal.Cardano.Types.Value as Value import Ctl.Internal.CoinSelection.UtxoIndex (UtxoIndex, buildUtxoIndex) import Ctl.Internal.Contract (getProtocolParameters) import Ctl.Internal.Contract.Monad (Contract, filterLockedUtxos, getQueryHandle) @@ -116,19 +111,17 @@ import Ctl.Internal.Contract.Wallet , getWalletCollateral , getWalletUtxos ) as Wallet -import Ctl.Internal.Helpers (liftEither, pprintTagSet, (??)) -import Ctl.Internal.Partition (equipartition, partition) -import Ctl.Internal.Plutus.Conversion (fromPlutusUtxoMap) -import Ctl.Internal.Serialization.Address (Address) -import Ctl.Internal.Types.OutputDatum (OutputDatum(NoOutputDatum, OutputDatum)) +import Ctl.Internal.Helpers (liftEither, pprintTagSet, unsafeFromJust, (??)) +import Ctl.Internal.Partition + ( equipartition + , equipartitionValueWithTokenQuantityUpperBound + , partition + ) import Ctl.Internal.Types.ProtocolParameters ( ProtocolParameters(ProtocolParameters) ) -import Ctl.Internal.Types.Scripts - ( Language(PlutusV1) - , PlutusScript(PlutusScript) - ) -import Ctl.Internal.Types.Transaction (TransactionInput) +import Ctl.Internal.Types.Val (Val(Val), pprintVal) +import Ctl.Internal.Types.Val as Val import Data.Array as Array import Data.Array.NonEmpty (NonEmptyArray) import Data.Array.NonEmpty @@ -142,10 +135,10 @@ import Data.Array.NonEmpty , zipWith ) as NEArray import Data.Array.NonEmpty as NEA -import Data.Bifunctor (lmap) +import Data.Bitraversable (ltraverse) import Data.Either (Either, hush, note) import Data.Foldable (any, fold, foldMap, foldr, length, null, or, sum) -import Data.Function (on) +import Data.Lens (view) import Data.Lens.Getter ((^.)) import Data.Lens.Setter ((%~), (.~), (?~)) import Data.Log.Tag (TagSet, tag, tagSetTag) @@ -153,14 +146,17 @@ import Data.Log.Tag (fromArray) as TagSet import Data.Map (Map) import Data.Map ( empty + , filter , filterWithKey , insert + , isEmpty , lookup + , singleton , toUnfoldable , union ) as Map -import Data.Maybe (Maybe(Just, Nothing), fromMaybe, isJust, maybe) -import Data.Newtype (class Newtype, unwrap, wrap) +import Data.Maybe (Maybe(Just, Nothing), isJust, maybe) +import Data.Newtype (unwrap, wrap) import Data.Set (Set) import Data.Set as Set import Data.Traversable (for, traverse) @@ -168,26 +164,18 @@ import Data.Tuple (fst) import Data.Tuple.Nested (type (/\), (/\)) import Data.UInt (toInt) as UInt import Effect.Aff.Class (liftAff) -import Effect.Class (liftEffect) import JS.BigInt (BigInt) -import JS.BigInt (toString) as BigInt +import Partial.Unsafe (unsafePartial) -- | Balances an unbalanced transaction using the specified balancer -- | constraints. balanceTxWithConstraints - :: UnindexedTx + :: Transaction -> Map TransactionInput TransactionOutput -> BalanceTxConstraintsBuilder - -> Contract (Either BalanceTxError FinalizedTransaction) -balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do - pparams <- getProtocolParameters - - withBalanceTxConstraints constraintsBuilder $ runExceptT do - let - depositValuePerCert = (unwrap pparams).stakeAddressDeposit - certsFee = getStakingBalance (transaction.transaction) - depositValuePerCert - + -> Contract (Either BalanceTxError Transaction) +balanceTxWithConstraints transaction extraUtxos constraintsBuilder = + withBalancerConstraints constraintsBuilder $ runExceptT do changeAddress <- getChangeAddress mbSrcAddrs <- asksConstraints Constraints._srcAddresses @@ -203,7 +191,10 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do >>> _.syncBackendWithWallet >>> _.beforeBalancing ) - syncBackendWithWallet + do + logInfo' "balanceTxWithConstraints: syncBackendWithWallet" + syncBackendWithWallet + logInfo' "balanceTxWithConstraints: Wallet.getWalletUtxos" note CouldNotGetUtxos <$> do Wallet.getWalletUtxos -- Use UTxOs from source addresses @@ -220,7 +211,7 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do >>> map (foldr Map.union Map.empty) -- merge all utxos into one map unbalancedCollTx <- transactionWithNetworkId >>= - if Array.null (transaction # _.redeemers) + if Array.null (transaction ^. _witnessSet <<< _redeemers) -- Don't set collateral if tx doesn't contain phase-2 scripts: then pure else setTransactionCollateral changeAddress @@ -239,24 +230,18 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do selectionStrategy <- asksConstraints Constraints._selectionStrategy - -- Reindex redeemers and update transaction - reindexedRedeemers <- liftEither $ lmap ReindexRedeemersError $ - indexRedeemers (mkRedeemersContext unbalancedCollTx) transaction.redeemers - let - reindexedTransaction = transaction - { transaction = attachIndexedRedeemers reindexedRedeemers - unbalancedCollTx - } + pparams <- liftContract getProtocolParameters -- Balance and finalize the transaction: runBalancer { strategy: selectionStrategy - , transaction: reindexedTransaction + , transaction: unbalancedCollTx , changeAddress - , changeDatum: fromMaybe NoOutputDatum changeDatum' + , changeDatum: changeDatum' , allUtxos , utxos: availableUtxos - , certsFee + , miscFee: getCertsBalance transaction pparams + getProposalsBalance + transaction } where getChangeAddress :: BalanceTxM Address @@ -266,8 +251,8 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do transactionWithNetworkId :: BalanceTxM Transaction transactionWithNetworkId = do networkId <- maybe askNetworkId pure - (transaction ^. _transaction <<< _body <<< _networkId) - pure (transaction.transaction # _body <<< _networkId ?~ networkId) + (transaction ^. _body <<< _networkId) + pure (transaction # _body <<< _networkId ?~ networkId) setTransactionCollateral :: Address -> Transaction -> BalanceTxM Transaction setTransactionCollateral changeAddr transaction = do @@ -295,20 +280,19 @@ setTransactionCollateral changeAddr transaction = do when (not $ Array.null filteredUtxos) do logWarn' $ pprintTagSet "Some of the collateral UTxOs returned by the wallet were marked as non-spendable and ignored" - (pprintUtxoMap (transactionUnspentOutputsToUtxoMap filteredUtxos)) + (pprintUtxoMap (TransactionUnspentOutputs.toUtxoMap filteredUtxos)) pure spendableUtxos -- otherwise, get all the utxos, filter out unspendable, and select -- collateral using internal algo, that is also used in KeyWallet Just utxoMap -> do ProtocolParameters params <- liftContract getProtocolParameters - networkId <- askNetworkId let - coinsPerUtxoUnit = params.coinsPerUtxoUnit maxCollateralInputs = UInt.toInt $ params.maxCollateralInputs - utxoMap' = Map.filterWithKey isSpendable $ fromPlutusUtxoMap networkId - utxoMap - mbCollateral <- liftEffect $ map Array.fromFoldable <$> - selectCollateral coinsPerUtxoUnit maxCollateralInputs utxoMap' + utxoMap' = Map.filterWithKey isSpendable utxoMap + mbCollateral = + Array.fromFoldable <$> + selectCollateral params.coinsPerUtxoByte maxCollateralInputs + utxoMap' liftEither $ note (InsufficientCollateralUtxos utxoMap') mbCollateral addTxCollateralReturn collateral (addTxCollateral collateral transaction) changeAddr @@ -319,48 +303,52 @@ setTransactionCollateral changeAddr transaction = do type BalancerParams = { strategy :: SelectionStrategy - , transaction :: UnindexedTx + , transaction :: Transaction , changeAddress :: Address - , changeDatum :: OutputDatum + , changeDatum :: Maybe OutputDatum , allUtxos :: UtxoMap , utxos :: UtxoMap - , certsFee :: Coin + , miscFee :: BigInt -- can be negative (deregistration) } +-- TODO: remove the parameter type BalancerState tx = { transaction :: tx , leftoverUtxos :: UtxoIndex , changeOutputs :: Array TransactionOutput - , minFee :: BigInt + , minFee :: Coin } initBalancerState - :: UnindexedTx + :: Transaction -> UtxoMap - -> BalancerState UnindexedTx + -> BalancerState Transaction initBalancerState transaction = buildUtxoIndex >>> - { transaction, leftoverUtxos: _, changeOutputs: mempty, minFee: zero } + { transaction, leftoverUtxos: _, changeOutputs: mempty, minFee: Coin.zero } data BalancerStep - = PrebalanceTx (BalancerState UnindexedTx) - | BalanceChangeAndMinFee (BalancerState UnindexedTx) + = PrebalanceTx (BalancerState Transaction) + | BalanceChangeAndMinFee (BalancerState Transaction) -runBalancer :: BalancerParams -> BalanceTxM FinalizedTransaction +runBalancer :: BalancerParams -> BalanceTxM Transaction runBalancer p = do utxos <- partitionAndFilterUtxos transaction <- addLovelacesToTransactionOutputs p.transaction mainLoop (initBalancerState transaction utxos.spendable) where + referenceInputSet = Set.fromFoldable $ p.transaction ^. _body + <<< _referenceInputs + -- We check if the transaction uses a plutusv1 script, so that we can filter -- out utxos which use plutusv2 features if so. txHasPlutusV1 :: Boolean txHasPlutusV1 = - case p.transaction ^. _transaction <<< _witnessSet <<< _plutusScripts of - Just scripts -> flip Array.any scripts case _ of + case p.transaction ^. _witnessSet <<< _plutusScripts of + [] -> false + scripts -> flip Array.any scripts case _ of PlutusScript (_ /\ PlutusV1) -> true _ -> false - Nothing -> false partitionAndFilterUtxos :: BalanceTxM { spendable :: UtxoMap, invalidInContext :: UtxoMap } @@ -382,7 +370,7 @@ runBalancer p = do let hasInlineDatum :: Boolean hasInlineDatum = case (unwrap output).datum of - OutputDatum _ -> true + Just (OutputDatum _) -> true _ -> false hasScriptRef :: Boolean @@ -391,12 +379,9 @@ runBalancer p = do spendable :: Boolean spendable = not $ or [ Set.member oref nonSpendableInputs + , Set.member oref referenceInputSet , any (\f -> f oref output) constraints.nonSpendableInputsPredicates - , Set.member oref - ( p.transaction ^. _transaction <<< _body <<< - _referenceInputs - ) ] validInContext :: Boolean @@ -417,10 +402,10 @@ runBalancer p = do } (Map.toUnfoldable p.utxos :: Array _) - mainLoop :: BalancerState UnindexedTx -> BalanceTxM FinalizedTransaction + mainLoop :: BalancerState Transaction -> BalanceTxM Transaction mainLoop = worker <<< PrebalanceTx where - worker :: BalancerStep -> BalanceTxM FinalizedTransaction + worker :: BalancerStep -> BalanceTxM Transaction worker (PrebalanceTx state) = do logBalancerState "Pre-balancing (Stage 1)" p.allUtxos state prebalanceTx state >>= runNextBalancerStep @@ -431,27 +416,25 @@ runBalancer p = do case newMinFee <= minFee of true -> do logTransaction "Balanced transaction (Done)" p.allUtxos - evaluatedTx.transaction - if Set.isEmpty $ evaluatedTx.transaction ^. _body <<< _inputs then + evaluatedTx + if Array.null $ evaluatedTx ^. _body <<< _inputs then do selectionState <- performMultiAssetSelection p.strategy leftoverUtxos - (lovelaceValueOf one) + (Val one Map.empty) runNextBalancerStep $ state - { transaction = transaction # - _transaction <<< _body <<< _inputs %~ Set.union - (selectedInputs selectionState) + { transaction = flip editTransaction transaction $ + _body <<< _inputs %~ appendInputs + (Array.fromFoldable $ selectedInputs selectionState) , leftoverUtxos = selectionState ^. _leftoverUtxos } else do - logTransaction "Balanced transaction (Done)" p.allUtxos - transaction.transaction finalizeTransaction evaluatedTx p.allUtxos false -> runNextBalancerStep $ state { transaction = transaction - # _transaction <<< _body <<< _fee .~ Coin newMinFee + # _body <<< _fee .~ newMinFee , minFee = newMinFee } @@ -461,21 +444,21 @@ runBalancer p = do -- | after generation of change, the first balancing step `PrebalanceTx` -- | is performed, otherwise we proceed to `BalanceChangeAndMinFee`. runNextBalancerStep - :: BalancerState UnindexedTx -> BalanceTxM FinalizedTransaction + :: BalancerState Transaction -> BalanceTxM Transaction runNextBalancerStep state@{ transaction } = do - let txBody = transaction ^. _transaction <<< _body - inputValue <- except $ getInputValue p.allUtxos txBody + let txBody = transaction ^. _body + inputValue <- except $ getInputVal p.allUtxos txBody ownWalletAddresses <- asks _.ownAddresses + inputValue' <- liftValue inputValue changeOutputs <- makeChange ownWalletAddresses p.changeAddress p.changeDatum - inputValue - p.certsFee + inputValue' + p.miscFee txBody requiredValue <- - except $ getRequiredValue p.certsFee p.allUtxos - $ setTxChangeOutputs changeOutputs transaction ^. _transaction <<< - _body + except $ getRequiredValue p.miscFee p.allUtxos + $ setTxChangeOutputs changeOutputs transaction ^. _body worker $ if requiredValue == mempty then BalanceChangeAndMinFee $ state @@ -486,27 +469,26 @@ runBalancer p = do -- | utxo set so that the total input value is sufficient to cover all -- | transaction outputs, including generated change and min fee. prebalanceTx - :: BalancerState UnindexedTx -> BalanceTxM (BalancerState UnindexedTx) + :: BalancerState Transaction -> BalanceTxM (BalancerState Transaction) prebalanceTx state@{ transaction, changeOutputs, leftoverUtxos } = performCoinSelection <#> \selectionState -> state { transaction = - ( transaction # - _transaction <<< _body <<< _inputs %~ - Set.union (selectedInputs selectionState) + ( flip editTransaction transaction $ + _body <<< _inputs %~ + appendInputs + (Array.fromFoldable $ selectedInputs selectionState) ) , leftoverUtxos = selectionState ^. _leftoverUtxos } where performCoinSelection :: BalanceTxM SelectionState - performCoinSelection = + performCoinSelection = do let - txBody :: TxBody - txBody = setTxChangeOutputs changeOutputs transaction ^. _transaction - <<< _body - in - except (getRequiredValue p.certsFee p.allUtxos txBody) - >>= performMultiAssetSelection p.strategy leftoverUtxos + txBody :: TransactionBody + txBody = setTxChangeOutputs changeOutputs transaction ^. _body + except (getRequiredValue p.miscFee p.allUtxos txBody) + >>= performMultiAssetSelection p.strategy leftoverUtxos -- | Calculates execution units for each script in the transaction and sets -- | min fee. @@ -515,51 +497,54 @@ runBalancer p = do -- | since this pre-condition is sometimes required for successfull script -- | execution during transaction evaluation. evaluateTx - :: BalancerState UnindexedTx -> BalanceTxM (BalancerState EvaluatedTx) + :: BalancerState Transaction -> BalanceTxM (BalancerState Transaction) evaluateTx state@{ transaction, changeOutputs } = do let - prebalancedTx :: UnindexedTx + prebalancedTx :: Transaction prebalancedTx = setTxChangeOutputs changeOutputs transaction - indexedTx <- liftEither $ lmap ReindexRedeemersError $ indexTx - prebalancedTx - evaluatedTx /\ minFee <- evalExUnitsAndMinFee indexedTx p.allUtxos + evaluatedTx /\ minFee <- evalExUnitsAndMinFee prebalancedTx p.allUtxos pure $ state { transaction = evaluatedTx, minFee = minFee } -- | For each transaction output, if necessary, adds some number of lovelaces -- | to cover the utxo min-ada-value requirement. addLovelacesToTransactionOutputs - :: UnindexedTx -> BalanceTxM UnindexedTx + :: Transaction -> BalanceTxM Transaction addLovelacesToTransactionOutputs transaction = map ( \txOutputs -> transaction # - _transaction <<< _body <<< _outputs .~ txOutputs + _body <<< _outputs .~ txOutputs ) $ traverse addLovelacesToTransactionOutput - (transaction ^. _transaction <<< _body <<< _outputs) + (transaction ^. _body <<< _outputs) addLovelacesToTransactionOutput :: TransactionOutput -> BalanceTxM TransactionOutput addLovelacesToTransactionOutput txOutput = do coinsPerUtxoUnit <- askCoinsPerUtxoUnit - txOutputMinAda <- - ExceptT $ liftEffect $ utxoMinAdaValue coinsPerUtxoUnit txOutput - <#> note UtxoMinAdaValueCalculationFailed let + txOutputMinAda = Coin $ utxoMinAdaValue coinsPerUtxoUnit txOutput txOutputRec = unwrap txOutput txOutputValue :: Value txOutputValue = txOutputRec.amount newCoin :: Coin - newCoin = Coin $ max (valueToCoin' txOutputValue) txOutputMinAda + newCoin = max (Value.getCoin txOutputValue) txOutputMinAda pure $ wrap txOutputRec - { amount = mkValue newCoin (getNonAdaAsset txOutputValue) } + { amount = mkValue newCoin (getMultiAsset txOutputValue) } + +-- removes duplicates +appendInputs + :: Array TransactionInput + -> Array TransactionInput + -> Array TransactionInput +appendInputs a b = Set.toUnfoldable (Set.fromFoldable a <> Set.fromFoldable b) setTxChangeOutputs - :: Array TransactionOutput -> UnindexedTx -> UnindexedTx + :: Array TransactionOutput -> Transaction -> Transaction setTxChangeOutputs outputs tx = - tx # _transaction <<< _body <<< _outputs %~ flip append outputs + tx # _body <<< _outputs %~ flip append outputs -------------------------------------------------------------------------------- -- Making change @@ -584,28 +569,30 @@ setTxChangeOutputs outputs tx = makeChange :: Set Address -> Address - -> OutputDatum + -> Maybe OutputDatum -> Value - -> Coin - -> TxBody + -> BigInt + -> TransactionBody -> BalanceTxM (Array TransactionOutput) makeChange ownWalletAddresses changeAddress changeDatum - inputValue - certsFee + inputValue' + miscFee txBody = -- Always generate change when a transaction has no outputs to avoid issues -- with transaction confirmation: -- FIXME: https://github.com/Plutonomicon/cardano-transaction-lib/issues/1293 if excessValue == mempty && (txBody ^. _outputs) /= mempty then pure mempty - else - map (mkChangeOutput changeAddress changeDatum) <$> - ( assignCoinsToChangeValues changeAddress excessCoin - =<< splitOversizedValues changeValueOutputCoinPairs - ) + else do + res <- traverse (ltraverse liftValue) changeValueOutputCoinPairs + >>= splitOversizedValues + >>= assignCoinsToChangeValues changeAddress excessCoin + pure $ mkChangeOutput changeAddress changeDatum <$> res where + inputValue = Val.fromValue inputValue' + -- | Change `Value`s for all assets, where each change map is paired with a -- | corresponding coin from the original outputs. -- | @@ -614,34 +601,41 @@ makeChange -- | -- | Taken from cardano-wallet: -- | https://github.com/input-output-hk/cardano-wallet/blob/4c2eb651d79212157a749d8e69a48fff30862e93/lib/wallet/src/Cardano/Wallet/CoinSelection/Internal/Balance.hs#L1447 - changeValueOutputCoinPairs :: NonEmptyArray (Value /\ BigInt) + changeValueOutputCoinPairs :: NonEmptyArray (Val /\ BigInt) changeValueOutputCoinPairs = outputCoins # NEArray.zip changeForAssets - # NEArray.sortWith (AssetCount <<< fst) + # NEArray.sortWith (Array.length <<< Val.valueAssets <<< fst) where outputCoins :: NonEmptyArray BigInt outputCoins = NEArray.fromArray - (valueToCoin' <<< _.amount <<< unwrap <$> ownAddressOutputs) + ( BigNum.toBigInt <<< unwrap <<< Value.getCoin <<< _.amount <<< unwrap + <$> ownAddressOutputs + ) ?? NEArray.singleton zero splitOversizedValues :: NonEmptyArray (Value /\ BigInt) -> BalanceTxM (NonEmptyArray (Value /\ BigInt)) splitOversizedValues pairs = - asksConstraints Constraints._maxChangeOutputTokenQuantity <#> case _ of - Nothing -> pairs - Just maxTokenQuantity -> - unbundle <$> - ( equipartitionValueWithTokenQuantityUpperBound maxTokenQuantity - =<< map bundle pairs - ) + asksConstraints Constraints._maxChangeOutputTokenQuantity >>= case _ of + Nothing -> pure pairs + Just maxTokenQuantity -> do + traverse bundle pairs <#> \bundled -> + unbundle <$> + ( equipartitionValueWithTokenQuantityUpperBound maxTokenQuantity =<< + bundled + ) where - bundle :: Value /\ BigInt -> Value - bundle (Value _ assets /\ coin) = mkValue (wrap coin) assets + bundle :: Value /\ BigInt -> BalanceTxM Value + bundle (Value _ assets /\ coin) = do + coin' <- liftEither + (note (NumericOverflowError Nothing) $ BigNum.fromBigInt coin) + pure $ mkValue (wrap coin') assets unbundle :: Value -> Value /\ BigInt - unbundle (Value coin assets) = mkValue mempty assets /\ unwrap coin + unbundle (Value coin assets) = mkValue mempty assets /\ BigNum.toBigInt + (unwrap coin) -- outputs belonging to one of the wallet's addresses. ownAddressOutputs :: Array TransactionOutput @@ -650,26 +644,29 @@ makeChange isOwnWalletAddress = unwrap >>> _.address >>> flip Set.member ownWalletAddresses - changeForAssets :: NonEmptyArray Value + changeForAssets :: NonEmptyArray Val changeForAssets = foldr (NEArray.zipWith (<>) <<< makeChangeForAsset ownAddressOutputs) (NEArray.replicate (length ownAddressOutputs) mempty) excessAssets excessAssets :: Array (AssetClass /\ BigInt) - excessAssets = Value.valueAssets excessValue + excessAssets = Val.valueAssets excessValue excessCoin :: BigInt - excessCoin = valueToCoin' excessValue + excessCoin = case excessValue of + Val c _ -> c - excessValue :: Value - excessValue = posValue $ - (inputValue <> mintValue txBody) `minus` - (outputValue txBody <> minFeeValue txBody <> coinToValue certsFee) + excessValue :: Val + excessValue = posVal $ + (inputValue <> mintValue txBody) `Val.minus` + (outputValue txBody <> minFeeValue txBody <> Val miscFee Map.empty) - posValue :: Value -> Value - posValue (Value (Coin coin) nonAdaAsset) = - mkValue (Coin $ max coin zero) (posNonAdaAsset nonAdaAsset) + posVal :: Val -> Val + posVal (Val coin nonAdaAsset) = + Val (max coin zero) + $ Map.filter (not <<< Map.isEmpty) + $ map (Map.filter (\x -> x > zero)) nonAdaAsset -- | Constructs change outputs for an asset. -- | @@ -687,18 +684,24 @@ makeChange makeChangeForAsset :: Array TransactionOutput -> (AssetClass /\ BigInt) - -> NonEmptyArray Value -makeChangeForAsset ownAddressOutputs (assetClass /\ excess) = - Value.assetToValue assetClass <$> + -> NonEmptyArray Val +makeChangeForAsset + ownAddressOutputs + (assetClass@(AssetClass scriptHash assetName) /\ excess) = + mkVal <$> partition excess weights ?? equipartition excess (length weights) where + mkVal n = Val zero (Map.singleton scriptHash $ Map.singleton assetName n) + weights :: NonEmptyArray BigInt weights = NEArray.fromArray assetQuantities ?? NEArray.singleton one assetQuantities :: Array BigInt assetQuantities = - ownAddressOutputs <#> Value.getAssetQuantity assetClass <<< _.amount <<< - unwrap + ownAddressOutputs <#> BigNum.toBigInt <<< Value.getAssetQuantity assetClass + <<< _.amount + <<< + unwrap -- | Constructs an array of ada change outputs based on the given distribution. -- | @@ -713,9 +716,9 @@ makeChangeForAsset ownAddressOutputs (assetClass /\ excess) = -- | -- | Taken from cardano-wallet: -- | https://github.com/input-output-hk/cardano-wallet/blob/4c2eb651d79212157a749d8e69a48fff30862e93/lib/wallet/src/Cardano/Wallet/CoinSelection/Internal/Balance.hs#L1799 -makeChangeForCoin :: NonEmptyArray BigInt -> BigInt -> NonEmptyArray Value +makeChangeForCoin :: NonEmptyArray BigInt -> BigInt -> NonEmptyArray Val makeChangeForCoin weights excess = - lovelaceValueOf <$> + flip Val Map.empty <$> partition excess weights ?? equipartition excess (length weights) -- | Assigns coin quantities to a list of pre-computed change `Value`s. @@ -748,9 +751,11 @@ assignCoinsToChangeValues -> BalanceTxM (Array Value) assignCoinsToChangeValues changeAddress adaAvailable pairsAtStart = changeValuesAtStart <#> \changeValues -> - worker (adaRequiredAtStart changeValues) changeValues + unsafeFromJust "assignCoinsToChangeValues" <<< Val.toValue <$> worker + (adaRequiredAtStart changeValues) + changeValues where - worker :: BigInt -> NonEmptyArray ChangeValue -> Array Value + worker :: BigInt -> NonEmptyArray ChangeValue -> Array Val worker adaRequired changeValues = changeValues # NEArray.uncons >>> case _ of { head: x, tail } | Just xs <- NEA.fromArray tail @@ -761,14 +766,14 @@ assignCoinsToChangeValues changeAddress adaAvailable pairsAtStart = adaRemaining :: BigInt adaRemaining = max zero (adaAvailable - adaRequired) - changeValuesForOutputCoins :: NonEmptyArray Value + changeValuesForOutputCoins :: NonEmptyArray Val changeValuesForOutputCoins = let weights = _.outputAda <$> changeValues in makeChangeForCoin weights adaRemaining - changeValuesWithMinCoins :: NonEmptyArray Value + changeValuesWithMinCoins :: NonEmptyArray Val changeValuesWithMinCoins = assignMinCoin <$> changeValues in NEArray.toArray $ @@ -776,11 +781,11 @@ assignCoinsToChangeValues changeAddress adaAvailable pairsAtStart = changeValuesForOutputCoins where noTokens :: ChangeValue -> Boolean - noTokens = null <<< Value.valueAssets <<< _.value + noTokens = null <<< Val.getAssets <<< _.value - assignMinCoin :: ChangeValue -> Value - assignMinCoin { value: (Value _ assets), minCoin } = - mkValue (wrap minCoin) assets + assignMinCoin :: ChangeValue -> Val + assignMinCoin { value: (Val _ assets), minCoin } = + Val minCoin assets adaRequiredAtStart :: NonEmptyArray ChangeValue -> BigInt adaRequiredAtStart = sum <<< map _.minCoin @@ -788,28 +793,19 @@ assignCoinsToChangeValues changeAddress adaAvailable pairsAtStart = changeValuesAtStart :: BalanceTxM (NonEmptyArray ChangeValue) changeValuesAtStart = for pairsAtStart \(value /\ outputAda) -> - { value, outputAda, minCoin: _ } <$> minCoinFor value + { value: Val.fromValue value, outputAda, minCoin: _ } <$> minCoinFor value minCoinFor :: Value -> BalanceTxM BigInt minCoinFor value = do let -- NOTE: Datum here doesn't matter, we deconstruct UTxO immediately anyway - txOutput = mkChangeOutput changeAddress NoOutputDatum value - coinsPerUtxoUnit <- askCoinsPerUtxoUnit - ExceptT $ liftEffect $ utxoMinAdaValue coinsPerUtxoUnit txOutput - <#> note UtxoMinAdaValueCalculationFailed + txOutput = mkChangeOutput changeAddress Nothing value + coinsPerUtxoByte <- askCoinsPerUtxoUnit + pure $ BigNum.toBigInt $ utxoMinAdaValue coinsPerUtxoByte txOutput -type ChangeValue = { value :: Value, outputAda :: BigInt, minCoin :: BigInt } +type ChangeValue = { value :: Val, outputAda :: BigInt, minCoin :: BigInt } -newtype AssetCount = AssetCount Value - -derive instance Newtype AssetCount _ -derive newtype instance Eq AssetCount - -instance Ord AssetCount where - compare = compare `on` (Array.length <<< Value.valueAssets <<< unwrap) - -mkChangeOutput :: Address -> OutputDatum -> Value -> TransactionOutput +mkChangeOutput :: Address -> Maybe OutputDatum -> Value -> TransactionOutput mkChangeOutput changeAddress datum amount = wrap { address: changeAddress, amount, datum, scriptRef: Nothing } @@ -817,65 +813,99 @@ mkChangeOutput changeAddress datum amount = wrap -- Getters for various `Value`s -------------------------------------------------------------------------------- -getRequiredValue :: Coin -> UtxoMap -> TxBody -> Either BalanceTxError Value -getRequiredValue certsFee utxos txBody = - getInputValue utxos txBody <#> \inputValue -> - (outputValue txBody <> minFeeValue txBody <> coinToValue certsFee) - `minus` (inputValue <> mintValue txBody) +getRequiredValue + :: BigInt -> UtxoMap -> TransactionBody -> Either BalanceTxError Val +getRequiredValue miscFee utxos txBody = do + getInputVal utxos txBody <#> \inputValue -> + ( outputValue txBody <> minFeeValue txBody <> Val miscFee Map.empty + ) + `Val.minus` (inputValue <> mintValue txBody) getAmount :: TransactionOutput -> Value getAmount = _.amount <<< unwrap -getInputValue :: UtxoMap -> TxBody -> Either BalanceTxError Value -getInputValue utxos txBody = - foldMap getAmount <$> +getInputVal :: UtxoMap -> TransactionBody -> Either BalanceTxError Val +getInputVal utxos txBody = + foldMap (view _amount >>> Val.fromValue) <$> for (Array.fromFoldable $ txBody ^. _inputs) \oref -> - note (UtxoLookupFailedFor oref) (Map.lookup oref utxos) + note (UtxoLookupFailedFor oref utxos) (Map.lookup oref utxos) -outputValue :: TxBody -> Value -outputValue txBody = foldMap getAmount (txBody ^. _outputs) +outputValue :: TransactionBody -> Val +outputValue txBody = foldMap (view _amount >>> Val.fromValue) + (txBody ^. _outputs) -minFeeValue :: TxBody -> Value -minFeeValue txBody = mkValue (txBody ^. _fee) mempty +minFeeValue :: TransactionBody -> Val +minFeeValue txBody = Val.fromCoin $ txBody ^. _fee -mintValue :: TxBody -> Value -mintValue txBody = maybe mempty (mkValue mempty <<< unwrap) (txBody ^. _mint) +mintValue :: TransactionBody -> Val +mintValue txBody = maybe mempty Val.fromMint (txBody ^. _mint) --- | Accounts for: --- | --- | - stake registration deposit --- | - stake deregistration deposit returns --- | - stake withdrawals fees -getStakingBalance :: Transaction -> Coin -> Coin -getStakingBalance tx depositLovelacesPerCert = +getProposalsBalance :: Transaction -> BigInt +getProposalsBalance tx = + let + deposits :: BigInt + deposits = + sum $ map (BigNum.toBigInt <<< _.deposit <<< unwrap) + (tx ^. _body <<< _votingProposals) + in + deposits + +getCertsBalance :: Transaction -> ProtocolParameters -> BigInt +getCertsBalance tx (ProtocolParameters pparams) = let - stakeDeposits :: BigInt - stakeDeposits = - (tx ^. _body <<< _certs) # fold - >>> map - case _ of - StakeRegistration _ -> unwrap depositLovelacesPerCert - StakeDeregistration _ -> negate $ unwrap depositLovelacesPerCert - _ -> zero - >>> sum - stakeWithdrawals = - unwrap $ fold $ fromMaybe Map.empty $ tx ^. _body <<< + stakeAddressDeposit :: BigInt + stakeAddressDeposit = BigNum.toBigInt $ unwrap pparams.stakeAddressDeposit + + toBi :: Coin -> BigInt + toBi = BigNum.toBigInt <<< unwrap + + deposits :: BigInt + deposits = + (tx ^. _body <<< _certs) # + map + ( case _ of + StakeRegistration _ -> + stakeAddressDeposit + + StakeDeregistration _ -> + negate $ stakeAddressDeposit + + StakeRegDelegCert _ _ stakeCredDeposit -> + toBi stakeCredDeposit + + VoteRegDelegCert _ _ stakeCredDeposit -> + toBi stakeCredDeposit + + StakeVoteRegDelegCert _ _ _ stakeCredDeposit -> + toBi stakeCredDeposit + + RegDrepCert _ drepDeposit _ -> + toBi drepDeposit + + UnregDrepCert _ drepDeposit -> + negate $ toBi drepDeposit + + _ -> zero + ) + >>> sum + + withdrawals :: BigInt + withdrawals = + sum $ map (BigNum.toBigInt <<< unwrap) $ tx ^. _body <<< _withdrawals - fee = stakeDeposits - stakeWithdrawals in - Coin fee + deposits - withdrawals -------------------------------------------------------------------------------- -- Helpers -------------------------------------------------------------------------------- logBalancerState - :: forall rest - . String + :: String -> UtxoMap - -> BalancerState { transaction :: Transaction | rest } + -> BalancerState Transaction -> BalanceTxM Unit -logBalancerState message utxos { transaction: { transaction }, changeOutputs } = +logBalancerState message utxos { transaction, changeOutputs } = logTransactionWithChange message utxos (Just changeOutputs) transaction logTransaction @@ -891,25 +921,31 @@ logTransactionWithChange -> BalanceTxM Unit logTransactionWithChange message utxos mChangeOutputs tx = let - txBody :: TxBody + txBody :: TransactionBody txBody = tx ^. _body outputValuesTagSet :: Maybe (Array TransactionOutput) -> Array TagSet outputValuesTagSet Nothing = - [ "Output Value" `tagSetTag` pprintValue (outputValue txBody) ] + [ "Output Value" `tagSetTag` pprintVal (outputValue txBody) ] outputValuesTagSet (Just changeOutputs) = - [ "Output Value without change" `tagSetTag` pprintValue + [ "Output Value without change" `tagSetTag` pprintVal (outputValue txBody) - , "Change Value" `tagSetTag` pprintValue (foldMap getAmount changeOutputs) + , "Change Value" `tagSetTag` pprintValue + (unsafePartial $ foldMap (getAmount) changeOutputs) ] - transactionInfo :: Value -> TagSet + transactionInfo :: Val -> TagSet transactionInfo inputValue = TagSet.fromArray $ - [ "Input Value" `tagSetTag` pprintValue inputValue - , "Mint Value" `tagSetTag` pprintValue (mintValue txBody) - , "Fees" `tag` BigInt.toString (unwrap (txBody ^. _fee)) + [ "Input Value" `tagSetTag` pprintVal inputValue + , "Mint Value" `tagSetTag` pprintVal (mintValue txBody) + , "Fees" `tag` BigNum.toString (unwrap (txBody ^. _fee)) ] <> outputValuesTagSet mChangeOutputs in - except (getInputValue utxos txBody) - >>= (flip Logger.info (message <> ":") <<< transactionInfo) + do + except (getInputVal utxos txBody) + >>= (flip Logger.info (message <> ":") <<< transactionInfo) + +liftValue :: forall a. MonadError BalanceTxError a => Val -> a Value +liftValue val = liftEither $ note (NumericOverflowError $ Just val) $ + Val.toValue val diff --git a/src/Internal/BalanceTx/CoinSelection.purs b/src/Internal/BalanceTx/CoinSelection.purs index 19b2796cc4..8a79c7579a 100644 --- a/src/Internal/BalanceTx/CoinSelection.purs +++ b/src/Internal/BalanceTx/CoinSelection.purs @@ -21,28 +21,21 @@ module Ctl.Internal.BalanceTx.CoinSelection import Prelude +import Cardano.Types.Asset (Asset(AdaAsset)) +import Cardano.Types.Asset as Asset +import Cardano.Types.AssetClass (AssetClass(AssetClass)) +import Cardano.Types.AssetName (unAssetName) +import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.UtxoMap (UtxoMap) import Control.Monad.Error.Class (class MonadThrow, throwError) import Ctl.Internal.BalanceTx.Error - ( Actual(Actual) - , BalanceTxError - ( BalanceInsufficientError - , InsufficientUtxoBalanceToCoverAsset + ( BalanceTxError + ( InsufficientUtxoBalanceToCoverAsset + , BalanceInsufficientError ) - , Expected(Expected) ) -import Ctl.Internal.Cardano.Types.Transaction (UtxoMap) -import Ctl.Internal.Cardano.Types.Value (AssetClass(AssetClass), Coin, Value) -import Ctl.Internal.Cardano.Types.Value - ( getAssetQuantity - , getCurrencySymbol - , leq - , valueAssets - , valueToCoin - , valueToCoin' - ) as Value import Ctl.Internal.CoinSelection.UtxoIndex - ( Asset(Asset, AssetLovelace) - , SelectionFilter(SelectAnyWith, SelectPairWith, SelectSingleton) + ( SelectionFilter(SelectSingleton, SelectPairWith, SelectAnyWith) , TxUnspentOutput , UtxoIndex , emptyUtxoIndex @@ -51,34 +44,30 @@ import Ctl.Internal.CoinSelection.UtxoIndex , utxoIndexPartition , utxoIndexUniverse ) -import Ctl.Internal.Plutus.Conversion (toPlutusValue) -import Ctl.Internal.Types.ByteArray (byteArrayToHex) -import Ctl.Internal.Types.TokenName (getTokenName) as TokenName -import Ctl.Internal.Types.Transaction (TransactionInput) -import Data.Array (snoc, uncons) as Array +import Ctl.Internal.Types.Val (Val) +import Ctl.Internal.Types.Val as Val +import Data.Array as Array import Data.Array.NonEmpty (NonEmptyArray) -import Data.Array.NonEmpty (cons', fromArray, singleton, uncons) as NEArray -import Data.Foldable (foldMap) as Foldable +import Data.Array.NonEmpty as NEArray +import Data.ByteArray (byteArrayToHex) +import Data.Foldable (foldMap) import Data.Function (applyFlipped) import Data.Generic.Rep (class Generic) -import Data.Lens (Lens') -import Data.Lens.Getter (view, (^.)) +import Data.Lens (Lens', over, view, (^.)) import Data.Lens.Iso.Newtype (_Newtype) import Data.Lens.Record (prop) -import Data.Lens.Setter (over) import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing), maybe, maybe') import Data.Newtype (class Newtype, unwrap, wrap) import Data.Set (Set) -import Data.Set (fromFoldable) as Set import Data.Show.Generic (genericShow) -import Data.Tuple (fst) as Tuple +import Data.Tuple (fst) import Data.Tuple.Nested (type (/\), (/\)) import Effect.Class (class MonadEffect) import JS.BigInt (BigInt) -import JS.BigInt (fromInt, toString) as BigInt -import Test.QuickCheck.Arbitrary (class Arbitrary) -import Test.QuickCheck.Gen (elements) as Arbitrary +import JS.BigInt as BigInt +import Test.QuickCheck (class Arbitrary) +import Test.QuickCheck.Gen as Arbitrary import Type.Proxy (Proxy(Proxy)) -------------------------------------------------------------------------------- @@ -126,10 +115,10 @@ performMultiAssetSelection => MonadThrow BalanceTxError m => SelectionStrategy -> UtxoIndex - -> Value + -> Val -> m SelectionState -performMultiAssetSelection strategy utxoIndex requiredValue = - case requiredValue `Value.leq` availableValue of +performMultiAssetSelection strategy utxoIndex requiredValue = do + case requiredValue `Val.leq` availableValue of true -> runRoundRobinM (mkSelectionState utxoIndex) selectors false -> @@ -137,11 +126,9 @@ performMultiAssetSelection strategy utxoIndex requiredValue = where balanceInsufficientError :: BalanceTxError balanceInsufficientError = - BalanceInsufficientError - (Expected $ toPlutusValue requiredValue) - (Actual $ toPlutusValue availableValue) + BalanceInsufficientError requiredValue availableValue - availableValue :: Value + availableValue :: Val availableValue = balance (utxoIndexUniverse utxoIndex) selectors @@ -149,7 +136,7 @@ performMultiAssetSelection strategy utxoIndex requiredValue = selectors = map assetSelector assets `Array.snoc` coinSelector where assets :: Array (AssetClass /\ BigInt) - assets = Value.valueAssets requiredValue + assets = Val.valueAssets requiredValue assetSelector :: AssetClass /\ BigInt -> SelectionState -> m (Maybe SelectionState) @@ -158,7 +145,7 @@ performMultiAssetSelection strategy utxoIndex requiredValue = coinSelector :: SelectionState -> m (Maybe SelectionState) coinSelector = runSelectionStep $ - coinSelectionLens strategy (Value.valueToCoin requiredValue) + coinSelectionLens strategy (Val.getCoin requiredValue) -- | Represents the internal state of a selection. -- | @@ -213,14 +200,14 @@ selectUtxo utxo@(oref /\ out) = <<< over _leftoverUtxos (utxoIndexDeleteEntry utxo) -- | Returns the balance of the given utxo set. -balance :: UtxoMap -> Value -balance = Foldable.foldMap (_.amount <<< unwrap) +balance :: UtxoMap -> Val +balance = foldMap (Val.fromValue <<< _.amount <<< unwrap) -- | Returns the balance of selected utxos. -- | -- | Taken from cardano-wallet: -- | https://github.com/input-output-hk/cardano-wallet/blob/a61d37f2557b8cb5c47b57da79375afad698eed4/lib/wallet/src/Cardano/Wallet/Primitive/Types/UTxOSelection.hs#L375 -selectedBalance :: SelectionState -> Value +selectedBalance :: SelectionState -> Val selectedBalance = balance <<< _.selectedUtxos <<< unwrap -- | Returns the quantity of the given asset in the selected `Value`. @@ -229,18 +216,18 @@ selectedBalance = balance <<< _.selectedUtxos <<< unwrap -- | https://github.com/input-output-hk/cardano-wallet/blob/a61d37f2557b8cb5c47b57da79375afad698eed4/lib/wallet/src/Cardano/Wallet/CoinSelection/Internal/Balance.hs#L2169 selectedAssetQuantity :: AssetClass -> SelectionState -> BigInt selectedAssetQuantity assetClass = - Value.getAssetQuantity assetClass <<< selectedBalance + Val.getAssetQuantity assetClass <<< selectedBalance -- | Returns the selected amount of Ada. -- | -- | Taken from cardano-wallet: -- |https://github.com/input-output-hk/cardano-wallet/blob/a61d37f2557b8cb5c47b57da79375afad698eed4/lib/wallet/src/Cardano/Wallet/CoinSelection/Internal/Balance.hs#L2175 selectedCoinQuantity :: SelectionState -> BigInt -selectedCoinQuantity = Value.valueToCoin' <<< selectedBalance +selectedCoinQuantity = Val.getCoin <<< selectedBalance -- | Returns the output references of the selected utxos. selectedInputs :: SelectionState -> Set TransactionInput -selectedInputs = Set.fromFoldable <<< Map.keys <<< view _selectedUtxos +selectedInputs = Map.keys <<< view _selectedUtxos -- | A `SelectionLens` gives `runSelectionStep` the information on the current -- | selection state along with the functions required to transition to the next @@ -272,9 +259,10 @@ assetSelectionLens selectionStrategy (assetClass /\ requiredQuantity) = selectedAssetQuantity assetClass , requiredQuantity , selectQuantityCover: - selectQuantityOf (Asset assetClass) SelectionPriorityCover + selectQuantityOf (Asset.fromAssetClass assetClass) SelectionPriorityCover , selectQuantityImprove: - selectQuantityOf (Asset assetClass) SelectionPriorityImprove + selectQuantityOf (Asset.fromAssetClass assetClass) + SelectionPriorityImprove , selectionStrategy } @@ -284,16 +272,16 @@ coinSelectionLens :: forall (m :: Type -> Type) . MonadEffect m => SelectionStrategy - -> Coin + -> BigInt -> SelectionLens m coinSelectionLens selectionStrategy coin = { assetDisplayString: show coin , currentQuantity: selectedCoinQuantity - , requiredQuantity: unwrap coin + , requiredQuantity: coin , selectQuantityCover: - selectQuantityOf AssetLovelace SelectionPriorityCover + selectQuantityOf AdaAsset SelectionPriorityCover , selectQuantityImprove: - selectQuantityOf AssetLovelace SelectionPriorityImprove + selectQuantityOf AdaAsset SelectionPriorityImprove , selectionStrategy } @@ -321,7 +309,7 @@ selectQuantityOf asset priority state = filters = filtersForAssetWithPriority asset priority updateState :: TxUnspentOutput /\ UtxoIndex -> SelectionState - updateState = flip selectUtxo state <<< Tuple.fst + updateState = flip selectUtxo state <<< fst -- | Runs just a single step of a coin selection. -- | @@ -468,11 +456,11 @@ showAssetClassWithQuantity (AssetClass cs tn) quantity = where displayCurrencySymbol :: String displayCurrencySymbol = - "cs: " <> byteArrayToHex (Value.getCurrencySymbol cs) <> ", " + "cs: " <> show cs <> ", " displayTokenName :: String displayTokenName = - "tn: " <> byteArrayToHex (TokenName.getTokenName tn) <> ", " + "tn: " <> byteArrayToHex (unAssetName tn) <> ", " displayQuantity :: String displayQuantity = diff --git a/src/Internal/BalanceTx/Collateral.purs b/src/Internal/BalanceTx/Collateral.purs index a6dc1a8f2c..3a773ea3ed 100644 --- a/src/Internal/BalanceTx/Collateral.purs +++ b/src/Internal/BalanceTx/Collateral.purs @@ -6,42 +6,41 @@ module Ctl.Internal.BalanceTx.Collateral import Prelude -import Control.Monad.Except.Trans (ExceptT(ExceptT), except) -import Ctl.Internal.BalanceTx.Collateral.Select (minRequiredCollateral) -import Ctl.Internal.BalanceTx.Collateral.Select (minRequiredCollateral) as X -import Ctl.Internal.BalanceTx.Error - ( BalanceTxError(CollateralReturnError, CollateralReturnMinAdaValueCalcError) - ) -import Ctl.Internal.BalanceTx.Types (BalanceTxM, askCoinsPerUtxoUnit) -import Ctl.Internal.BalanceTx.UtxoMinAda (utxoMinAdaValue) -import Ctl.Internal.Cardano.Types.Transaction - ( Transaction +import Cardano.Types + ( BigNum + , Coin + , MultiAsset + , Transaction , TransactionOutput + , TransactionUnspentOutput , _body , _collateral , _collateralReturn , _totalCollateral ) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput +import Cardano.Types.Address (Address) +import Cardano.Types.BigNum (add, max, maxValue, sub, zero) as BigNum +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.Value (getMultiAsset, mkValue, valueToCoin) as Value +import Control.Monad.Error.Class (throwError) +import Control.Monad.Except.Trans (except) +import Ctl.Internal.BalanceTx.Collateral.Select (minRequiredCollateral) +import Ctl.Internal.BalanceTx.Collateral.Select (minRequiredCollateral) as X +import Ctl.Internal.BalanceTx.Error + ( BalanceTxError(NumericOverflowError, CollateralReturnError) ) -import Ctl.Internal.Cardano.Types.Value (Coin, NonAdaAsset) -import Ctl.Internal.Cardano.Types.Value (getNonAdaAsset, mkValue, valueToCoin') as Value -import Ctl.Internal.Serialization.Address (Address) -import Ctl.Internal.Types.BigNum (maxValue, toBigInt) as BigNum -import Ctl.Internal.Types.OutputDatum (OutputDatum(NoOutputDatum)) -import Data.Either (Either(Left, Right), note) -import Data.Foldable (foldMap, foldl) +import Ctl.Internal.BalanceTx.Types (BalanceTxM, askCoinsPerUtxoUnit) +import Ctl.Internal.BalanceTx.UtxoMinAda (utxoMinAdaValue) +import Data.Either (Either(Left, Right)) +import Data.Foldable (foldl) +import Data.Lens ((.~)) import Data.Lens.Setter ((?~)) -import Data.Maybe (Maybe(Nothing)) +import Data.Maybe (Maybe(Just, Nothing)) import Data.Newtype (unwrap, wrap) -import Data.Ord.Max (Max(Max)) -import Effect.Class (liftEffect) -import JS.BigInt (BigInt) addTxCollateral :: Array TransactionUnspentOutput -> Transaction -> Transaction addTxCollateral collateral transaction = - transaction # _body <<< _collateral ?~ + transaction # _body <<< _collateral .~ map (_.input <<< unwrap) collateral -------------------------------------------------------------------------------- @@ -59,33 +58,33 @@ addTxCollateralReturn -> Transaction -> Address -> BalanceTxM Transaction -addTxCollateralReturn collateral transaction ownAddress = - let - collAdaValue :: BigInt - collAdaValue = foldl adaValue' zero collateral - - collNonAdaAsset :: NonAdaAsset - collNonAdaAsset = foldMap nonAdaAsset collateral - in - case collAdaValue <= minRequiredCollateral && collNonAdaAsset == mempty of - true -> - pure transaction - false -> - setTxCollateralReturn collAdaValue collNonAdaAsset +addTxCollateralReturn collateral transaction ownAddress = do + let maybeAdd acc n = BigNum.add (unwrap $ adaValue n) =<< acc + collAdaValue <- throwOnOverflow $ foldl maybeAdd (Just BigNum.zero) collateral + collMultiAsset <- throwOnOverflow $ MultiAsset.sum $ nonAdaAsset <$> + collateral + case + collAdaValue <= unwrap minRequiredCollateral && collMultiAsset == + MultiAsset.empty + of + true -> + pure transaction + false -> + setTxCollateralReturn collAdaValue collMultiAsset where setTxCollateralReturn - :: BigInt - -> NonAdaAsset + :: BigNum + -> MultiAsset -> BalanceTxM Transaction - setTxCollateralReturn collAdaValue collNonAdaAsset = do + setTxCollateralReturn collAdaValue collMultiAsset = do let maxBigNumAdaValue :: Coin - maxBigNumAdaValue = wrap (BigNum.toBigInt BigNum.maxValue) + maxBigNumAdaValue = wrap BigNum.maxValue collReturnOutputRec = { address: ownAddress - , amount: Value.mkValue maxBigNumAdaValue collNonAdaAsset - , datum: NoOutputDatum + , amount: Value.mkValue maxBigNumAdaValue collMultiAsset + , datum: Nothing , scriptRef: Nothing } @@ -94,30 +93,22 @@ addTxCollateralReturn collateral transaction ownAddress = -- Calculate the required min ada value for the collateral return output: minAdaValue <- do let returnAsTxOut = wrap collReturnOutputRec - ExceptT $ - liftEffect (utxoMinAdaValue coinsPerUtxoUnit returnAsTxOut) - <#> note - ( CollateralReturnMinAdaValueCalcError coinsPerUtxoUnit - returnAsTxOut - ) - + pure $ utxoMinAdaValue coinsPerUtxoUnit returnAsTxOut + -- Determine the actual ada value of the collateral return output: + collReturnAda <- throwOnOverflow do + remaining <- BigNum.sub collAdaValue (unwrap minRequiredCollateral) + pure $ BigNum.max remaining minAdaValue let - -- Determine the actual ada value of the collateral return output: - collReturnAda :: BigInt - collReturnAda = unwrap $ - Max (collAdaValue - minRequiredCollateral) <> Max minAdaValue - -- Build the final collateral return output: collReturnOutput :: TransactionOutput collReturnOutput = wrap $ collReturnOutputRec - { amount = Value.mkValue (wrap collReturnAda) collNonAdaAsset } + { amount = Value.mkValue (wrap collReturnAda) collMultiAsset } - totalCollateral :: BigInt - totalCollateral = collAdaValue - collReturnAda + totalCollateral <- throwOnOverflow $ BigNum.sub collAdaValue collReturnAda except $ - case totalCollateral > zero of + case totalCollateral > BigNum.zero of true -> -- Set collateral return and total collateral: Right $ @@ -129,13 +120,15 @@ addTxCollateralReturn collateral transaction ownAddress = -- Helpers -------------------------------------------------------------------------------- -adaValue :: TransactionUnspentOutput -> BigInt +adaValue :: TransactionUnspentOutput -> Coin adaValue = - Value.valueToCoin' <<< _.amount <<< unwrap <<< _.output <<< unwrap + Value.valueToCoin <<< _.amount <<< unwrap <<< _.output <<< unwrap -adaValue' :: BigInt -> TransactionUnspentOutput -> BigInt -adaValue' init = add init <<< adaValue - -nonAdaAsset :: TransactionUnspentOutput -> NonAdaAsset +nonAdaAsset :: TransactionUnspentOutput -> MultiAsset nonAdaAsset = - Value.getNonAdaAsset <<< _.amount <<< unwrap <<< _.output <<< unwrap + Value.getMultiAsset <<< _.amount <<< unwrap <<< _.output <<< unwrap + +throwOnOverflow :: forall a. Maybe a -> BalanceTxM a +throwOnOverflow = case _ of + Nothing -> throwError (NumericOverflowError Nothing) + Just a -> pure a diff --git a/src/Internal/BalanceTx/Collateral/Select.purs b/src/Internal/BalanceTx/Collateral/Select.purs index 992471d0a3..853d9ed299 100644 --- a/src/Internal/BalanceTx/Collateral/Select.purs +++ b/src/Internal/BalanceTx/Collateral/Select.purs @@ -6,20 +6,24 @@ module Ctl.Internal.BalanceTx.Collateral.Select import Prelude -import Ctl.Internal.BalanceTx.FakeOutput (fakeOutputWithNonAdaAssets) -import Ctl.Internal.BalanceTx.UtxoMinAda (utxoMinAdaValue) -import Ctl.Internal.Cardano.Types.Transaction - ( TransactionOutput - , UtxoMap - ) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput +import Cardano.Types.BigNum (BigNum) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Coin (Coin) +import Cardano.Types.Coin as Coin +import Cardano.Types.MultiAsset (MultiAsset) +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.TransactionOutput (TransactionOutput) +import Cardano.Types.TransactionUnspentOutput + ( TransactionUnspentOutput(TransactionUnspentOutput) ) -import Ctl.Internal.Cardano.Types.Value (NonAdaAsset) -import Ctl.Internal.Cardano.Types.Value (getNonAdaAsset, valueToCoin') as Value -import Ctl.Internal.Types.ProtocolParameters (CoinsPerUtxoUnit) -import Ctl.Internal.Types.Transaction (TransactionInput) -import Data.Foldable (foldMap, foldl) +import Cardano.Types.UtxoMap (UtxoMap) +import Cardano.Types.Value as Value +import Ctl.Internal.BalanceTx.FakeOutput (fakeOutputWithMultiAssets) +import Ctl.Internal.BalanceTx.UtxoMinAda (utxoMinAdaValue) +import Ctl.Internal.Helpers (unsafeFromJust) +import Data.Array as Array +import Data.Foldable (foldl) import Data.Function (on) import Data.List (List(Nil, Cons)) import Data.List as List @@ -27,16 +31,12 @@ import Data.Map (toUnfoldable) as Map import Data.Maybe (Maybe) import Data.Newtype (class Newtype, unwrap, wrap) import Data.Ordering (invert) as Ordering -import Data.Traversable (traverse) import Data.Tuple (Tuple(Tuple)) import Data.Tuple (fst, snd) as Tuple import Data.Tuple.Nested (type (/\), (/\)) -import Effect (Effect) -import JS.BigInt (BigInt) -import JS.BigInt (fromInt) as BigInt -minRequiredCollateral :: BigInt -minRequiredCollateral = BigInt.fromInt 5_000_000 +minRequiredCollateral :: Coin +minRequiredCollateral = wrap $ BigNum.fromInt 5_000_000 -- | A constant that limits the number of candidate utxos for collateral -- | selection, thus maintaining acceptable time complexity. @@ -48,12 +48,12 @@ maxCandidateUtxos = 10 -------------------------------------------------------------------------------- collateralReturnMinAdaValue - :: CoinsPerUtxoUnit -> List TransactionUnspentOutput -> Effect (Maybe BigInt) -collateralReturnMinAdaValue coinsPerUtxoUnit = - utxoMinAdaValue coinsPerUtxoUnit <<< fakeOutputWithNonAdaAssets <<< foldMap - nonAdaAsset + :: Coin -> List TransactionUnspentOutput -> Maybe BigNum +collateralReturnMinAdaValue coinsPerUtxoByte = + pure <<< utxoMinAdaValue coinsPerUtxoByte <<< fakeOutputWithMultiAssets <=< + MultiAsset.sum <<< Array.fromFoldable <<< map nonAdaAsset -type ReturnOutMinAdaValue = BigInt +type ReturnOutMinAdaValue = BigNum newtype CollateralCandidate = CollateralCandidate (List TransactionUnspentOutput /\ ReturnOutMinAdaValue) @@ -84,8 +84,8 @@ instance Ord CollateralCandidate where byNumOfInputs :: CollateralCandidate -> Int byNumOfInputs = List.length <<< Tuple.fst <<< unwrap - byAdaValue :: CollateralCandidate -> BigInt - byAdaValue = foldl consumeUtxoAdaValue zero <<< Tuple.fst <<< unwrap + byAdaValue :: CollateralCandidate -> Coin + byAdaValue = foldl consumeUtxoAdaValue Coin.zero <<< Tuple.fst <<< unwrap mkCollateralCandidate :: List TransactionUnspentOutput /\ Maybe ReturnOutMinAdaValue @@ -110,23 +110,22 @@ mkCollateralCandidate (unspentOutputs /\ returnOutMinAdaValue) = -- | utxo min ada value, we prefer the one with fewer inputs. -- | selectCollateral - :: CoinsPerUtxoUnit + :: Coin -> Int -> UtxoMap - -> Effect (Maybe (List TransactionUnspentOutput)) + -> Maybe (List TransactionUnspentOutput) selectCollateral coinsPerUtxoUnit maxCollateralInputs = -- Sort candidate utxo combinations in ascending order by utxo min ada value -- of return output, then select the first utxo combination: - map (map (Tuple.fst <<< unwrap) <<< List.head <<< List.sort) + map (Tuple.fst <<< unwrap) <<< List.head <<< List.sort -- For each candidate utxo combination calculate -- the min Ada value of the corresponding collateral return output: - <<< map (List.mapMaybe mkCollateralCandidate) - <<< traverse - (\x -> Tuple x <$> collateralReturnMinAdaValue coinsPerUtxoUnit x) + <<< List.mapMaybe mkCollateralCandidate + <<< map (\x -> Tuple x $ collateralReturnMinAdaValue coinsPerUtxoUnit x) -- Filter out all utxo combinations -- with total Ada value < `minRequiredCollateral`: <<< List.filter - (\x -> foldl consumeUtxoAdaValue zero x >= minRequiredCollateral) + (\x -> foldl consumeUtxoAdaValue (Coin.zero) x >= minRequiredCollateral) -- Get all possible non-empty utxo combinations -- with the number of utxos <= `maxCollateralInputs`: <<< combinations maxCollateralInputs @@ -158,16 +157,17 @@ asTxUnspentOutput :: TransactionInput /\ TransactionOutput -> TransactionUnspentOutput asTxUnspentOutput (input /\ output) = wrap { input, output } -adaValue :: TransactionUnspentOutput -> BigInt +adaValue :: TransactionUnspentOutput -> Coin adaValue = - Value.valueToCoin' <<< _.amount <<< unwrap <<< _.output <<< unwrap + Value.getCoin <<< _.amount <<< unwrap <<< _.output <<< unwrap -consumeUtxoAdaValue :: BigInt -> TransactionUnspentOutput -> BigInt -consumeUtxoAdaValue acc = add acc <<< adaValue +consumeUtxoAdaValue :: Coin -> TransactionUnspentOutput -> Coin +consumeUtxoAdaValue acc = unsafeFromJust "consumeUtxoAdaValue" <<< Coin.add acc + <<< adaValue -nonAdaAsset :: TransactionUnspentOutput -> NonAdaAsset +nonAdaAsset :: TransactionUnspentOutput -> MultiAsset nonAdaAsset = - Value.getNonAdaAsset <<< _.amount <<< unwrap <<< _.output <<< unwrap + Value.getMultiAsset <<< _.amount <<< unwrap <<< _.output <<< unwrap -- | Returns a list of all subsequences of the given list. subsequences :: forall (a :: Type). List a -> List (List a) diff --git a/src/Internal/BalanceTx/Constraints.purs b/src/Internal/BalanceTx/Constraints.purs index b96e255565..c71143aa87 100644 --- a/src/Internal/BalanceTx/Constraints.purs +++ b/src/Internal/BalanceTx/Constraints.purs @@ -1,8 +1,9 @@ module Ctl.Internal.BalanceTx.Constraints - ( BalanceTxConstraints(BalanceTxConstraints) - , BalanceTxConstraintsBuilder(BalanceTxConstraintsBuilder) + ( BalanceTxConstraintsBuilder + , BalancerConstraints(BalancerConstraints) + , BalancerConfig(BalancerConfig) , UtxoPredicate - , buildBalanceTxConstraints + , buildBalancerConfig , mustGenChangeOutsWithMaxTokenQuantity , mustNotSpendUtxosWhere , mustNotSpendUtxosWithOutRefs @@ -27,24 +28,11 @@ module Ctl.Internal.BalanceTx.Constraints import Prelude +import Cardano.Types (Address, TransactionInput, TransactionOutput, UtxoMap) +import Cardano.Types.OutputDatum (OutputDatum) import Ctl.Internal.BalanceTx.CoinSelection ( SelectionStrategy(SelectionStrategyOptimal) ) -import Ctl.Internal.Cardano.Types.Transaction (TransactionOutput) -import Ctl.Internal.Plutus.Conversion - ( fromPlutusAddress - , fromPlutusAddressWithNetworkTag - , toPlutusTxOutputWithRefScript - ) -import Ctl.Internal.Plutus.Types.Address - ( Address - , AddressWithNetworkTag(AddressWithNetworkTag) - ) as Plutus -import Ctl.Internal.Plutus.Types.Transaction (TransactionOutputWithRefScript) as Plutus -import Ctl.Internal.Plutus.Types.Transaction (UtxoMap) -import Ctl.Internal.Serialization.Address (Address, NetworkId) -import Ctl.Internal.Types.OutputDatum (OutputDatum) -import Ctl.Internal.Types.Transaction (TransactionInput) import Data.Array (singleton) as Array import Data.Function (applyFlipped) import Data.Lens (Lens') @@ -52,74 +40,75 @@ import Data.Lens.Iso.Newtype (_Newtype) import Data.Lens.Record (prop) import Data.Lens.Setter (appendOver, set, setJust) import Data.Map (empty) as Map -import Data.Maybe (Maybe(Just, Nothing), fromMaybe) +import Data.Maybe (Maybe(Just, Nothing)) import Data.Newtype (class Newtype, over2, unwrap, wrap) import Data.Set (Set) import Data.Set (singleton) as Set import JS.BigInt (BigInt) import Type.Proxy (Proxy(Proxy)) -newtype BalanceTxConstraints = BalanceTxConstraints +newtype BalancerConfig = BalancerConfig { additionalUtxos :: UtxoMap , collateralUtxos :: Maybe UtxoMap , maxChangeOutputTokenQuantity :: Maybe BigInt , nonSpendableInputs :: Set TransactionInput - , nonSpendableInputsPredicates :: Array (UtxoPredicate TransactionOutput) + , nonSpendableInputsPredicates :: Array UtxoPredicate , srcAddresses :: Maybe (Array Address) , changeAddress :: Maybe Address , changeDatum :: Maybe OutputDatum , selectionStrategy :: SelectionStrategy } -derive instance Newtype BalanceTxConstraints _ +derive instance Newtype BalancerConfig _ -type UtxoPredicate (output :: Type) = TransactionInput -> output -> Boolean +type UtxoPredicate = TransactionInput -> TransactionOutput -> Boolean -_additionalUtxos :: Lens' BalanceTxConstraints UtxoMap +_additionalUtxos :: Lens' BalancerConfig UtxoMap _additionalUtxos = _Newtype <<< prop (Proxy :: Proxy "additionalUtxos") -_collateralUtxos :: Lens' BalanceTxConstraints (Maybe UtxoMap) +_collateralUtxos :: Lens' BalancerConfig (Maybe UtxoMap) _collateralUtxos = _Newtype <<< prop (Proxy :: Proxy "collateralUtxos") -_maxChangeOutputTokenQuantity :: Lens' BalanceTxConstraints (Maybe BigInt) +_maxChangeOutputTokenQuantity :: Lens' BalancerConfig (Maybe BigInt) _maxChangeOutputTokenQuantity = _Newtype <<< prop (Proxy :: Proxy "maxChangeOutputTokenQuantity") -_nonSpendableInputs :: Lens' BalanceTxConstraints (Set TransactionInput) +_nonSpendableInputs :: Lens' BalancerConfig (Set TransactionInput) _nonSpendableInputs = _Newtype <<< prop (Proxy :: Proxy "nonSpendableInputs") -_nonSpendableInputsPredicates - :: Lens' BalanceTxConstraints (Array (UtxoPredicate TransactionOutput)) +_nonSpendableInputsPredicates :: Lens' BalancerConfig (Array UtxoPredicate) _nonSpendableInputsPredicates = _Newtype <<< prop (Proxy :: Proxy "nonSpendableInputsPredicates") -_srcAddresses :: Lens' BalanceTxConstraints (Maybe (Array Address)) +_srcAddresses :: Lens' BalancerConfig (Maybe (Array Address)) _srcAddresses = _Newtype <<< prop (Proxy :: Proxy "srcAddresses") -_changeAddress :: Lens' BalanceTxConstraints (Maybe Address) +_changeAddress :: Lens' BalancerConfig (Maybe Address) _changeAddress = _Newtype <<< prop (Proxy :: Proxy "changeAddress") -_changeDatum :: Lens' BalanceTxConstraints (Maybe OutputDatum) +_changeDatum :: Lens' BalancerConfig (Maybe OutputDatum) _changeDatum = _Newtype <<< prop (Proxy :: Proxy "changeDatum") -_selectionStrategy :: Lens' BalanceTxConstraints SelectionStrategy +_selectionStrategy :: Lens' BalancerConfig SelectionStrategy _selectionStrategy = _Newtype <<< prop (Proxy :: Proxy "selectionStrategy") -newtype BalanceTxConstraintsBuilder = - BalanceTxConstraintsBuilder (BalanceTxConstraints -> BalanceTxConstraints) +type BalanceTxConstraintsBuilder = BalancerConstraints + +newtype BalancerConstraints = + BalancerConstraints (BalancerConfig -> BalancerConfig) -derive instance Newtype BalanceTxConstraintsBuilder _ +derive instance Newtype BalancerConstraints _ -instance Semigroup BalanceTxConstraintsBuilder where - append = over2 BalanceTxConstraintsBuilder (>>>) +instance Semigroup BalancerConstraints where + append = over2 BalancerConstraints (>>>) -instance Monoid BalanceTxConstraintsBuilder where +instance Monoid BalancerConstraints where mempty = wrap identity -buildBalanceTxConstraints :: BalanceTxConstraintsBuilder -> BalanceTxConstraints -buildBalanceTxConstraints = applyFlipped defaultConstraints <<< unwrap +buildBalancerConfig :: BalancerConstraints -> BalancerConfig +buildBalancerConfig = applyFlipped defaultConstraints <<< unwrap where - defaultConstraints :: BalanceTxConstraints + defaultConstraints :: BalancerConfig defaultConstraints = wrap { additionalUtxos: Map.empty , collateralUtxos: Nothing @@ -139,13 +128,13 @@ buildBalanceTxConstraints = applyFlipped defaultConstraints <<< unwrap -- | NOTE: Setting `mustUseUtxosAtAddresses` or `mustUseUtxosAtAddress` -- | does NOT have any effect on which address will be used as a change address. mustSendChangeToAddress - :: Plutus.AddressWithNetworkTag -> BalanceTxConstraintsBuilder + :: Address -> BalancerConstraints mustSendChangeToAddress = - wrap <<< setJust _changeAddress <<< fromPlutusAddressWithNetworkTag + wrap <<< setJust _changeAddress -- | Tells the balancer to include the datum in each change UTxO. Useful when -- | balancing a transactions for script owned UTxOs. -mustSendChangeWithDatum :: OutputDatum -> BalanceTxConstraintsBuilder +mustSendChangeWithDatum :: OutputDatum -> BalancerConstraints mustSendChangeWithDatum = wrap <<< setJust _changeDatum @@ -156,9 +145,9 @@ mustSendChangeWithDatum = -- | NOTE: Setting `mustUseUtxosAtAddresses` or `mustUseUtxosAtAddress` -- | does NOT have any effect on which address will be used as a change address. mustUseUtxosAtAddresses - :: NetworkId -> Array Plutus.Address -> BalanceTxConstraintsBuilder -mustUseUtxosAtAddresses networkId = - wrap <<< setJust _srcAddresses <<< map (fromPlutusAddress networkId) + :: Array Address -> BalancerConstraints +mustUseUtxosAtAddresses = + wrap <<< setJust _srcAddresses -- | Tells the balancer to use UTxO's at a given address. -- | If this constraint is not set, then the default addresses owned by the @@ -167,25 +156,25 @@ mustUseUtxosAtAddresses networkId = -- | NOTE: Setting `mustUseUtxosAtAddresses` or `mustUseUtxosAtAddress` -- | does NOT have any effect on which address will be used as a change address. mustUseUtxosAtAddress - :: Plutus.AddressWithNetworkTag -> BalanceTxConstraintsBuilder -mustUseUtxosAtAddress (Plutus.AddressWithNetworkTag { address, networkId }) = - mustUseUtxosAtAddresses networkId (Array.singleton address) + :: Address -> BalancerConstraints +mustUseUtxosAtAddress address = + mustUseUtxosAtAddresses (Array.singleton address) -- | Tells the balancer to split change outputs and equipartition change `Value` -- | between them if the total change `Value` contains token quantities -- | exceeding the specified upper bound. -- | (See `Cardano.Types.Value.equipartitionValueWithTokenQuantityUpperBound`) -mustGenChangeOutsWithMaxTokenQuantity :: BigInt -> BalanceTxConstraintsBuilder +mustGenChangeOutsWithMaxTokenQuantity :: BigInt -> BalancerConstraints mustGenChangeOutsWithMaxTokenQuantity = wrap <<< setJust _maxChangeOutputTokenQuantity <<< max one -- | Tells the balancer not to spend UTxO's with the specified output references. mustNotSpendUtxosWithOutRefs - :: Set TransactionInput -> BalanceTxConstraintsBuilder + :: Set TransactionInput -> BalancerConstraints mustNotSpendUtxosWithOutRefs = wrap <<< appendOver _nonSpendableInputs -- | Tells the balancer not to spend a UTxO with the specified output reference. -mustNotSpendUtxoWithOutRef :: TransactionInput -> BalanceTxConstraintsBuilder +mustNotSpendUtxoWithOutRef :: TransactionInput -> BalancerConstraints mustNotSpendUtxoWithOutRef = mustNotSpendUtxosWithOutRefs <<< Set.singleton -- | Tells the balancer not to spend UTxO's based on the given predicate. @@ -193,27 +182,24 @@ mustNotSpendUtxoWithOutRef = mustNotSpendUtxosWithOutRefs <<< Set.singleton -- | multiple times, and utxos are tested against each predicate. The order of -- | specifying multiple `mustNotSpendUtxosWhere` constraints does NOT affect -- | the resulting set. -mustNotSpendUtxosWhere - :: UtxoPredicate Plutus.TransactionOutputWithRefScript - -> BalanceTxConstraintsBuilder -mustNotSpendUtxosWhere p = - wrap $ appendOver _nonSpendableInputsPredicates - ( Array.singleton \oref out -> - fromMaybe false $ p oref <$> toPlutusTxOutputWithRefScript out - ) +mustNotSpendUtxosWhere :: UtxoPredicate -> BalanceTxConstraintsBuilder +mustNotSpendUtxosWhere = + wrap + <<< appendOver _nonSpendableInputsPredicates + <<< Array.singleton -- | Tells the balancer to use the provided UTxO set when evaluating script -- | execution units (sets `additionalUtxoSet` of Ogmios `EvaluateTx`). -- | Note that you need to use `unspentOutputs` lookup to make these UTxO's -- | spendable by the transaction (see `Examples.TxChaining` for reference). -mustUseAdditionalUtxos :: UtxoMap -> BalanceTxConstraintsBuilder +mustUseAdditionalUtxos :: UtxoMap -> BalancerConstraints mustUseAdditionalUtxos = wrap <<< set _additionalUtxos -- | Tells the balancer to select from the provided UTxO set when choosing -- | collateral UTxOs, instead of UTxOs provided by the browser wallet. -mustUseCollateralUtxos :: UtxoMap -> BalanceTxConstraintsBuilder +mustUseCollateralUtxos :: UtxoMap -> BalancerConstraints mustUseCollateralUtxos = wrap <<< set _collateralUtxos <<< Just -- | Tells the balancer to use the given strategy for coin selection. -mustUseCoinSelectionStrategy :: SelectionStrategy -> BalanceTxConstraintsBuilder +mustUseCoinSelectionStrategy :: SelectionStrategy -> BalancerConstraints mustUseCoinSelectionStrategy = wrap <<< set _selectionStrategy diff --git a/src/Internal/BalanceTx/Error.purs b/src/Internal/BalanceTx/Error.purs index ced8db218a..a644f57f8a 100644 --- a/src/Internal/BalanceTx/Error.purs +++ b/src/Internal/BalanceTx/Error.purs @@ -16,6 +16,7 @@ module Ctl.Internal.BalanceTx.Error , ReindexRedeemersError , UtxoLookupFailedFor , UtxoMinAdaValueCalculationFailed + , NumericOverflowError ) , Expected(Expected) , printTxEvaluationFailure @@ -24,20 +25,21 @@ module Ctl.Internal.BalanceTx.Error import Prelude -import Ctl.Internal.BalanceTx.RedeemerIndex (UnindexedRedeemer) -import Ctl.Internal.Cardano.Types.Transaction - ( Redeemer(Redeemer) +import Cardano.AsCbor (encodeCbor) +import Cardano.Transaction.Edit (DetachedRedeemer) +import Cardano.Types + ( Coin + , Redeemer(Redeemer) , Transaction - , TransactionOutput - , UtxoMap , _redeemers , _witnessSet - , pprintUtxoMap ) -import Ctl.Internal.Cardano.Types.Value (pprintValue) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.TransactionInput (TransactionInput(TransactionInput)) +import Cardano.Types.TransactionOutput (TransactionOutput) +import Cardano.Types.UtxoMap (UtxoMap, pprintUtxoMap) +import Cardano.Types.Value (Value) import Ctl.Internal.Helpers (bugTrackerLink, pprintTagSet) -import Ctl.Internal.Plutus.Conversion.Value (fromPlutusValue) -import Ctl.Internal.Plutus.Types.Value (Value) import Ctl.Internal.QueryM.Ogmios ( RedeemerPointer , ScriptFailure @@ -53,18 +55,18 @@ import Ctl.Internal.QueryM.Ogmios ) , TxEvaluationFailure(UnparsedError, AdditionalUtxoOverlap, ScriptFailures) ) as Ogmios -import Ctl.Internal.Types.Natural (toBigInt) as Natural -import Ctl.Internal.Types.ProtocolParameters (CoinsPerUtxoUnit) -import Ctl.Internal.Types.Transaction (TransactionInput) +import Ctl.Internal.Types.Val (Val, pprintVal) import Data.Array (catMaybes, filter, uncons) as Array import Data.Bifunctor (bimap) +import Data.ByteArray (byteArrayToHex) import Data.Either (Either(Left, Right), either, isLeft) -import Data.Foldable (find, foldMap, foldl, length) +import Data.Foldable (find, fold, foldMap, foldl, length) import Data.FoldableWithIndex (foldMapWithIndex) import Data.Function (applyN) import Data.Generic.Rep (class Generic) import Data.Int (ceil, decimal, toNumber, toStringAs) -import Data.Lens (non, (^.)) +import Data.Lens ((^.)) +import Data.Log.Tag (TagSet, tag) import Data.Maybe (Maybe(Just, Nothing)) import Data.Newtype (class Newtype, unwrap) import Data.Show.Generic (genericShow) @@ -72,22 +74,24 @@ import Data.String (Pattern(Pattern)) import Data.String.CodePoints (length) as String import Data.String.Common (joinWith, split) as String import Data.String.Utils (padEnd) -import JS.BigInt (toString) as BigInt +import Data.UInt as UInt +import JS.BigInt as BigInt -- | Errors conditions that may possibly arise during transaction balancing data BalanceTxError - = BalanceInsufficientError Expected Actual + = BalanceInsufficientError Val Val | CouldNotConvertScriptOutputToTxInput | CouldNotGetCollateral | InsufficientCollateralUtxos UtxoMap | CouldNotGetUtxos | CollateralReturnError - | CollateralReturnMinAdaValueCalcError CoinsPerUtxoUnit TransactionOutput + | CollateralReturnMinAdaValueCalcError Coin TransactionOutput | ExUnitsEvaluationFailed Transaction Ogmios.TxEvaluationFailure | InsufficientUtxoBalanceToCoverAsset String - | ReindexRedeemersError UnindexedRedeemer - | UtxoLookupFailedFor TransactionInput + | ReindexRedeemersError DetachedRedeemer + | UtxoLookupFailedFor TransactionInput UtxoMap | UtxoMinAdaValueCalculationFailed + | NumericOverflowError (Maybe Val) derive instance Generic BalanceTxError _ @@ -97,9 +101,9 @@ instance Show BalanceTxError where explainBalanceTxError :: BalanceTxError -> String explainBalanceTxError = case _ of BalanceInsufficientError expected actual -> - "Insufficient balance. " <> prettyValue "Expected" (unwrap expected) + "Insufficient balance. " <> prettyVal "Expected" expected <> ", " - <> prettyValue "actual" (unwrap actual) + <> prettyVal "Actual" actual InsufficientCollateralUtxos utxos -> "Could not cover collateral requirements. " <> pprintTagSet "UTxOs for collateral selection:" (pprintUtxoMap utxos) @@ -118,8 +122,11 @@ explainBalanceTxError = case _ of <> show coinsPerUtxoUnit <> "\nTransaction output: " <> show txOut - ExUnitsEvaluationFailed _ _ -> - "Script evaluation failure while trying to estimate ExUnits" + ExUnitsEvaluationFailed tx err -> + "Script evaluation failure while trying to estimate ExUnits. Tx: " + <> show tx + <> ", error: " + <> show err InsufficientUtxoBalanceToCoverAsset asset -> "Insufficient UTxO balance to cover asset named " <> asset @@ -130,17 +137,26 @@ explainBalanceTxError = case _ of <> show uir <> "\nThis should be impossible: please report this as a bug to " <> bugTrackerLink - UtxoLookupFailedFor ti -> - "Could not look up UTxO for " - <> show ti - <> " from a given set of UTxOs.\n" - <> "This should be impossible: please report this as a bug to " - <> bugTrackerLink + UtxoLookupFailedFor ti mp -> + "Could not look up UTxO " + <> pprintTagSet "for" (pprintTransactionInput ti) + <> " from a " + <> pprintTagSet "given set of UTxOs:" (pprintUtxoMap mp) UtxoMinAdaValueCalculationFailed -> "Could not calculate min ADA for UTxO" + NumericOverflowError mbVal -> + "Could not compute output value due to numeric overflow. Decrease the quantity of assets. " + <> fold (prettyVal "Value:" <$> mbVal) where - prettyValue :: String -> Value -> String - prettyValue str = fromPlutusValue >>> pprintValue >>> pprintTagSet str + prettyVal :: String -> Val -> String + prettyVal str = pprintVal >>> pprintTagSet str + + pprintTransactionInput :: TransactionInput -> TagSet + pprintTransactionInput (TransactionInput { transactionId, index }) = + "TransactionInput" `tag` + ( byteArrayToHex (unwrap (encodeCbor transactionId)) <> "#" <> + show (UInt.toInt index) + ) newtype Actual = Actual Value @@ -190,10 +206,10 @@ number ary = freeze (foldl go [] ary) biggestPrefix :: String biggestPrefix = toStringAs decimal (length (Array.filter isLeft ary)) <> ". " - width :: Int + width :: Prim.Int width = ceil (toNumber (String.length biggestPrefix) / 2.0) * 2 - numberLine :: Int -> String -> String + numberLine :: Prim.Int -> String -> String numberLine i l = padEnd width (toStringAs decimal (i + 1) <> ". ") <> l indentLine :: String -> String @@ -218,15 +234,15 @@ printTxEvaluationFailure transaction e = lookupRedeemerPointer :: Ogmios.RedeemerPointer -> Maybe Redeemer lookupRedeemerPointer ptr = - flip find (transaction ^. _witnessSet <<< _redeemers <<< non []) + flip find (transaction ^. _witnessSet <<< _redeemers) $ \(Redeemer { index, tag }) -> tag == ptr.redeemerTag && index == - Natural.toBigInt ptr.redeemerIndex + (BigNum.fromInt $ UInt.toInt ptr.redeemerIndex) printRedeemerPointer :: Ogmios.RedeemerPointer -> PrettyString printRedeemerPointer ptr = line ( show ptr.redeemerTag <> ":" <> BigInt.toString - (Natural.toBigInt ptr.redeemerIndex) + (BigInt.fromInt $ UInt.toInt ptr.redeemerIndex) ) -- TODO Investigate if more details can be printed, for example minting @@ -279,8 +295,8 @@ printTxEvaluationFailure transaction e = Ogmios.IllFormedExecutionBudget (Just { memory, steps }) -> line "Ill formed execution budget:" <> bullet - ( line ("Memory: " <> BigInt.toString (Natural.toBigInt memory)) - <> line ("Steps: " <> BigInt.toString (Natural.toBigInt steps)) + ( line ("Memory: " <> BigNum.toString memory) + <> line ("Steps: " <> BigNum.toString steps) ) Ogmios.NoCostModelForLanguage languages -> line "No cost model for languages:" diff --git a/src/Internal/BalanceTx/ExUnitsAndMinFee.purs b/src/Internal/BalanceTx/ExUnitsAndMinFee.purs index c902223a8d..f82298db86 100644 --- a/src/Internal/BalanceTx/ExUnitsAndMinFee.purs +++ b/src/Internal/BalanceTx/ExUnitsAndMinFee.purs @@ -5,47 +5,42 @@ module Ctl.Internal.BalanceTx.ExUnitsAndMinFee import Prelude -import Contract.Numeric.Natural (fromInt') as Natural +import Cardano.Types + ( Coin + , CostModel + , ExUnits(ExUnits) + , Language + , PlutusData + , PlutusScript + , Redeemer(Redeemer) + , Transaction + , TransactionBody(TransactionBody) + , TransactionOutput(TransactionOutput) + , TransactionWitnessSet + , UtxoMap + , _body + , _isValid + , _witnessSet + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.ScriptRef as ScriptRef +import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.TransactionWitnessSet (_redeemers) import Control.Monad.Error.Class (throwError) import Control.Monad.Except.Trans (except) -import Ctl.Internal.BalanceTx.Constraints - ( _additionalUtxos - , _collateralUtxos - ) as Constraints +import Ctl.Internal.BalanceTx.Constraints (_additionalUtxos, _collateralUtxos) as Constraints import Ctl.Internal.BalanceTx.Error ( BalanceTxError(UtxoLookupFailedFor, ExUnitsEvaluationFailed) ) -import Ctl.Internal.BalanceTx.RedeemerIndex - ( IndexedRedeemer - , attachRedeemers - , indexedRedeemerToRedeemer - ) import Ctl.Internal.BalanceTx.Types ( BalanceTxM - , FinalizedTransaction(FinalizedTransaction) , askCostModelsForLanguages - , askNetworkId , asksConstraints , liftContract ) -import Ctl.Internal.BalanceTx.UnattachedTx (EvaluatedTx, IndexedTx) -import Ctl.Internal.Cardano.Types.ScriptRef as ScriptRef -import Ctl.Internal.Cardano.Types.Transaction - ( Costmdls - , Redeemer(Redeemer) - , Transaction - , TransactionOutput(TransactionOutput) - , TransactionWitnessSet - , TxBody(TxBody) - , UtxoMap - , _body - , _isValid - , _plutusData - , _witnessSet - ) import Ctl.Internal.Contract.MinFee (calculateMinFee) as Contract.MinFee import Ctl.Internal.Contract.Monad (getQueryHandle) -import Ctl.Internal.Plutus.Conversion (fromPlutusUtxoMap) +import Ctl.Internal.Helpers (unsafeFromJust) import Ctl.Internal.QueryM.Ogmios ( AdditionalUtxoSet , TxEvaluationFailure(AdditionalUtxoOverlap) @@ -57,17 +52,14 @@ import Ctl.Internal.TxOutput ( transactionInputToTxOutRef , transactionOutputToOgmiosTxOut ) -import Ctl.Internal.Types.Datum (Datum) -import Ctl.Internal.Types.Natural (toBigInt) as Natural -import Ctl.Internal.Types.Scripts (Language, PlutusScript) -import Ctl.Internal.Types.Transaction (TransactionInput) import Data.Array (catMaybes) import Data.Array (fromFoldable, notElem) as Array import Data.Bifunctor (bimap) import Data.Either (Either(Left, Right), note) import Data.Foldable (foldMap) +import Data.Lens ((.~)) import Data.Lens.Getter ((^.)) -import Data.Lens.Setter ((?~)) +import Data.Map (Map) import Data.Map (empty, filterKeys, fromFoldable, lookup, toUnfoldable, union) as Map import Data.Maybe (Maybe(Just, Nothing), fromMaybe) import Data.Newtype (unwrap, wrap) @@ -76,17 +68,15 @@ import Data.Set as Set import Data.Traversable (for) import Data.Tuple (snd) import Data.Tuple.Nested (type (/\), (/\)) +import Data.UInt as UInt import Effect.Aff.Class (liftAff) import Effect.Class (liftEffect) -import JS.BigInt (BigInt) evalTxExecutionUnits :: Transaction -> BalanceTxM Ogmios.TxEvaluationResult evalTxExecutionUnits tx = do - networkId <- askNetworkId - additionalUtxos <- - fromPlutusUtxoMap networkId <$> asksConstraints Constraints._additionalUtxos + additionalUtxos <- asksConstraints Constraints._additionalUtxos worker $ toOgmiosAdditionalUtxos additionalUtxos where toOgmiosAdditionalUtxos :: UtxoMap -> Ogmios.AdditionalUtxoSet @@ -117,77 +107,64 @@ evalTxExecutionUnits tx = do -- and the minimum fee, including the script fees. -- Returns a tuple consisting of updated `UnbalancedTx` and the minimum fee. evalExUnitsAndMinFee - :: IndexedTx + :: Transaction -> UtxoMap - -> BalanceTxM (EvaluatedTx /\ BigInt) -evalExUnitsAndMinFee unattachedTx allUtxos = do - -- Reattach datums and redeemers before evaluating ex units: - let attachedTx = reattachDatumsAndFakeRedeemers unattachedTx + -> BalanceTxM (Transaction /\ Coin) +evalExUnitsAndMinFee transaction allUtxos = do -- Evaluate transaction ex units: - exUnits <- evalTxExecutionUnits attachedTx + exUnits <- evalTxExecutionUnits transaction -- Set execution units received from the server: txWithExUnits <- - case updateTxExecutionUnits unattachedTx exUnits of + case updateTxExecutionUnits transaction exUnits of Just res -> pure res Nothing - | not (attachedTx ^. _isValid) -> pure $ - unattachedTx - { redeemers = indexedRedeemerToRedeemer <$> unattachedTx.redeemers - } - _ -> throwError $ ExUnitsEvaluationFailed attachedTx + | not (transaction ^. _isValid) -> pure transaction + _ -> throwError $ ExUnitsEvaluationFailed transaction (UnparsedError "Unable to extract ExUnits from Ogmios response") -- Attach datums and redeemers, set the script integrity hash: - FinalizedTransaction finalizedTx <- finalizeTransaction txWithExUnits allUtxos + finalizedTx <- finalizeTransaction txWithExUnits allUtxos -- Calculate the minimum fee for a transaction: - networkId <- askNetworkId - additionalUtxos <- - fromPlutusUtxoMap networkId - <$> asksConstraints Constraints._additionalUtxos - collateralUtxos <- - fromPlutusUtxoMap networkId <<< fromMaybe Map.empty - <$> asksConstraints Constraints._collateralUtxos + additionalUtxos <- asksConstraints Constraints._additionalUtxos + collateralUtxos <- fromMaybe Map.empty + <$> asksConstraints Constraints._collateralUtxos minFee <- liftContract $ Contract.MinFee.calculateMinFee finalizedTx (Map.union additionalUtxos collateralUtxos) - pure $ txWithExUnits /\ unwrap minFee + pure $ txWithExUnits /\ minFee -- | Attaches datums and redeemers, sets the script integrity hash, -- | for use after reindexing. finalizeTransaction - :: EvaluatedTx -> UtxoMap -> BalanceTxM FinalizedTransaction + :: Transaction -> UtxoMap -> BalanceTxM Transaction finalizeTransaction tx utxos = do let - attachedTxWithExUnits :: Transaction - attachedTxWithExUnits = - reattachDatumsAndRedeemers tx - - txBody :: TxBody - txBody = attachedTxWithExUnits ^. _body + txBody :: TransactionBody + txBody = tx ^. _body ws :: TransactionWitnessSet - ws = attachedTxWithExUnits ^. _witnessSet + ws = tx ^. _witnessSet redeemers :: Array Redeemer - redeemers = fromMaybe mempty (_.redeemers $ unwrap ws) + redeemers = (_.redeemers $ unwrap ws) - datums :: Array Datum - datums = wrap <$> fromMaybe mempty (_.plutusData $ unwrap ws) + datums :: Array PlutusData + datums = _.plutusData (unwrap ws) refPlutusScripts <- except $ getRefPlutusScripts txBody let scripts :: Array PlutusScript - scripts = fromMaybe mempty (_.plutusScripts $ unwrap ws) <> refPlutusScripts + scripts = (_.plutusScripts $ unwrap ws) <> refPlutusScripts languages :: Set Language languages = foldMap (Set.singleton <<< snd <<< unwrap) scripts - (costModels :: Costmdls) <- askCostModelsForLanguages languages + (costModels :: Map Language CostModel) <- askCostModelsForLanguages languages - liftEffect $ FinalizedTransaction <$> - setScriptDataHash costModels redeemers datums attachedTxWithExUnits + liftEffect $ setScriptDataHash costModels redeemers datums tx where - getRefPlutusScripts :: TxBody -> Either BalanceTxError (Array PlutusScript) - getRefPlutusScripts (TxBody txBody) = + getRefPlutusScripts + :: TransactionBody -> Either BalanceTxError (Array PlutusScript) + getRefPlutusScripts (TransactionBody txBody) = let spendAndRefInputs :: Array TransactionInput spendAndRefInputs = @@ -195,49 +172,37 @@ finalizeTransaction tx utxos = do in catMaybes <<< map getPlutusScript <$> for spendAndRefInputs \oref -> - note (UtxoLookupFailedFor oref) (Map.lookup oref utxos) + note (UtxoLookupFailedFor oref utxos) (Map.lookup oref utxos) getPlutusScript :: TransactionOutput -> Maybe PlutusScript getPlutusScript (TransactionOutput { scriptRef }) = ScriptRef.getPlutusScript =<< scriptRef -reattachDatumsAndFakeRedeemers :: IndexedTx -> Transaction -reattachDatumsAndFakeRedeemers - { transaction, datums, redeemers } = - reattachDatumsAndRedeemers - { transaction, datums, redeemers: indexedRedeemerToRedeemer <$> redeemers } - -reattachDatumsAndRedeemers :: EvaluatedTx -> Transaction -reattachDatumsAndRedeemers - ({ transaction, datums, redeemers }) = - let - transaction' = attachRedeemers redeemers transaction - in - transaction' - # _witnessSet <<< _plutusData ?~ map unwrap datums - updateTxExecutionUnits - :: IndexedTx + :: Transaction -> Ogmios.TxEvaluationResult - -> Maybe EvaluatedTx -updateTxExecutionUnits tx@{ redeemers } result = - getRedeemersExUnits result redeemers <#> \redeemers' -> tx - { redeemers = redeemers' } + -> Maybe Transaction +updateTxExecutionUnits tx result = + getRedeemersExUnits result (tx ^. _witnessSet <<< _redeemers) <#> + \redeemers' -> + tx # _witnessSet <<< _redeemers .~ redeemers' getRedeemersExUnits :: Ogmios.TxEvaluationResult - -> Array IndexedRedeemer + -> Array Redeemer -> Maybe (Array Redeemer) getRedeemersExUnits (Ogmios.TxEvaluationResult result) redeemers = do for redeemers \indexedRedeemer -> do { memory, steps } <- Map.lookup { redeemerTag: (unwrap indexedRedeemer).tag - , redeemerIndex: Natural.fromInt' (unwrap indexedRedeemer).index + , redeemerIndex: UInt.fromInt $ unsafeFromJust "getRedeemersExUnits" + $ BigNum.toInt + $ (unwrap indexedRedeemer).index } result - pure $ Redeemer $ (unwrap $ indexedRedeemerToRedeemer indexedRedeemer) - { exUnits = - { mem: Natural.toBigInt memory - , steps: Natural.toBigInt steps + pure $ Redeemer $ (unwrap indexedRedeemer) + { exUnits = ExUnits + { mem: memory + , steps: steps } } diff --git a/src/Internal/BalanceTx/FakeOutput.purs b/src/Internal/BalanceTx/FakeOutput.purs index 0faad4ec74..bb5e636095 100644 --- a/src/Internal/BalanceTx/FakeOutput.purs +++ b/src/Internal/BalanceTx/FakeOutput.purs @@ -1,16 +1,15 @@ module Ctl.Internal.BalanceTx.FakeOutput ( fakeOutputWithValue - , fakeOutputWithNonAdaAssets + , fakeOutputWithMultiAssets ) where import Prelude -import Ctl.Internal.Cardano.Types.Transaction - ( TransactionOutput(TransactionOutput) - ) -import Ctl.Internal.Cardano.Types.Value (NonAdaAsset, Value, mkValue) -import Ctl.Internal.Serialization.Address (addressFromBech32) as Csl -import Ctl.Internal.Types.OutputDatum (OutputDatum(NoOutputDatum)) +import Cardano.Types.Address as Address +import Cardano.Types.Coin as Coin +import Cardano.Types.MultiAsset (MultiAsset) +import Cardano.Types.TransactionOutput (TransactionOutput(TransactionOutput)) +import Cardano.Types.Value (Value, mkValue) import Data.Maybe (Maybe(Nothing), fromJust) import Partial.Unsafe (unsafePartial) @@ -19,14 +18,14 @@ fakeOutputWithValue amount = TransactionOutput { -- this fake address is taken from CSL: -- https://github.com/Emurgo/cardano-serialization-lib/blob/a58bfa583297705ffc0fb03923cecef3452a6aee/rust/src/utils.rs#L1146 - address: unsafePartial fromJust $ Csl.addressFromBech32 + address: unsafePartial fromJust $ Address.fromBech32 "addr_test1qpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5ewvxwdrt70qlcpe\ \eagscasafhffqsxy36t90ldv06wqrk2qum8x5w" , amount - , datum: NoOutputDatum + , datum: Nothing , scriptRef: Nothing } -fakeOutputWithNonAdaAssets :: NonAdaAsset -> TransactionOutput -fakeOutputWithNonAdaAssets = - fakeOutputWithValue <<< mkValue mempty +fakeOutputWithMultiAssets :: MultiAsset -> TransactionOutput +fakeOutputWithMultiAssets = + fakeOutputWithValue <<< mkValue Coin.zero diff --git a/src/Internal/BalanceTx/RedeemerIndex.purs b/src/Internal/BalanceTx/RedeemerIndex.purs deleted file mode 100644 index 3308e1db7e..0000000000 --- a/src/Internal/BalanceTx/RedeemerIndex.purs +++ /dev/null @@ -1,175 +0,0 @@ --- | Redeemer indexing refers to the process of updating redeemer's `index` --- | value based on its `RedeemerPurpose` and context from the transaction. --- | Redeemer indexing is needed, because at the Tx construction stage we --- | don't know the exact indices redeemers will have after balancing. --- | For the algorithm, see `indexof` description in --- | "Combining Scripts with Their Inputs" chapter of "A Formal Specification --- | of the Cardano Ledger integrating Plutus Core" --- | https://github.com/input-output-hk/cardano-ledger/releases/latest/download/alonzo-ledger.pdf -module Ctl.Internal.BalanceTx.RedeemerIndex - ( IndexedRedeemer(IndexedRedeemer) - , RedeemerPurpose(ForReward, ForCert, ForMint, ForSpend) - , RedeemersContext - , UnindexedRedeemer(UnindexedRedeemer) - , attachIndexedRedeemers - , attachRedeemers - , indexRedeemers - , indexedRedeemerToRedeemer - , mkRedeemersContext - , unindexedRedeemerToRedeemer - ) where - -import Prelude - -import Aeson (class EncodeAeson, encodeAeson) -import Ctl.Internal.Cardano.Types.Transaction - ( Certificate - , Redeemer(Redeemer) - , Transaction(Transaction) - , TxBody(TxBody) - , _redeemers - , _witnessSet - ) -import Ctl.Internal.Cardano.Types.Value (currencyMPSHash, unwrapNonAdaAsset) -import Ctl.Internal.Types.PlutusData (PlutusData) -import Ctl.Internal.Types.RedeemerTag (RedeemerTag(Spend, Mint, Cert, Reward)) -import Ctl.Internal.Types.RewardAddress (RewardAddress) -import Ctl.Internal.Types.Scripts (MintingPolicyHash) -import Ctl.Internal.Types.Transaction (TransactionInput) -import Data.Array (findIndex) -import Data.Either (Either, note) -import Data.Foldable (fold) -import Data.Generic.Rep (class Generic) -import Data.Lens ((.~)) -import Data.Map as Map -import Data.Maybe (Maybe(Just), fromMaybe) -import Data.Newtype (class Newtype, unwrap) -import Data.Set as Set -import Data.Show.Generic (genericShow) -import Data.Traversable (for) -import JS.BigInt as BigInt - -attachRedeemers :: Array Redeemer -> Transaction -> Transaction -attachRedeemers redeemers = _witnessSet <<< _redeemers .~ Just redeemers - -attachIndexedRedeemers :: Array IndexedRedeemer -> Transaction -> Transaction -attachIndexedRedeemers = attachRedeemers <<< map indexedRedeemerToRedeemer - --- | Redeemer that hasn't yet been indexed, that tracks its purpose info --- | that is enough to find its index given a `RedeemersContext`. -newtype UnindexedRedeemer = UnindexedRedeemer - { datum :: PlutusData - , purpose :: RedeemerPurpose - } - -derive instance Generic UnindexedRedeemer _ -derive instance Newtype UnindexedRedeemer _ -derive newtype instance Eq UnindexedRedeemer -derive newtype instance EncodeAeson UnindexedRedeemer - -instance Show UnindexedRedeemer where - show = genericShow - --- | Ignore the value that the redeemer points to -redeemerPurposeToRedeemerTag :: RedeemerPurpose -> RedeemerTag -redeemerPurposeToRedeemerTag = case _ of - ForSpend _ -> Spend - ForMint _ -> Mint - ForReward _ -> Reward - ForCert _ -> Cert - -unindexedRedeemerToRedeemer :: UnindexedRedeemer -> Redeemer -unindexedRedeemerToRedeemer (UnindexedRedeemer { datum, purpose }) = - Redeemer - { tag: redeemerPurposeToRedeemerTag purpose - , "data": datum - , index: zero - , exUnits: zero - } - --- | A redeemer with an index, but without `ExUnits` -newtype IndexedRedeemer = IndexedRedeemer - { tag :: RedeemerTag - , datum :: PlutusData - , index :: Int - } - -derive instance Generic IndexedRedeemer _ -derive instance Newtype IndexedRedeemer _ -derive newtype instance Eq IndexedRedeemer -derive newtype instance EncodeAeson IndexedRedeemer - -instance Show IndexedRedeemer where - show = genericShow - --- | Sets `ExUnits` to `zero` -indexedRedeemerToRedeemer :: IndexedRedeemer -> Redeemer -indexedRedeemerToRedeemer (IndexedRedeemer { tag, datum, index }) = - Redeemer - { tag - , index: BigInt.fromInt index - , data: datum - , exUnits: { mem: zero, steps: zero } - } - --- | Contains a value redeemer corresponds to, different for each possible --- | `RedeemerTag`. --- | Allows to uniquely compute redeemer index, given a `RedeemersContext` that --- | is valid for the transaction. -data RedeemerPurpose - = ForSpend TransactionInput - | ForMint MintingPolicyHash - | ForReward RewardAddress - | ForCert Certificate - -derive instance Generic RedeemerPurpose _ -derive instance Eq RedeemerPurpose - -instance EncodeAeson RedeemerPurpose where - encodeAeson = case _ of - ForSpend txo -> encodeAeson { tag: "ForSpend", value: encodeAeson txo } - ForMint mps -> encodeAeson { tag: "ForMint", value: encodeAeson mps } - ForReward addr -> encodeAeson { tag: "ForReward", value: encodeAeson addr } - ForCert cert -> encodeAeson { tag: "ForCert", value: encodeAeson cert } - -instance Show RedeemerPurpose where - show = genericShow - --- | Contains parts of a transaction that are important when indexing redeemers -type RedeemersContext = - { inputs :: Array TransactionInput - , mintingPolicyHashes :: Array MintingPolicyHash - , rewardAddresses :: Array RewardAddress - , certs :: Array Certificate - } - -mkRedeemersContext :: Transaction -> RedeemersContext -mkRedeemersContext - (Transaction { body: TxBody { inputs, mint, withdrawals, certs } }) = - { inputs: Set.toUnfoldable inputs - , mintingPolicyHashes: Set.toUnfoldable (Map.keys mintedAssets) <#> - currencyMPSHash - , rewardAddresses: Set.toUnfoldable $ Map.keys $ fromMaybe Map.empty - withdrawals - , certs: fold certs - } - where - mintedAssets = fromMaybe Map.empty (map unwrapNonAdaAsset $ map unwrap mint) - -indexRedeemers - :: RedeemersContext - -> Array UnindexedRedeemer - -> Either UnindexedRedeemer (Array IndexedRedeemer) -indexRedeemers ctx redeemers = do - for redeemers \redeemer -> note redeemer $ indexRedeemer ctx redeemer - -indexRedeemer :: RedeemersContext -> UnindexedRedeemer -> Maybe IndexedRedeemer -indexRedeemer ctx (UnindexedRedeemer { purpose, datum }) = case purpose of - ForSpend input -> findIndex (eq input) ctx.inputs <#> \index -> - IndexedRedeemer { tag: Spend, index, datum } - ForMint mps -> findIndex (eq mps) ctx.mintingPolicyHashes <#> \index -> - IndexedRedeemer { tag: Mint, index, datum } - ForReward addr -> findIndex (eq addr) ctx.rewardAddresses <#> \index -> - IndexedRedeemer { tag: Reward, index, datum } - ForCert cert -> findIndex (eq cert) ctx.certs <#> \index -> - IndexedRedeemer { tag: Cert, index, datum } diff --git a/src/Internal/BalanceTx/Sync.purs b/src/Internal/BalanceTx/Sync.purs index 7895b6e39b..4e30075f6b 100644 --- a/src/Internal/BalanceTx/Sync.purs +++ b/src/Internal/BalanceTx/Sync.purs @@ -12,16 +12,20 @@ module Ctl.Internal.BalanceTx.Sync import Prelude +import Cardano.Serialization.Lib (toBytes) +import Cardano.Types + ( TransactionHash + , TransactionInput + , TransactionOutput + , TransactionUnspentOutput + , UtxoMap + ) +import Cardano.Types.Address (Address) import Contract.Log (logError', logTrace', logWarn') import Contract.Monad (Contract, liftedE) import Control.Monad.Reader (local) import Control.Monad.Reader.Class (asks) import Control.Parallel (parOneOf, parTraverse, parallel, sequential) -import Ctl.Internal.Cardano.Types.Transaction (UtxoMap) -import Ctl.Internal.Cardano.Types.Transaction as Cardano -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput - ) import Ctl.Internal.Contract.Monad ( ContractSynchronizationParams , getQueryHandle @@ -34,12 +38,10 @@ import Ctl.Internal.Contract.Wallet , getWalletUtxos ) import Ctl.Internal.Helpers (liftEither, liftedM) -import Ctl.Internal.Serialization.Address (Address) -import Ctl.Internal.Types.ByteArray (byteArrayToHex) -import Ctl.Internal.Types.Transaction (TransactionHash, TransactionInput) import Ctl.Internal.Wallet (Wallet(GenericCip30)) import Data.Array as Array import Data.Bifunctor (bimap) +import Data.ByteArray (byteArrayToHex) import Data.Map as Map import Data.Maybe (Maybe(Just), fromMaybe, isJust, maybe) import Data.Monoid (guard) @@ -147,7 +149,7 @@ syncWalletWithTransaction txHash = whenM isCip30Wallet do logTrace' $ "syncWalletWithTransaction: waiting for wallet state synchronization " <> "with the query layer, querying for Tx: " - <> byteArrayToHex (unwrap txHash) + <> byteArrayToHex (toBytes $ unwrap txHash) liftAff (delay delayMs) sync -- Collect all the addresses controlled by the wallet @@ -245,7 +247,7 @@ disabledSynchronizationParams = } -- | A version without plutus conversion for internal use. -getUtxo' :: TransactionInput -> Contract (Maybe Cardano.TransactionOutput) +getUtxo' :: TransactionInput -> Contract (Maybe TransactionOutput) getUtxo' oref = do queryHandle <- getQueryHandle liftedE $ liftAff $ queryHandle.getUtxoByOref oref diff --git a/src/Internal/BalanceTx/Types.purs b/src/Internal/BalanceTx/Types.purs index 10cfa2a599..2ce82ab871 100644 --- a/src/Internal/BalanceTx/Types.purs +++ b/src/Internal/BalanceTx/Types.purs @@ -1,47 +1,41 @@ module Ctl.Internal.BalanceTx.Types ( BalanceTxM , BalanceTxMContext - , FinalizedTransaction(FinalizedTransaction) , askCoinsPerUtxoUnit , askCostModelsForLanguages , askNetworkId , asksConstraints , liftEitherContract , liftContract - , withBalanceTxConstraints + , withBalancerConstraints ) where import Prelude +import Cardano.Types (Address, Coin, CostModel, Language, NetworkId) import Control.Monad.Except.Trans (ExceptT(ExceptT)) import Control.Monad.Reader.Class (asks) import Control.Monad.Reader.Trans (ReaderT, runReaderT) import Control.Monad.Trans.Class (lift) import Ctl.Internal.BalanceTx.Constraints - ( BalanceTxConstraints - , BalanceTxConstraintsBuilder + ( BalancerConfig + , BalancerConstraints + , buildBalancerConfig ) -import Ctl.Internal.BalanceTx.Constraints (buildBalanceTxConstraints) as Constraints import Ctl.Internal.BalanceTx.Error (BalanceTxError) -import Ctl.Internal.Cardano.Types.Transaction (Costmdls(Costmdls), Transaction) import Ctl.Internal.Contract.Monad (Contract, ContractEnv) import Ctl.Internal.Contract.Wallet (getWalletAddresses) -import Ctl.Internal.Serialization.Address (NetworkId) -import Ctl.Internal.Serialization.Address as Csl -import Ctl.Internal.Types.ProtocolParameters (CoinsPerUtxoUnit) -import Ctl.Internal.Types.Scripts (Language) import Data.Either (Either) -import Data.Generic.Rep (class Generic) import Data.Lens (Lens') import Data.Lens.Getter (view) +import Data.Map (Map) import Data.Map (filterKeys) as Map -import Data.Newtype (class Newtype, over, unwrap) +import Data.Newtype (unwrap) import Data.Set (Set) import Data.Set (fromFoldable, member) as Set -import Data.Show.Generic (genericShow) type BalanceTxMContext = - { constraints :: BalanceTxConstraints, ownAddresses :: Set Csl.Address } + { constraints :: BalancerConfig, ownAddresses :: Set Address } type BalanceTxM (a :: Type) = ExceptT BalanceTxError (ReaderT BalanceTxMContext Contract) a @@ -54,44 +48,35 @@ liftEitherContract liftEitherContract = ExceptT <<< lift asksConstraints - :: forall (a :: Type). Lens' BalanceTxConstraints a -> BalanceTxM a + :: forall (a :: Type). Lens' BalancerConfig a -> BalanceTxM a asksConstraints l = asks (view l <<< _.constraints) asksContractEnv :: forall (a :: Type). (ContractEnv -> a) -> BalanceTxM a asksContractEnv = lift <<< lift <<< asks -askCoinsPerUtxoUnit :: BalanceTxM CoinsPerUtxoUnit +askCoinsPerUtxoUnit :: BalanceTxM Coin askCoinsPerUtxoUnit = asksContractEnv - (_.coinsPerUtxoUnit <<< unwrap <<< _.pparams <<< _.ledgerConstants) + (_.coinsPerUtxoByte <<< unwrap <<< _.pparams <<< _.ledgerConstants) askNetworkId :: BalanceTxM NetworkId askNetworkId = asksContractEnv _.networkId -withBalanceTxConstraints +withBalancerConstraints :: forall (a :: Type) - . BalanceTxConstraintsBuilder + . BalancerConstraints -> ReaderT BalanceTxMContext Contract a -> Contract a -withBalanceTxConstraints constraintsBuilder m = do +withBalancerConstraints constraintsBuilder m = do -- we can ignore failures due to reward addresses because reward addresses -- do not receive transaction outputs from dApps ownAddresses <- Set.fromFoldable <$> getWalletAddresses flip runReaderT { constraints, ownAddresses } m where - constraints :: BalanceTxConstraints - constraints = Constraints.buildBalanceTxConstraints constraintsBuilder + constraints :: BalancerConfig + constraints = buildBalancerConfig constraintsBuilder -askCostModelsForLanguages :: Set Language -> BalanceTxM Costmdls +askCostModelsForLanguages :: Set Language -> BalanceTxM (Map Language CostModel) askCostModelsForLanguages languages = asksContractEnv (_.costModels <<< unwrap <<< _.pparams <<< _.ledgerConstants) - <#> over Costmdls (Map.filterKeys (flip Set.member languages)) - -newtype FinalizedTransaction = FinalizedTransaction Transaction - -derive instance Generic FinalizedTransaction _ -derive instance Newtype FinalizedTransaction _ -derive newtype instance Eq FinalizedTransaction - -instance Show FinalizedTransaction where - show = genericShow + <#> Map.filterKeys (flip Set.member languages) diff --git a/src/Internal/BalanceTx/UnattachedTx.purs b/src/Internal/BalanceTx/UnattachedTx.purs deleted file mode 100644 index 49f1345cd1..0000000000 --- a/src/Internal/BalanceTx/UnattachedTx.purs +++ /dev/null @@ -1,52 +0,0 @@ -module Ctl.Internal.BalanceTx.UnattachedTx - ( UnattachedTx - , UnindexedTx - , IndexedTx - , EvaluatedTx - , indexTx - , _transaction - ) where - -import Prelude - -import Ctl.Internal.BalanceTx.RedeemerIndex - ( IndexedRedeemer - , UnindexedRedeemer - , attachIndexedRedeemers - , indexRedeemers - , mkRedeemersContext - ) -import Ctl.Internal.Cardano.Types.Transaction (Redeemer, Transaction) -import Ctl.Internal.Types.Datum (Datum) -import Data.Either (Either) -import Data.Lens (Lens') -import Data.Lens.Record (prop) -import Type.Proxy (Proxy(Proxy)) - -type UnattachedTx redeemer = - { transaction :: Transaction - , datums :: Array Datum - , redeemers :: Array redeemer - } - --- | A Tx with unindexed redeemers -type UnindexedTx = UnattachedTx UnindexedRedeemer - --- | A Tx with indexed, but not yet evaluated redeemers -type IndexedTx = UnattachedTx IndexedRedeemer - --- | A Tx with fully indexed and evaluated redeemers -type EvaluatedTx = UnattachedTx Redeemer - -indexTx :: UnindexedTx -> Either UnindexedRedeemer IndexedTx -indexTx { transaction, datums, redeemers } = do - redeemers' <- indexRedeemers (mkRedeemersContext transaction) redeemers - pure - { transaction: attachIndexedRedeemers redeemers' transaction - , datums - , redeemers: redeemers' - } - -_transaction - :: forall (redeemer :: Type). Lens' (UnattachedTx redeemer) Transaction -_transaction = prop (Proxy :: Proxy "transaction") diff --git a/src/Internal/BalanceTx/UtxoMinAda.js b/src/Internal/BalanceTx/UtxoMinAda.js deleted file mode 100644 index 5b6910c849..0000000000 --- a/src/Internal/BalanceTx/UtxoMinAda.js +++ /dev/null @@ -1,26 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function minAdaForOutput(maybe) { - return txOutput => dataCost => { - try { - return maybe.just(lib.min_ada_for_output(txOutput, dataCost)); - } catch (_) { - return maybe.nothing; - } - }; -} - -export function newCoinsPerWord(n) { - return lib.DataCost.new_coins_per_word(n); -} - -export function newCoinsPerByte(n) { - return lib.DataCost.new_coins_per_byte(n); -} diff --git a/src/Internal/BalanceTx/UtxoMinAda.purs b/src/Internal/BalanceTx/UtxoMinAda.purs index e1d37dba34..9937c226d9 100644 --- a/src/Internal/BalanceTx/UtxoMinAda.purs +++ b/src/Internal/BalanceTx/UtxoMinAda.purs @@ -5,53 +5,21 @@ module Ctl.Internal.BalanceTx.UtxoMinAda import Prelude -import Control.Monad.Error.Class (liftMaybe) +import Cardano.Types.BigNum (BigNum) +import Cardano.Types.BigNum (maxValue) as BigNum +import Cardano.Types.Coin (Coin) +import Cardano.Types.TransactionOutput (TransactionOutput, minAdaForOutput) +import Cardano.Types.Value (lovelaceValueOf) import Ctl.Internal.BalanceTx.FakeOutput (fakeOutputWithValue) -import Ctl.Internal.Cardano.Types.Transaction (TransactionOutput) -import Ctl.Internal.Cardano.Types.Value (Coin(Coin), lovelaceValueOf) -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Ctl.Internal.Serialization (convertTxOutput) -import Ctl.Internal.Serialization.Types (DataCost) -import Ctl.Internal.Serialization.Types (TransactionOutput) as Csl -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum - ( fromBigInt - , maxValue - , toBigInt - ) as BigNum -import Ctl.Internal.Types.ProtocolParameters - ( CoinsPerUtxoUnit(CoinsPerUtxoWord, CoinsPerUtxoByte) - ) -import Data.Maybe (Maybe, fromJust) -import Effect (Effect) -import Effect.Exception (error) -import JS.BigInt (BigInt) -import Partial.Unsafe (unsafePartial) - -foreign import minAdaForOutput - :: MaybeFfiHelper -> Csl.TransactionOutput -> DataCost -> Maybe BigNum - -foreign import newCoinsPerWord :: BigNum -> DataCost - -foreign import newCoinsPerByte :: BigNum -> DataCost +import Data.Newtype (unwrap) utxoMinAdaValue - :: CoinsPerUtxoUnit -> TransactionOutput -> Effect (Maybe BigInt) -utxoMinAdaValue coinsPerUtxoUnit txOutput = do - cslTxOutput <- convertTxOutput txOutput - dataCost <- case coinsPerUtxoUnit of - CoinsPerUtxoByte (Coin n) -> do - newCoinsPerByte <$> liftMaybe (error "Failed to convert CoinsPerUtxoByte") - (BigNum.fromBigInt n) - CoinsPerUtxoWord (Coin n) -> do - newCoinsPerWord <$> liftMaybe (error "Failed to convert CoinsPerUtxoWord") - (BigNum.fromBigInt n) - pure $ minAdaForOutput maybeFfiHelper cslTxOutput dataCost - -- useful spy: BigNum.toBigInt >>= (pure <<< spy "utxoMinAdaValue") - <#> BigNum.toBigInt + :: Coin -> TransactionOutput -> BigNum +utxoMinAdaValue coinsPerUtxoByte txOutput = + unwrap $ minAdaForOutput txOutput (unwrap coinsPerUtxoByte) -adaOnlyUtxoMinAdaValue :: CoinsPerUtxoUnit -> Effect BigInt -adaOnlyUtxoMinAdaValue coinsPerUtxoUnit = - map (unsafePartial fromJust) <<< utxoMinAdaValue coinsPerUtxoUnit <<< +adaOnlyUtxoMinAdaValue :: Coin -> BigNum +adaOnlyUtxoMinAdaValue coinsPerUtxoByte = + utxoMinAdaValue coinsPerUtxoByte <<< fakeOutputWithValue - $ lovelaceValueOf (BigNum.toBigInt BigNum.maxValue) + $ lovelaceValueOf BigNum.maxValue diff --git a/src/Internal/Cardano/TextEnvelope.purs b/src/Internal/Cardano/TextEnvelope.purs index 9cf47bb165..0e291cff8f 100644 --- a/src/Internal/Cardano/TextEnvelope.purs +++ b/src/Internal/Cardano/TextEnvelope.purs @@ -3,39 +3,35 @@ module Ctl.Internal.Cardano.TextEnvelope , TextEnvelopeType ( PlutusScriptV1 , PlutusScriptV2 + , PlutusScriptV3 , PaymentSigningKeyShelleyed25519 , StakeSigningKeyShelleyed25519 , Other ) , decodeTextEnvelope - , plutusScriptV1FromEnvelope - , plutusScriptV2FromEnvelope + , plutusScriptFromEnvelope ) where import Prelude -import Aeson - ( class DecodeAeson - , decodeAeson - , parseJsonStringToAeson - ) -import Ctl.Internal.Types.ByteArray (ByteArray, hexToByteArray) +import Aeson (class DecodeAeson, decodeAeson, parseJsonStringToAeson) +import Cardano.Types.Language (Language(PlutusV3)) +import Cardano.Types.PlutusScript (PlutusScript) +import Cardano.Types.PlutusScript as PlutusScript import Ctl.Internal.Types.Cbor (toByteArray) -import Ctl.Internal.Types.Scripts - ( PlutusScript - , plutusV1Script - , plutusV2Script - ) +import Data.ByteArray (ByteArray, hexToByteArray) import Data.Either (hush) -import Data.Maybe (Maybe(Nothing)) -import Data.Newtype (class Newtype, wrap) +import Data.Maybe (Maybe(Just, Nothing)) +import Data.Newtype (class Newtype, unwrap, wrap) +import Data.Tuple.Nested ((/\)) data TextEnvelopeType = PlutusScriptV1 | PlutusScriptV2 + | PlutusScriptV3 | PaymentSigningKeyShelleyed25519 | StakeSigningKeyShelleyed25519 - | Other String -- TextEnvelope we can parse from String, but cannot use now + | Other String derive instance Eq TextEnvelopeType @@ -43,6 +39,7 @@ instance Show TextEnvelopeType where show = case _ of PlutusScriptV1 -> "PlutusScriptV1" PlutusScriptV2 -> "PlutusScriptV2" + PlutusScriptV3 -> "PlutusScriptV3" PaymentSigningKeyShelleyed25519 -> "PaymentSigningKeyShelley_ed25519" StakeSigningKeyShelleyed25519 -> "StakeSigningKeyShelley_ed25519" Other other -> other @@ -52,6 +49,7 @@ instance DecodeAeson TextEnvelopeType where decodeAeson aeson >>= case _ of "PlutusScriptV1" -> pure PlutusScriptV1 "PlutusScriptV2" -> pure PlutusScriptV2 + "PlutusScriptV3" -> pure PlutusScriptV3 "PaymentSigningKeyShelley_ed25519" -> pure PaymentSigningKeyShelleyed25519 "StakeSigningKeyShelley_ed25519" -> pure @@ -88,22 +86,16 @@ decodeTextEnvelope json = do ba <- decodeCborHexToBytes cborHex pure $ wrap { type_, description, bytes: ba } -plutusScriptFromEnvelope - :: TextEnvelopeType - -> (ByteArray -> PlutusScript) - -> TextEnvelope - -> Maybe PlutusScript -plutusScriptFromEnvelope type_ bytesToScript (TextEnvelope envelope) = do - -- Check TextEnvelope type match to desirable - unless (envelope.type_ == type_) Nothing - pure $ bytesToScript envelope.bytes - -plutusScriptV1FromEnvelope - :: TextEnvelope -> Maybe PlutusScript -plutusScriptV1FromEnvelope envelope = do - plutusScriptFromEnvelope PlutusScriptV1 plutusV1Script envelope - -plutusScriptV2FromEnvelope - :: TextEnvelope -> Maybe PlutusScript -plutusScriptV2FromEnvelope envelope = - plutusScriptFromEnvelope PlutusScriptV2 plutusV2Script envelope +plutusScriptFromEnvelope :: TextEnvelope -> Maybe PlutusScript +plutusScriptFromEnvelope (TextEnvelope envelope) = + case envelope.type_ of + PlutusScriptV1 -> + Just $ PlutusScript.plutusV1Script envelopeBytes + PlutusScriptV2 -> + Just $ PlutusScript.plutusV2Script envelopeBytes + PlutusScriptV3 -> + -- TODO: add plutusV3Script to Cardano.Types.PlutusScript + Just $ wrap $ unwrap envelopeBytes /\ PlutusV3 + _ -> Nothing + where + envelopeBytes = wrap envelope.bytes diff --git a/src/Internal/Cardano/Types/NativeScript.purs b/src/Internal/Cardano/Types/NativeScript.purs deleted file mode 100644 index 8014cf5443..0000000000 --- a/src/Internal/Cardano/Types/NativeScript.purs +++ /dev/null @@ -1,123 +0,0 @@ -module Ctl.Internal.Cardano.Types.NativeScript - ( NativeScript - ( ScriptPubkey - , ScriptAll - , ScriptAny - , ScriptNOfK - , TimelockStart - , TimelockExpiry - ) - , pprintNativeScript - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , caseAesonObject - , getField - , (.:) - ) -import Ctl.Internal.Helpers (contentsProp, encodeTagged', tagProp) -import Ctl.Internal.Metadata.Helpers (errExpectedObject) -import Ctl.Internal.Serialization.Address (Slot) -import Ctl.Internal.Serialization.Hash - ( Ed25519KeyHash - , ed25519KeyHashFromBytes - , ed25519KeyHashToBytes - ) -import Ctl.Internal.Types.BigNum (fromString) -import Ctl.Internal.Types.BigNum as BigNum -import Ctl.Internal.Types.ByteArray (hexToByteArrayUnsafe) -import Ctl.Internal.Types.RawBytes (rawBytesToHex) -import Data.Array.NonEmpty (fromFoldable) -import Data.Either (Either(Left)) -import Data.Generic.Rep (class Generic) -import Data.Log.Tag (TagSet, tag, tagSetTag) -import Data.Log.Tag as TagSet -import Data.Maybe (fromJust) -import Data.Newtype (unwrap, wrap) -import Data.Show.Generic (genericShow) -import Partial.Unsafe (unsafePartial) -import Test.QuickCheck (class Arbitrary) -import Test.QuickCheck.Arbitrary (arbitrary) -import Test.QuickCheck.Gen (Gen, oneOf, resize, sized, suchThat) - -data NativeScript - = ScriptPubkey Ed25519KeyHash - | ScriptAll (Array NativeScript) - | ScriptAny (Array NativeScript) - | ScriptNOfK Int (Array NativeScript) - | TimelockStart Slot -- spend after - | TimelockExpiry Slot -- spend before - -derive instance Eq NativeScript -derive instance Generic NativeScript _ - -instance Show NativeScript where - show x = genericShow x - -instance Arbitrary NativeScript where - arbitrary = oneOf $ unsafePartial $ fromJust $ fromFoldable - [ ScriptPubkey <$> (pure pk) - , ScriptAll <$> sized (\i -> resize (i `div` 2) arbitrary) - , ScriptAny <$> sized (\i -> resize (i `div` 2) arbitrary) - , ScriptNOfK - <$> suchThat (arbitrary :: Gen Int) (_ >= 0) - <*> sized (\i -> resize (i `div` 2) arbitrary) - , TimelockStart <$> map - (wrap <<< (unsafePartial $ fromJust <<< fromString <<< show)) - (suchThat (arbitrary :: Gen Int) (_ > 0)) - , TimelockExpiry <$> map - (wrap <<< (unsafePartial $ fromJust <<< fromString <<< show)) - (suchThat (arbitrary :: Gen Int) (_ > 0)) - ] - where - pk :: Ed25519KeyHash - pk = unsafePartial $ fromJust $ ed25519KeyHashFromBytes $ - hexToByteArrayUnsafe - "1c12f03c1ef2e935acc35ec2e6f96c650fd3bfba3e96550504d53361" - -instance DecodeAeson NativeScript where - decodeAeson = caseAesonObject errExpectedObject $ \obj -> do - tag <- obj .: tagProp - let - aesonContents - :: forall (a :: Type). DecodeAeson a => Either JsonDecodeError a - aesonContents = obj .: contentsProp - case tag of - "ScriptPubkey" -> ScriptPubkey <$> aesonContents - "ScriptAll" -> ScriptAll <$> aesonContents - "ScriptAny" -> ScriptAny <$> aesonContents - "TimelockStart" -> TimelockStart <$> aesonContents - "TimelockExpiry" -> TimelockExpiry <$> aesonContents - "ScriptNOfK" -> ScriptNOfK - <$> (flip getField "n" =<< aesonContents) - <*> (flip getField "nativeScripts" =<< aesonContents) - - _ -> Left $ TypeMismatch ("Unknown tag: " <> tag) - -instance EncodeAeson NativeScript where - encodeAeson = case _ of - ScriptPubkey r -> encodeTagged' "ScriptPubkey" r - ScriptAll r -> encodeTagged' "ScriptAll" r - ScriptAny r -> encodeTagged' "ScriptAny" r - ScriptNOfK n nativeScripts -> encodeTagged' "ScriptNOfK" - { n, nativeScripts } - TimelockStart r -> encodeTagged' "TimelockStart" r - TimelockExpiry r -> encodeTagged' "TimelockExpiry" r - -pprintNativeScript :: NativeScript -> TagSet -pprintNativeScript = case _ of - ScriptPubkey kh -> TagSet.fromArray - [ "PubKey" `tag` rawBytesToHex (ed25519KeyHashToBytes kh) ] - ScriptAll scripts -> "All of" `tagSetTag` TagSet.fromArray - (pprintNativeScript <$> scripts) - ScriptAny scripts -> "Any of" `tagSetTag` TagSet.fromArray - (pprintNativeScript <$> scripts) - ScriptNOfK n scripts -> ("At least " <> show n <> " of ") - `tagSetTag` TagSet.fromArray (pprintNativeScript <$> scripts) - TimelockStart slot -> "Timelock start" `tag` BigNum.toString (unwrap slot) - TimelockExpiry slot -> "Timelock expiry" `tag` BigNum.toString (unwrap slot) diff --git a/src/Internal/Cardano/Types/ScriptRef.purs b/src/Internal/Cardano/Types/ScriptRef.purs deleted file mode 100644 index 31a757f6fe..0000000000 --- a/src/Internal/Cardano/Types/ScriptRef.purs +++ /dev/null @@ -1,69 +0,0 @@ -module Ctl.Internal.Cardano.Types.ScriptRef - ( ScriptRef(NativeScriptRef, PlutusScriptRef) - , scriptRefFromMintingPolicy - , getNativeScript - , getPlutusScript - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(UnexpectedValue, TypeMismatch) - , caseAesonObject - , fromString - , toStringifiedNumbersJson - , (.:) - ) -import Ctl.Internal.Cardano.Types.NativeScript (NativeScript) -import Ctl.Internal.Helpers (encodeTagged') -import Ctl.Internal.Types.Scripts - ( MintingPolicy(PlutusMintingPolicy, NativeMintingPolicy) - , PlutusScript - ) -import Data.Either (Either(Left)) -import Data.Generic.Rep (class Generic) -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Show.Generic (genericShow) - -data ScriptRef = NativeScriptRef NativeScript | PlutusScriptRef PlutusScript - -scriptRefFromMintingPolicy :: MintingPolicy -> ScriptRef -scriptRefFromMintingPolicy = case _ of - PlutusMintingPolicy ps -> PlutusScriptRef ps - NativeMintingPolicy ns -> NativeScriptRef ns - -derive instance Eq ScriptRef -derive instance Generic ScriptRef _ - -instance Show ScriptRef where - show = genericShow - -instance EncodeAeson ScriptRef where - encodeAeson = case _ of - NativeScriptRef r -> encodeTagged' "NativeScriptRef" r - PlutusScriptRef r -> encodeTagged' "PlutusScriptRef" r - -instance DecodeAeson ScriptRef where - decodeAeson = caseAesonObject (Left $ TypeMismatch "Expected object") $ - \obj -> do - tag <- obj .: "tag" - case tag of - "NativeScriptRef" -> do - nativeScript <- obj .: "contents" - pure $ NativeScriptRef nativeScript - "PlutusScriptRef" -> do - plutusScript <- obj .: "contents" - pure $ PlutusScriptRef plutusScript - tagValue -> do - Left $ UnexpectedValue $ toStringifiedNumbersJson $ fromString - tagValue - -getNativeScript :: ScriptRef -> Maybe NativeScript -getNativeScript (NativeScriptRef nativeScript) = Just nativeScript -getNativeScript _ = Nothing - -getPlutusScript :: ScriptRef -> Maybe PlutusScript -getPlutusScript (PlutusScriptRef plutusScript) = Just plutusScript -getPlutusScript _ = Nothing diff --git a/src/Internal/Cardano/Types/Transaction.purs b/src/Internal/Cardano/Types/Transaction.purs deleted file mode 100644 index 3aebed07a5..0000000000 --- a/src/Internal/Cardano/Types/Transaction.purs +++ /dev/null @@ -1,1007 +0,0 @@ -module Ctl.Internal.Cardano.Types.Transaction - ( AuxiliaryData(AuxiliaryData) - , AuxiliaryDataHash(AuxiliaryDataHash) - , BootstrapWitness - , Certificate - ( StakeRegistration - , StakeDeregistration - , StakeDelegation - , PoolRegistration - , PoolRetirement - , GenesisKeyDelegation - , MoveInstantaneousRewardsCert - ) - , CostModel(CostModel) - , Costmdls(Costmdls) - , Ed25519Signature - , mkEd25519Signature - , mkFromCslEd25519Signature - , convertEd25519Signature - , Epoch(Epoch) - , ExUnitPrices - , ExUnits - , GenesisDelegateHash(GenesisDelegateHash) - , GenesisHash(GenesisHash) - , Ipv4(Ipv4) - , Ipv6(Ipv6) - , MIRToStakeCredentials(MIRToStakeCredentials) - , Mint(Mint) - , MoveInstantaneousReward(ToOtherPot, ToStakeCreds) - , Nonce(IdentityNonce, HashNonce) - , PoolMetadata(PoolMetadata) - , PoolMetadataHash(PoolMetadataHash) - , PoolPubKeyHash(PoolPubKeyHash) - , mkPoolPubKeyHash - , poolPubKeyHashToBech32 - , ProposedProtocolParameterUpdates(ProposedProtocolParameterUpdates) - , ProtocolParamUpdate - , ProtocolVersion - , PublicKey - , mkPublicKey - , mkFromCslPubKey - , convertPubKey - , Redeemer(Redeemer) - , Relay(SingleHostAddr, SingleHostName, MultiHostName) - , RequiredSigner(RequiredSigner) - , ScriptDataHash(ScriptDataHash) - , SubCoin - , Transaction(Transaction) - , TransactionOutput(TransactionOutput) - , PoolRegistrationParams - , TransactionWitnessSet(TransactionWitnessSet) - , TxBody(TxBody) - , URL(URL) - , UnitInterval - , Update - , UtxoMap - , pprintUtxoMap - , Vkey(Vkey) - , Vkeywitness(Vkeywitness) - , _auxiliaryData - , _auxiliaryDataHash - , _body - , _bootstraps - , _certs - , _collateral - , _collateralReturn - , _fee - , _inputs - , _isValid - , _mint - , _nativeScripts - , _networkId - , _outputs - , _plutusData - , _plutusScripts - , _redeemers - , _referenceInputs - , _requiredSigners - , _scriptDataHash - , _totalCollateral - , _ttl - , _update - , _validityStartInterval - , _vkeys - , _withdrawals - , _witnessSet - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , caseAesonString - , decodeAeson - , encodeAeson - , finiteNumber - ) -import Control.Alternative ((<|>)) -import Control.Apply (lift2) -import Ctl.Internal.Cardano.Types.NativeScript (NativeScript) -import Ctl.Internal.Cardano.Types.ScriptRef (ScriptRef) -import Ctl.Internal.Cardano.Types.Value (Coin, NonAdaAsset, Value, pprintValue) -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.Deserialization.Keys - ( ed25519SignatureFromBech32 - , publicKeyFromBech32 - ) -import Ctl.Internal.FromData (class FromData, fromData) -import Ctl.Internal.Helpers (appendMap, encodeMap, encodeTagged', (), (<<>>)) -import Ctl.Internal.Serialization.Address - ( Address - , NetworkId - , Slot(Slot) - , StakeCredential - , addressBech32 - ) -import Ctl.Internal.Serialization.Hash - ( Ed25519KeyHash - , ed25519KeyHashFromBech32 - , ed25519KeyHashToBech32 - , ed25519KeyHashToBech32Unsafe - ) -import Ctl.Internal.Serialization.Keys - ( bech32FromEd25519Signature - , bech32FromPublicKey - , bytesFromPublicKey - ) -import Ctl.Internal.Serialization.ToBytes (toBytes) -import Ctl.Internal.Serialization.Types (Ed25519Signature, PublicKey) as Serialization -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.ByteArray (ByteArray, byteArrayToHex) -import Ctl.Internal.Types.Int as Int -import Ctl.Internal.Types.OutputDatum - ( OutputDatum(NoOutputDatum, OutputDatumHash, OutputDatum) - ) -import Ctl.Internal.Types.PlutusData (PlutusData, pprintPlutusData) -import Ctl.Internal.Types.PubKeyHash (PaymentPubKeyHash, PubKeyHash(PubKeyHash)) -import Ctl.Internal.Types.RawBytes (RawBytes) -import Ctl.Internal.Types.RedeemerTag (RedeemerTag) -import Ctl.Internal.Types.RewardAddress (RewardAddress) -import Ctl.Internal.Types.Scripts (Language, PlutusScript) -import Ctl.Internal.Types.Transaction (TransactionInput(TransactionInput)) -import Ctl.Internal.Types.TransactionMetadata (GeneralTransactionMetadata) -import Ctl.Internal.Types.VRFKeyHash (VRFKeyHash) -import Data.Array (union) -import Data.Either (Either(Left), note) -import Data.Generic.Rep (class Generic) -import Data.Lens (lens') -import Data.Lens.Iso.Newtype (_Newtype) -import Data.Lens.Record (prop) -import Data.Lens.Types (Lens') -import Data.Log.Tag (TagSet, tag, tagSetTag) -import Data.Log.Tag as TagSet -import Data.Map (Map) -import Data.Map as Map -import Data.Maybe (Maybe(Just, Nothing), fromJust) -import Data.Monoid (guard) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Set (Set) -import Data.Set (union) as Set -import Data.Show.Generic (genericShow) -import Data.String.Utils (startsWith) -import Data.Tuple (Tuple(Tuple)) -import Data.Tuple.Nested (type (/\), (/\)) -import Data.UInt (UInt) -import Data.UInt as UInt -import JS.BigInt (BigInt) -import Partial.Unsafe (unsafePartial) -import Type.Proxy (Proxy(Proxy)) - --------------------------------------------------------------------------------- --- `Transaction` --------------------------------------------------------------------------------- --- note: these types are derived from the cardano-serialization-lib Sundae fork --- the source of truth for these types should be that library and the --- corresponding Rust types -newtype Transaction = Transaction - { body :: TxBody - , witnessSet :: TransactionWitnessSet - , isValid :: Boolean - , auxiliaryData :: Maybe AuxiliaryData - } - -derive instance Generic Transaction _ -derive instance Eq Transaction -derive instance Newtype Transaction _ -derive newtype instance EncodeAeson Transaction - -instance Show Transaction where - show = genericShow - -instance Semigroup Transaction where - append (Transaction tx) (Transaction tx') = - Transaction - { body: txCheck tx.body <> txCheck' tx'.body - , witnessSet: txCheck tx.witnessSet <> txCheck' tx'.witnessSet - , isValid: tx.isValid && tx'.isValid - , auxiliaryData: txCheck tx.auxiliaryData <> txCheck' tx'.auxiliaryData - } - where - txCheck :: forall (m :: Type). Monoid m => m -> m - txCheck = guard tx.isValid - - txCheck' :: forall (m :: Type). Monoid m => m -> m - txCheck' = guard tx'.isValid - -instance Monoid Transaction where - mempty = Transaction - { body: mempty - , witnessSet: mempty - , isValid: true - , auxiliaryData: Nothing - } - --------------------------------------------------------------------------------- --- `Transaction` Lenses --------------------------------------------------------------------------------- -_body :: Lens' Transaction TxBody -_body = lens' \(Transaction rec@{ body }) -> - Tuple body \bod -> Transaction rec { body = bod } - -_witnessSet :: Lens' Transaction TransactionWitnessSet -_witnessSet = lens' \(Transaction rec@{ witnessSet }) -> - Tuple witnessSet \ws -> Transaction rec { witnessSet = ws } - -_isValid :: Lens' Transaction Boolean -_isValid = lens' \(Transaction rec@{ isValid }) -> - Tuple isValid \iv -> Transaction rec { isValid = iv } - -_auxiliaryData :: Lens' Transaction (Maybe AuxiliaryData) -_auxiliaryData = lens' \(Transaction rec@{ auxiliaryData }) -> - Tuple auxiliaryData \ad -> Transaction rec { auxiliaryData = ad } - --------------------------------------------------------------------------------- --- `TxBody` --------------------------------------------------------------------------------- --- According to https://github.com/input-output-hk/cardano-ledger/blob/master/eras/babbage/test-suite/cddl-files/babbage.cddl --- requiredSigners is an Array over `VKey`s essentially. But some comments at --- the bottom say it's Maybe? -newtype TxBody = TxBody - { inputs :: Set TransactionInput - , outputs :: Array TransactionOutput - , fee :: Coin - , ttl :: Maybe Slot - , certs :: Maybe (Array Certificate) - , withdrawals :: Maybe (Map RewardAddress Coin) - , update :: Maybe Update - , auxiliaryDataHash :: Maybe AuxiliaryDataHash - , validityStartInterval :: Maybe Slot - , mint :: Maybe Mint - , scriptDataHash :: Maybe ScriptDataHash - , collateral :: Maybe (Array TransactionInput) - , requiredSigners :: Maybe (Array RequiredSigner) - , networkId :: Maybe NetworkId - , collateralReturn :: Maybe TransactionOutput - , totalCollateral :: Maybe Coin - , referenceInputs :: Set TransactionInput - } - -derive instance Generic TxBody _ -derive instance Newtype TxBody _ -derive newtype instance Eq TxBody - -instance Show TxBody where - show = genericShow - -instance Semigroup TxBody where - append (TxBody txB) (TxBody txB') = TxBody - { inputs: txB.inputs `Set.union` txB'.inputs - , outputs: txB.outputs `union` txB'.outputs - , fee: txB.fee <> txB'.fee - , ttl: lift2 lowerbound txB.ttl txB'.ttl - , certs: lift2 union txB.certs txB'.certs - , withdrawals: lift2 appendMap txB.withdrawals txB'.withdrawals - , update: txB.update txB'.update - , auxiliaryDataHash: txB.auxiliaryDataHash txB'.auxiliaryDataHash - , validityStartInterval: - lift2 lowerbound - txB.validityStartInterval - txB'.validityStartInterval - , mint: txB.mint <> txB'.mint - , referenceInputs: txB.referenceInputs <> txB'.referenceInputs - , scriptDataHash: txB.scriptDataHash txB'.scriptDataHash - , collateral: lift2 union txB.collateral txB'.collateral - , requiredSigners: lift2 union txB.requiredSigners txB'.requiredSigners - , networkId: txB.networkId txB'.networkId - , collateralReturn: txB.collateralReturn <|> txB.collateralReturn - , totalCollateral: txB.totalCollateral <|> txB.totalCollateral - } - where - lowerbound :: Slot -> Slot -> Slot - lowerbound (Slot x) (Slot y) = Slot $ min x y - -instance Monoid TxBody where - mempty = TxBody - { inputs: mempty - , outputs: mempty - , fee: mempty - , ttl: Nothing - , certs: Nothing - , withdrawals: Nothing - , update: Nothing - , auxiliaryDataHash: Nothing - , validityStartInterval: Nothing - , mint: Nothing - , scriptDataHash: Nothing - , collateral: Nothing - , requiredSigners: Nothing - , networkId: Nothing - , collateralReturn: Nothing - , totalCollateral: Nothing - , referenceInputs: mempty - } - -instance EncodeAeson TxBody where - encodeAeson (TxBody r) = encodeAeson $ r - { withdrawals = encodeMap <$> r.withdrawals } - -newtype ScriptDataHash = ScriptDataHash ByteArray - -derive instance Newtype ScriptDataHash _ -derive instance Generic ScriptDataHash _ -derive newtype instance Eq ScriptDataHash -derive newtype instance EncodeAeson ScriptDataHash - -instance Show ScriptDataHash where - show = genericShow - -newtype Mint = Mint NonAdaAsset - -derive instance Generic Mint _ -derive instance Newtype Mint _ -derive newtype instance Eq Mint -derive newtype instance Semigroup Mint -derive newtype instance Monoid Mint -derive newtype instance EncodeAeson Mint - -instance Show Mint where - show = genericShow - -newtype AuxiliaryDataHash = AuxiliaryDataHash ByteArray - -derive instance Generic AuxiliaryDataHash _ -derive instance Newtype AuxiliaryDataHash _ -derive newtype instance Eq AuxiliaryDataHash -derive newtype instance EncodeAeson AuxiliaryDataHash - -instance Show AuxiliaryDataHash where - show = genericShow - -type Update = - { proposedProtocolParameterUpdates :: ProposedProtocolParameterUpdates - , epoch :: Epoch - } - -newtype ProposedProtocolParameterUpdates = - ProposedProtocolParameterUpdates (Map GenesisHash ProtocolParamUpdate) - -derive instance Newtype ProposedProtocolParameterUpdates _ - -derive newtype instance Eq ProposedProtocolParameterUpdates - -derive instance Generic ProposedProtocolParameterUpdates _ - -instance Show ProposedProtocolParameterUpdates where - show = genericShow - -instance EncodeAeson ProposedProtocolParameterUpdates where - encodeAeson (ProposedProtocolParameterUpdates r) = encodeMap r - -newtype GenesisHash = GenesisHash ByteArray - -derive instance Newtype GenesisHash _ -derive newtype instance Eq GenesisHash -derive newtype instance Ord GenesisHash -derive instance Generic GenesisHash _ -derive newtype instance EncodeAeson GenesisHash - -instance Show GenesisHash where - show = genericShow - -type ProtocolParamUpdate = - { minfeeA :: Maybe Coin - , minfeeB :: Maybe Coin - , maxBlockBodySize :: Maybe UInt - , maxTxSize :: Maybe UInt - , maxBlockHeaderSize :: Maybe UInt - , keyDeposit :: Maybe Coin - , poolDeposit :: Maybe Coin - , maxEpoch :: Maybe Epoch - , nOpt :: Maybe UInt - , poolPledgeInfluence :: Maybe UnitInterval - , expansionRate :: Maybe UnitInterval - , treasuryGrowthRate :: Maybe UnitInterval - , protocolVersion :: Maybe ProtocolVersion - , minPoolCost :: Maybe BigNum - , adaPerUtxoByte :: Maybe BigNum - , costModels :: Maybe Costmdls - , executionCosts :: Maybe ExUnitPrices - , maxTxExUnits :: Maybe ExUnits - , maxBlockExUnits :: Maybe ExUnits - , maxValueSize :: Maybe UInt - , collateralPercentage :: Maybe UInt - , maxCollateralInputs :: Maybe UInt - } - -type ExUnitPrices = - { memPrice :: SubCoin - , stepPrice :: SubCoin - } - -type ExUnits = - { mem :: BigInt - , steps :: BigInt - } - -type SubCoin = UnitInterval - -newtype Costmdls = Costmdls (Map Language CostModel) - -derive instance Newtype Costmdls _ -derive newtype instance Eq Costmdls -derive instance Generic Costmdls _ - -instance Show Costmdls where - show = genericShow - -instance EncodeAeson Costmdls where - encodeAeson = encodeMap <<< unwrap - -newtype CostModel = CostModel (Array Int.Int) - -derive instance Newtype CostModel _ -derive newtype instance Eq CostModel -derive newtype instance EncodeAeson CostModel -derive instance Generic Nonce _ -derive instance Generic CostModel _ - -instance Show CostModel where - show = genericShow - -type ProtocolVersion = - { major :: UInt - , minor :: UInt - } - --- Following CSL Nonce is either None or a 32 byte hash -data Nonce = IdentityNonce | HashNonce ByteArray - -derive instance Eq Nonce - -instance Show Nonce where - show = genericShow - -instance DecodeAeson Nonce where - decodeAeson aeson = (HashNonce <$> decodeAeson aeson) <|> - caseAesonString err - ( case _ of - "neutral" -> pure IdentityNonce - _ -> err - ) - aeson - where - err :: Either JsonDecodeError Nonce - err = Left (TypeMismatch "Nonce") - -instance EncodeAeson Nonce where - encodeAeson IdentityNonce = encodeAeson "neutral" - encodeAeson (HashNonce hash) = encodeAeson hash - -type UnitInterval = - { numerator :: BigNum - , denominator :: BigNum - } - -newtype Epoch = Epoch UInt - -derive instance Newtype Epoch _ -derive instance Generic Epoch _ -derive newtype instance Eq Epoch -derive newtype instance EncodeAeson Epoch - -instance Show Epoch where - show = genericShow - -newtype Ipv4 = Ipv4 ByteArray - -derive instance Eq Ipv4 -derive instance Generic Ipv4 _ -derive instance Newtype Ipv4 _ --- TODO: Use a more legible representation -derive newtype instance EncodeAeson Ipv4 - -instance Show Ipv4 where - show = genericShow - -newtype Ipv6 = Ipv6 ByteArray - -derive instance Eq Ipv6 -derive instance Generic Ipv6 _ -derive instance Newtype Ipv6 _ -derive newtype instance EncodeAeson Ipv6 - -instance Show Ipv6 where - show = genericShow - -data Relay - = SingleHostAddr - { port :: Maybe Int - , ipv4 :: Maybe Ipv4 - , ipv6 :: Maybe Ipv6 - } - | SingleHostName - { port :: Maybe Int - , dnsName :: String - } - | MultiHostName { dnsName :: String } - -derive instance Eq Relay -derive instance Generic Relay _ - -instance Show Relay where - show = genericShow - -instance EncodeAeson Relay where - encodeAeson = case _ of - SingleHostAddr r -> encodeTagged' "SingleHostAddr" r - SingleHostName r -> encodeTagged' "SingleHostName" r - MultiHostName r -> encodeTagged' "MultiHostName" r - -newtype URL = URL String - -derive instance Eq URL -derive instance Generic URL _ -derive instance Newtype URL _ -derive newtype instance EncodeAeson URL - -instance Show URL where - show = genericShow - -newtype PoolMetadataHash = PoolMetadataHash ByteArray - -derive instance Eq PoolMetadataHash -derive instance Generic PoolMetadataHash _ -derive instance Newtype PoolMetadataHash _ -derive newtype instance EncodeAeson PoolMetadataHash - -instance Show PoolMetadataHash where - show = genericShow - -newtype PoolMetadata = PoolMetadata - { url :: URL - , hash :: PoolMetadataHash - } - -derive instance Eq PoolMetadata -derive instance Generic PoolMetadata _ -derive newtype instance EncodeAeson PoolMetadata - -instance Show PoolMetadata where - show = genericShow - -newtype GenesisDelegateHash = GenesisDelegateHash ByteArray - -derive instance Eq GenesisDelegateHash -derive instance Generic GenesisDelegateHash _ -derive newtype instance EncodeAeson GenesisDelegateHash - -instance Show GenesisDelegateHash where - show = genericShow - -newtype MIRToStakeCredentials = MIRToStakeCredentials - (Map StakeCredential Int.Int) - -derive instance Eq MIRToStakeCredentials -derive instance Generic MIRToStakeCredentials _ - -instance Show MIRToStakeCredentials where - show = genericShow - -instance EncodeAeson MIRToStakeCredentials where - encodeAeson (MIRToStakeCredentials r) = encodeMap r - -data MoveInstantaneousReward - = ToOtherPot - { pot :: Number - , amount :: BigNum - } - | ToStakeCreds - { pot :: Number - , amounts :: MIRToStakeCredentials - } - -derive instance Eq MoveInstantaneousReward -derive instance Generic MoveInstantaneousReward _ - -instance Show MoveInstantaneousReward where - show = genericShow - -instance EncodeAeson MoveInstantaneousReward where - encodeAeson = case _ of - ToOtherPot r -> encodeTagged' "ToOtherPot" r - -- We assume the numbers are finite - { pot = unsafePartial $ fromJust $ finiteNumber r.pot } - ToStakeCreds r -> encodeTagged' "ToStakeCreds" r - -- We assume the numbers are finite - { pot = unsafePartial $ fromJust $ finiteNumber r.pot } - -type PoolRegistrationParams = - { operator :: PoolPubKeyHash -- cwitness (cert) - , vrfKeyhash :: VRFKeyHash - -- needed to prove that the pool won the lottery - , pledge :: BigNum - , cost :: BigNum -- >= pparams.minPoolCost - , margin :: UnitInterval -- proportion that goes to the reward account - , rewardAccount :: RewardAddress - , poolOwners :: Array PaymentPubKeyHash - -- payment key hashes that contribute to pledge amount - , relays :: Array Relay - , poolMetadata :: Maybe PoolMetadata - } - -newtype PoolPubKeyHash = PoolPubKeyHash PubKeyHash - -derive instance Newtype PoolPubKeyHash _ -derive instance Eq PoolPubKeyHash -derive instance Ord PoolPubKeyHash -derive instance Generic PoolPubKeyHash _ -derive newtype instance ToData PoolPubKeyHash -derive newtype instance FromData PoolPubKeyHash - -instance EncodeAeson PoolPubKeyHash where - encodeAeson (PoolPubKeyHash kh) = - encodeAeson (ed25519KeyHashToBech32 "pool" $ unwrap kh) - -instance DecodeAeson PoolPubKeyHash where - decodeAeson aeson = do - str <- decodeAeson aeson - PoolPubKeyHash <<< PubKeyHash <$> note (TypeMismatch "PoolPubKeyHash") - (ed25519KeyHashFromBech32 str) - -instance Show PoolPubKeyHash where - show (PoolPubKeyHash kh) = - "(PoolPubKeyHash (Ed25519KeyHash (unsafePartial $ fromJust $ \ - \ed25519KeyHashFromBech32 " - <> show (ed25519KeyHashToBech32 "pool" $ unwrap kh) - <> ")))" - -mkPoolPubKeyHash :: Bech32String -> Maybe PoolPubKeyHash -mkPoolPubKeyHash str - | startsWith "pool" str = PoolPubKeyHash <<< PubKeyHash <$> - ed25519KeyHashFromBech32 str - | otherwise = Nothing - -poolPubKeyHashToBech32 :: PoolPubKeyHash -> Bech32String -poolPubKeyHashToBech32 = unwrap >>> unwrap >>> ed25519KeyHashToBech32Unsafe - "pool" - -data Certificate - = StakeRegistration StakeCredential - | StakeDeregistration StakeCredential - | StakeDelegation StakeCredential PoolPubKeyHash - | PoolRegistration PoolRegistrationParams - | PoolRetirement - { poolKeyHash :: PoolPubKeyHash - , epoch :: Epoch - } - | GenesisKeyDelegation - { genesisHash :: GenesisHash - , genesisDelegateHash :: GenesisDelegateHash - , vrfKeyhash :: VRFKeyHash - } - | MoveInstantaneousRewardsCert MoveInstantaneousReward - -derive instance Eq Certificate -derive instance Generic Certificate _ - -instance Show Certificate where - show = genericShow - -instance EncodeAeson Certificate where - encodeAeson = case _ of - StakeRegistration r -> encodeTagged' "StakeRegistration" r - StakeDeregistration r -> encodeTagged' "StakeDeregistration" - r - StakeDelegation cred hash -> encodeTagged' "StakeDelegation" - { stakeCredential: cred, ed25519KeyHash: hash } - PoolRegistration r -> encodeTagged' "PoolRegistration" r - PoolRetirement r -> encodeTagged' "PoolRetirement" r - GenesisKeyDelegation r -> encodeTagged' - "GenesisKeyDelegation" - r - MoveInstantaneousRewardsCert r -> encodeTagged' - "MoveInstantaneousReward" - r - --------------------------------------------------------------------------------- --- `TxBody` Lenses --------------------------------------------------------------------------------- - -_inputs :: Lens' TxBody (Set TransactionInput) -_inputs = _Newtype <<< prop (Proxy :: Proxy "inputs") - -_outputs :: Lens' TxBody (Array TransactionOutput) -_outputs = _Newtype <<< prop (Proxy :: Proxy "outputs") - -_fee :: Lens' TxBody (Coin) -_fee = _Newtype <<< prop (Proxy :: Proxy "fee") - -_ttl :: Lens' TxBody (Maybe Slot) -_ttl = _Newtype <<< prop (Proxy :: Proxy "ttl") - -_certs :: Lens' TxBody (Maybe (Array Certificate)) -_certs = _Newtype <<< prop (Proxy :: Proxy "certs") - -_withdrawals :: Lens' TxBody (Maybe (Map RewardAddress Coin)) -_withdrawals = _Newtype <<< prop (Proxy :: Proxy "withdrawals") - -_update :: Lens' TxBody (Maybe Update) -_update = _Newtype <<< prop (Proxy :: Proxy "update") - -_auxiliaryDataHash :: Lens' TxBody (Maybe AuxiliaryDataHash) -_auxiliaryDataHash = _Newtype <<< prop (Proxy :: Proxy "auxiliaryDataHash") - -_validityStartInterval :: Lens' TxBody (Maybe Slot) -_validityStartInterval = - _Newtype <<< prop (Proxy :: Proxy "validityStartInterval") - -_mint :: Lens' TxBody (Maybe Mint) -_mint = _Newtype <<< prop (Proxy :: Proxy "mint") - -_scriptDataHash :: Lens' TxBody (Maybe ScriptDataHash) -_scriptDataHash = _Newtype <<< prop (Proxy :: Proxy "scriptDataHash") - -_collateral :: Lens' TxBody (Maybe (Array TransactionInput)) -_collateral = _Newtype <<< prop (Proxy :: Proxy "collateral") - -_requiredSigners :: Lens' TxBody (Maybe (Array RequiredSigner)) -_requiredSigners = _Newtype <<< prop (Proxy :: Proxy "requiredSigners") - -_networkId :: Lens' TxBody (Maybe NetworkId) -_networkId = _Newtype <<< prop (Proxy :: Proxy "networkId") - -_referenceInputs :: Lens' TxBody (Set TransactionInput) -_referenceInputs = _Newtype <<< prop (Proxy :: Proxy "referenceInputs") - -_collateralReturn :: Lens' TxBody (Maybe TransactionOutput) -_collateralReturn = _Newtype <<< prop (Proxy :: Proxy "collateralReturn") - -_totalCollateral :: Lens' TxBody (Maybe Coin) -_totalCollateral = _Newtype <<< prop (Proxy :: Proxy "totalCollateral") - --------------------------------------------------------------------------------- --- `TransactionWitnessSet` --------------------------------------------------------------------------------- -newtype TransactionWitnessSet = TransactionWitnessSet - { vkeys :: Maybe (Array Vkeywitness) - , nativeScripts :: Maybe (Array NativeScript) - , bootstraps :: Maybe (Array BootstrapWitness) - , plutusScripts :: Maybe (Array PlutusScript) - , plutusData :: Maybe (Array PlutusData) - , redeemers :: Maybe (Array Redeemer) - } - -derive instance Generic TransactionWitnessSet _ -derive instance Newtype TransactionWitnessSet _ -derive newtype instance Eq TransactionWitnessSet -derive newtype instance EncodeAeson TransactionWitnessSet - -instance Show TransactionWitnessSet where - show = genericShow - -instance Semigroup TransactionWitnessSet where - append (TransactionWitnessSet tws) (TransactionWitnessSet tws') = - TransactionWitnessSet - { vkeys: tws.vkeys <<>> tws'.vkeys - , nativeScripts: tws.nativeScripts <<>> tws'.nativeScripts - , bootstraps: tws.bootstraps <<>> tws'.bootstraps - , plutusScripts: tws.plutusScripts <<>> tws'.plutusScripts - , plutusData: tws.plutusData <<>> tws'.plutusData - , redeemers: tws.redeemers <<>> tws'.redeemers - } - -instance Monoid TransactionWitnessSet where - mempty = TransactionWitnessSet - { vkeys: Nothing - , nativeScripts: Nothing - , bootstraps: Nothing - , plutusScripts: Nothing - , plutusData: Nothing - , redeemers: Nothing - } - --------------------------------------------------------------------------------- --- `TransactionWitnessSet` Lenses --------------------------------------------------------------------------------- -_vkeys :: Lens' TransactionWitnessSet (Maybe (Array Vkeywitness)) -_vkeys = lens' \(TransactionWitnessSet rec@{ vkeys }) -> - Tuple vkeys \vk -> TransactionWitnessSet rec { vkeys = vk } - -_nativeScripts :: Lens' TransactionWitnessSet (Maybe (Array NativeScript)) -_nativeScripts = lens' \(TransactionWitnessSet rec@{ nativeScripts }) -> - Tuple nativeScripts \ns -> TransactionWitnessSet rec { nativeScripts = ns } - -_bootstraps :: Lens' TransactionWitnessSet (Maybe (Array BootstrapWitness)) -_bootstraps = lens' \(TransactionWitnessSet rec@{ bootstraps }) -> - Tuple bootstraps \bs -> TransactionWitnessSet rec { bootstraps = bs } - -_plutusScripts :: Lens' TransactionWitnessSet (Maybe (Array PlutusScript)) -_plutusScripts = lens' \(TransactionWitnessSet rec@{ plutusScripts }) -> - Tuple plutusScripts \ps -> TransactionWitnessSet rec { plutusScripts = ps } - -_plutusData :: Lens' TransactionWitnessSet (Maybe (Array PlutusData)) -_plutusData = lens' \(TransactionWitnessSet rec@{ plutusData }) -> - Tuple plutusData \pd -> TransactionWitnessSet rec { plutusData = pd } - -_redeemers :: Lens' TransactionWitnessSet (Maybe (Array Redeemer)) -_redeemers = lens' \(TransactionWitnessSet rec@{ redeemers }) -> - Tuple redeemers \red -> TransactionWitnessSet rec { redeemers = red } - --------------------------------------------------------------------------------- --- Other Datatypes --------------------------------------------------------------------------------- -type BootstrapWitness = - { vkey :: Vkey - , signature :: Ed25519Signature - , chainCode :: ByteArray - , attributes :: ByteArray - } - -newtype RequiredSigner = RequiredSigner Ed25519KeyHash - -derive instance Newtype RequiredSigner _ -derive newtype instance Eq RequiredSigner -derive newtype instance Ord RequiredSigner -derive newtype instance EncodeAeson RequiredSigner -derive instance Generic RequiredSigner _ - -instance Show RequiredSigner where - show = genericShow - -newtype Vkeywitness = Vkeywitness (Vkey /\ Ed25519Signature) - -derive instance Generic Vkeywitness _ -derive newtype instance Eq Vkeywitness -derive newtype instance EncodeAeson Vkeywitness -derive instance Newtype Vkeywitness _ - -instance Show Vkeywitness where - show = genericShow - -newtype Vkey = Vkey PublicKey - -derive instance Generic Vkey _ -derive instance Newtype Vkey _ -derive newtype instance Eq Vkey -derive newtype instance Ord Vkey -derive newtype instance EncodeAeson Vkey - -instance Show Vkey where - show = genericShow - -newtype PublicKey = PublicKey RawBytes - -mkPublicKey :: Bech32String -> Maybe PublicKey -mkPublicKey = map (PublicKey <<< bytesFromPublicKey) <<< publicKeyFromBech32 - -mkFromCslPubKey :: Serialization.PublicKey -> PublicKey -mkFromCslPubKey = PublicKey <<< bytesFromPublicKey - -convertPubKey :: PublicKey -> Serialization.PublicKey -convertPubKey (PublicKey bs) = unsafePartial - $ fromJust <<< fromBytes <<< wrap <<< unwrap - $ bs - -derive newtype instance Eq PublicKey -derive newtype instance Ord PublicKey -derive newtype instance EncodeAeson PublicKey - -instance ToData PublicKey where - toData (PublicKey bytes) = toData bytes - -instance FromData PublicKey where - fromData = map mkFromCslPubKey <<< fromBytes <=< fromData - -instance Show PublicKey where - show pk = "(PublicKey " <> (bech32FromPublicKey <<< convertPubKey $ pk) <> ")" - -newtype Ed25519Signature = Ed25519Signature RawBytes - -mkEd25519Signature :: Bech32String -> Maybe Ed25519Signature -mkEd25519Signature = - map (Ed25519Signature <<< wrap <<< unwrap <<< toBytes) <<< - ed25519SignatureFromBech32 - -mkFromCslEd25519Signature :: Serialization.Ed25519Signature -> Ed25519Signature -mkFromCslEd25519Signature = Ed25519Signature <<< wrap <<< unwrap <<< toBytes - -convertEd25519Signature :: Ed25519Signature -> Serialization.Ed25519Signature -convertEd25519Signature (Ed25519Signature bs) = unsafePartial - $ fromJust <<< fromBytes <<< wrap <<< unwrap - $ bs - -derive newtype instance Eq Ed25519Signature -derive newtype instance Ord Ed25519Signature -derive newtype instance EncodeAeson Ed25519Signature - -instance Show Ed25519Signature where - show sig = "(Ed25519Signature " - <> (bech32FromEd25519Signature <<< convertEd25519Signature $ sig) - <> ")" - -newtype Redeemer = Redeemer - { tag :: RedeemerTag - , index :: BigInt - , data :: PlutusData - , exUnits :: ExUnits - } - -derive instance Generic Redeemer _ -derive instance Newtype Redeemer _ -derive newtype instance Eq Redeemer -derive newtype instance Ord Redeemer -derive newtype instance EncodeAeson Redeemer - -instance Show Redeemer where - show = genericShow - -newtype AuxiliaryData = AuxiliaryData - { metadata :: Maybe GeneralTransactionMetadata - , nativeScripts :: Maybe (Array NativeScript) - , plutusScripts :: Maybe (Array PlutusScript) - } - -derive instance Generic AuxiliaryData _ -derive instance Newtype AuxiliaryData _ -derive newtype instance Eq AuxiliaryData -derive newtype instance EncodeAeson AuxiliaryData - -instance Show AuxiliaryData where - show = genericShow - -instance Semigroup AuxiliaryData where - append (AuxiliaryData ad) (AuxiliaryData ad') = - AuxiliaryData - { metadata: ad.metadata <> ad'.metadata - , nativeScripts: lift2 union ad.nativeScripts ad'.nativeScripts - , plutusScripts: lift2 union ad.plutusScripts ad'.plutusScripts - } - -instance Monoid AuxiliaryData where - mempty = AuxiliaryData - { metadata: Nothing - , nativeScripts: Nothing - , plutusScripts: Nothing - } - -newtype TransactionOutput = TransactionOutput - { address :: Address - , amount :: Value - , datum :: OutputDatum - , scriptRef :: Maybe ScriptRef - } - -derive instance Generic TransactionOutput _ -derive instance Newtype TransactionOutput _ -derive newtype instance Eq TransactionOutput -derive newtype instance EncodeAeson TransactionOutput - -instance Show TransactionOutput where - show = genericShow - -type UtxoMap = Map TransactionInput TransactionOutput - -pprintUtxoMap :: UtxoMap -> TagSet -pprintUtxoMap utxos = TagSet.fromArray $ - Map.toUnfoldable utxos <#> - \( TransactionInput { transactionId, index } /\ - TransactionOutput { address, amount, datum, scriptRef } - ) -> - let - datumTagSets = case datum of - NoOutputDatum -> [] - OutputDatumHash datumHash -> - [ TagSet.fromArray - [ "datum hash" `tag` byteArrayToHex (unwrap datumHash) ] - ] - OutputDatum plutusData -> - [ TagSet.fromArray - [ "datum" `tagSetTag` pprintPlutusData (unwrap plutusData) ] - ] - scriptRefTagSets = case scriptRef of - Nothing -> [] - Just ref -> [ "Script Reference" `tag` show ref ] - outputTagSet = - [ "amount" `tagSetTag` pprintValue amount - , "address" `tag` addressBech32 address - ] - <> datumTagSets - <> scriptRefTagSets - in - (byteArrayToHex (unwrap transactionId) <> "#" <> UInt.toString index) - `tagSetTag` TagSet.fromArray outputTagSet diff --git a/src/Internal/Cardano/Types/TransactionUnspentOutput.purs b/src/Internal/Cardano/Types/TransactionUnspentOutput.purs deleted file mode 100644 index b73ac506af..0000000000 --- a/src/Internal/Cardano/Types/TransactionUnspentOutput.purs +++ /dev/null @@ -1,32 +0,0 @@ -module Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - , transactionUnspentOutputsToUtxoMap - ) where - -import Prelude - -import Aeson (class EncodeAeson) -import Ctl.Internal.Cardano.Types.Transaction (TransactionOutput, UtxoMap) -import Ctl.Internal.Types.Transaction (TransactionInput) -import Data.Generic.Rep (class Generic) -import Data.Map as Map -import Data.Newtype (class Newtype) -import Data.Show.Generic (genericShow) -import Data.Tuple (Tuple(Tuple)) - -newtype TransactionUnspentOutput = TransactionUnspentOutput - { input :: TransactionInput - , output :: TransactionOutput - } - -derive instance Generic TransactionUnspentOutput _ -derive instance Newtype TransactionUnspentOutput _ -derive newtype instance Eq TransactionUnspentOutput -derive newtype instance EncodeAeson TransactionUnspentOutput - -instance Show TransactionUnspentOutput where - show = genericShow - -transactionUnspentOutputsToUtxoMap :: Array TransactionUnspentOutput -> UtxoMap -transactionUnspentOutputsToUtxoMap = Map.fromFoldable <<< map - \(TransactionUnspentOutput { input, output }) -> Tuple input output diff --git a/src/Internal/Cardano/Types/Value.purs b/src/Internal/Cardano/Types/Value.purs deleted file mode 100644 index 567a189c0a..0000000000 --- a/src/Internal/Cardano/Types/Value.purs +++ /dev/null @@ -1,911 +0,0 @@ -module Ctl.Internal.Cardano.Types.Value - ( AssetClass(AssetClass) - , Coin(Coin) - , CurrencySymbol - , NonAdaAsset - , Value(Value) - , class Negate - , class Split - , assetToValue - , coinToValue - , currencyMPSHash - , eq - , equipartitionValueWithTokenQuantityUpperBound - , filterNonAda - , flattenNonAdaValue - , geq - , getAssetQuantity - , getCurrencySymbol - , getLovelace - , getNonAdaAsset - , getNonAdaAsset' - , gt - , isAdaOnly - , isPos - , isZero - , leq - , lovelaceValueOf - , lt - , minus - , mkCoin - , mkCurrencySymbol - , mkNonAdaAsset - , mkNonAdaAssets - , mkNonAdaAssetsFromTokenMap - , mkSingletonNonAdaAsset - , mkSingletonValue - , mkSingletonValue' - , mkValue - , mpsSymbol - , negation - , numCurrencySymbols - , numNonAdaAssets - , numNonAdaCurrencySymbols - , numTokenNames - , posNonAdaAsset - , pprintNonAdaAsset - , pprintValue - , scriptHashAsCurrencySymbol - , split - , sumTokenNameLengths - , unionWith - , unionWithNonAda - , unwrapNonAdaAsset - , valueAssetClasses - , valueAssets - , valueOf - , valueToCoin - , valueToCoin' - ) where - -import Prelude hiding (join) - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , caseAesonObject - , encodeAeson - , getField - ) -import Control.Alt ((<|>)) -import Control.Alternative (guard) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Helpers (encodeMap, showWithParens) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata) -import Ctl.Internal.Partition (class Equipartition, equipartition) -import Ctl.Internal.Serialization.Hash - ( ScriptHash - , scriptHashFromBytes - , scriptHashToBytes - ) -import Ctl.Internal.ToData (class ToData) -import Ctl.Internal.Types.ByteArray - ( ByteArray - , byteArrayFromIntArrayUnsafe - , byteArrayToHex - , byteLength - , hexToByteArray - ) -import Ctl.Internal.Types.Scripts (MintingPolicyHash(MintingPolicyHash)) -import Ctl.Internal.Types.TokenName - ( TokenName - , adaToken - , fromTokenName - , getTokenName - , mkTokenName - , mkTokenNames - ) -import Data.Array (cons, filter) -import Data.Array (fromFoldable) as Array -import Data.Array.NonEmpty (NonEmptyArray) -import Data.Array.NonEmpty (replicate, singleton, zipWith) as NEArray -import Data.Bifunctor (bimap) -import Data.Bitraversable (bitraverse, ltraverse) -import Data.Either (Either(Left), note) -import Data.Foldable (any, fold, foldl, length) -import Data.FoldableWithIndex (foldrWithIndex) -import Data.Function (on) -import Data.Generic.Rep (class Generic) -import Data.Int (ceil) as Int -import Data.Lattice (class JoinSemilattice, class MeetSemilattice, join, meet) -import Data.List (List(Nil), all, (:)) -import Data.List (nubByEq) as List -import Data.Log.Tag (TagSet, tag, tagSetTag) -import Data.Log.Tag as TagSet -import Data.Map (Map, keys, lookup, toUnfoldable, unions, values) -import Data.Map as Map -import Data.Map.Gen (genMap) -import Data.Maybe (Maybe(Just, Nothing), fromJust) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Set (Set) -import Data.Show.Generic (genericShow) -import Data.These (These(Both, That, This)) -import Data.Traversable (class Traversable, traverse) -import Data.Tuple (fst) -import Data.Tuple.Nested (type (/\), (/\)) -import JS.BigInt (BigInt, fromInt, toNumber) -import JS.BigInt as BigInt -import Partial.Unsafe (unsafePartial) -import Test.QuickCheck.Arbitrary (class Arbitrary, arbitrary) -import Test.QuickCheck.Gen (Gen, chooseInt, suchThat, vectorOf) - --- `Negate` and `Split` seem a bit too contrived, and their purpose is to --- combine similar behaviour without satisfying any useful laws. I wonder --- if we're better off simply writing functions for Coin, NonAdaAsset and Value --- to `split` and `negate` (it's just 6 functions) in total without the need of --- a somewhat meaningless typeclass. - --- We could write a Group instance to get `negate` but I'm not sure this would --- make much sense for Value. Plutus uses a custom AdditiveGroup. --- We could define a Data.Group although zero-valued tokens don't degenerate --- from our map currently - I don't think we'd want this behaviour. --- | Negation to create an AdditiveGroup for Value. Call it negation to not confuse --- | with negate. -class Negate (a :: Type) where - negation :: a -> a - --- | Split a value into its positive and non-positive parts. The first element of --- | the tuple contains the non-positive parts of the value, the second element --- | contains the positive parts. The convention is non-positive parts are --- | negated to make them positive in the output. -class Split (a :: Type) where - split :: a -> a /\ a - --------------------------------------------------------------------------------- --- Coin (Ada) --------------------------------------------------------------------------------- - -newtype Coin = Coin BigInt - -derive instance Generic Coin _ -derive instance Newtype Coin _ -derive newtype instance Eq Coin -derive newtype instance Ord Coin -derive newtype instance DecodeAeson Coin -derive newtype instance EncodeAeson Coin -derive newtype instance Equipartition Coin -derive newtype instance Semiring Coin -derive newtype instance Ring Coin -derive newtype instance CommutativeRing Coin -derive newtype instance EuclideanRing Coin - -instance Arbitrary Coin where - arbitrary = Coin <<< fromInt <$> suchThat arbitrary (_ >= zero) - -instance Show Coin where - show (Coin c) = showWithParens "Coin" c - -instance Semigroup Coin where - append (Coin c1) (Coin c2) = Coin (c1 + c2) - -instance Monoid Coin where - mempty = Coin zero - -instance JoinSemilattice Coin where - join (Coin c1) (Coin c2) = Coin (max c1 c2) - -instance MeetSemilattice Coin where - meet (Coin c1) (Coin c2) = Coin (min c1 c2) - -instance Negate Coin where - negation = wrap <<< negate <<< unwrap - -instance Split Coin where - split (Coin c) = - if c <= zero then Coin (negate c) /\ Coin zero else Coin zero /\ Coin c - --- This module rewrites functionality from: --- https://github.com/mlabs-haskell/bot-plutus-interface/blob/master/src/BotPlutusInterface/PreBalance.hs --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value - --- | Make `Coin` from an `Int` instead of `BigInt` -mkCoin :: Int -> Coin -mkCoin = Coin <<< fromInt - --- | Get the amount of lovelaces in Ada `Coin`. -getLovelace :: Coin -> BigInt -getLovelace (Coin l) = l - --- | Convert a `BigInt` to Ada-only `Value` -lovelaceValueOf :: BigInt -> Value -lovelaceValueOf = flip (Value <<< Coin) mempty - --- | Create a `Value` containing only the given `Coin`. -coinToValue :: Coin -> Value -coinToValue (Coin i) = lovelaceValueOf i - --- | Get the `Coin` in the given `Value`. -valueToCoin :: Value -> Coin -valueToCoin = Coin <<< valueToCoin' - --- | Get the `Coin` in the given `Value` as a `BigInt` -valueToCoin' :: Value -> BigInt -valueToCoin' v = valueOf v unsafeAdaSymbol adaToken - --------------------------------------------------------------------------------- --- CurrencySymbol --------------------------------------------------------------------------------- - -newtype CurrencySymbol = CurrencySymbol ByteArray - -derive newtype instance Eq CurrencySymbol -derive newtype instance FromData CurrencySymbol -derive newtype instance FromMetadata CurrencySymbol -derive newtype instance Ord CurrencySymbol -derive newtype instance ToData CurrencySymbol -derive newtype instance ToMetadata CurrencySymbol - -instance Arbitrary CurrencySymbol where - arbitrary = - unsafePartial fromJust <<< mkCurrencySymbol <<< byteArrayFromIntArrayUnsafe - <$> vectorOf 28 (chooseInt 0 255) - -instance Show CurrencySymbol where - show (CurrencySymbol cs) = "(CurrencySymbol " <> show cs <> ")" - --- This is needed for `ApplyArgs`. Plutus has an `unCurrencySymbol` field. -instance DecodeAeson CurrencySymbol where - decodeAeson = caseAesonObject - (Left $ TypeMismatch "Expected object") - ( note (TypeMismatch "Invalid CurrencySymbol") <<< mkCurrencySymbol - <=< note (TypeMismatch "Invalid ByteArray") <<< hexToByteArray - <=< flip getField "unCurrencySymbol" - ) - -instance EncodeAeson CurrencySymbol where - encodeAeson (CurrencySymbol ba) = encodeAeson - { "unCurrencySymbol": byteArrayToHex ba } - -getCurrencySymbol :: CurrencySymbol -> ByteArray -getCurrencySymbol (CurrencySymbol curSymbol) = curSymbol - --- Currency symbol for Ada, do not use inside NonAdaAsset map - do not export. --- For internal use only -unsafeAdaSymbol :: CurrencySymbol -unsafeAdaSymbol = CurrencySymbol mempty - --- | Create a `CurrencySymbol` from a `ByteArray` since `CurrencySymbol` data --- | constructor is not exported -mkCurrencySymbol :: ByteArray -> Maybe CurrencySymbol -mkCurrencySymbol byteArr = - scriptHashFromBytes byteArr *> pure (CurrencySymbol byteArr) - --- Do not export. Create an Ada `CurrencySymbol` from a `ByteArray` -mkUnsafeAdaSymbol :: ByteArray -> Maybe CurrencySymbol -mkUnsafeAdaSymbol byteArr = - if byteArr == mempty then pure unsafeAdaSymbol else Nothing - --------------------------------------------------------------------------------- --- NonAdaAsset --------------------------------------------------------------------------------- - -newtype NonAdaAsset = NonAdaAsset (Map CurrencySymbol (Map TokenName BigInt)) - -derive newtype instance Eq NonAdaAsset - -instance Arbitrary NonAdaAsset where - arbitrary = - NonAdaAsset <$> - genMap - (arbitrary :: Gen CurrencySymbol) - ( flip suchThat (not Map.isEmpty) $ - genMap - (arbitrary :: Gen TokenName) - (fromInt <$> suchThat arbitrary (_ >= one) :: Gen BigInt) - ) - -instance Show NonAdaAsset where - show (NonAdaAsset nonAdaAsset) = "(NonAdaAsset " <> show nonAdaAsset <> ")" - -instance Semigroup NonAdaAsset where - append = unionWithNonAda (+) - -instance Monoid NonAdaAsset where - mempty = NonAdaAsset Map.empty - -instance JoinSemilattice NonAdaAsset where - join = unionWithNonAda max - -instance MeetSemilattice NonAdaAsset where - meet = unionWithNonAda min - -instance Negate NonAdaAsset where - negation = NonAdaAsset <<< map (map negate) <<< unwrapNonAdaAsset - -instance Split NonAdaAsset where - split (NonAdaAsset mp) = NonAdaAsset npos /\ NonAdaAsset pos - where - splitIntl - :: Map TokenName BigInt - -> These (Map TokenName BigInt) (Map TokenName BigInt) - splitIntl mp' = Both l r - where - l /\ r = mapThese (\i -> if i <= zero then This (negate i) else That i) - mp' - - npos /\ pos = mapThese splitIntl mp - -instance EncodeAeson NonAdaAsset where - encodeAeson (NonAdaAsset m) = encodeAeson $ encodeMap $ encodeMap <$> m - -instance Equipartition NonAdaAsset where - equipartition nonAdaAssets numParts = - foldl accumulate (NEArray.replicate numParts mempty) - (flattenNonAdaValue nonAdaAssets) - where - accumulate - :: NonEmptyArray NonAdaAsset - -> (CurrencySymbol /\ TokenName /\ BigInt) - -> NonEmptyArray NonAdaAsset - accumulate xs (cs /\ tn /\ tokenQuantity) = - NEArray.zipWith append xs $ - map (mkSingletonNonAdaAsset cs tn) - (equipartition tokenQuantity numParts) - -pprintNonAdaAsset :: NonAdaAsset -> TagSet -pprintNonAdaAsset mp = TagSet.fromArray $ - Map.toUnfoldable (unwrapNonAdaAsset mp) <#> \(currency /\ tokens) -> - byteArrayToHex (getCurrencySymbol currency) `tagSetTag` TagSet.fromArray - ( Map.toUnfoldable tokens <#> \(tokenName /\ amount) -> - fromTokenName byteArrayToHex show tokenName `tag` BigInt.toString - amount - ) - --- | Partitions a `NonAdaAsset` into smaller `NonAdaAsset`s, where the --- | quantity of each token is equipartitioned across the resultant --- | `NonAdaAsset`s, with the goal that no token quantity in any of the --- | resultant `NonAdaAsset`s exceeds the given upper bound. --- | Taken from cardano-wallet: --- | https://github.com/input-output-hk/cardano-wallet/blob/d4b30de073f2b5eddb25bf12c2453abb42e8b352/lib/wallet/src/Cardano/Wallet/Primitive/Types/TokenMap.hs#L780 -equipartitionAssetsWithTokenQuantityUpperBound - :: NonAdaAsset -> BigInt -> NonEmptyArray NonAdaAsset /\ Int -equipartitionAssetsWithTokenQuantityUpperBound nonAdaAssets maxTokenQuantity = - case - maxTokenQuantity <= zero || currentMaxTokenQuantity <= maxTokenQuantity - of - true -> - NEArray.singleton nonAdaAssets /\ one - false -> - equipartition nonAdaAssets numParts /\ numParts - where - numParts :: Int - numParts = - Int.ceil (toNumber currentMaxTokenQuantity / toNumber maxTokenQuantity) - - tokenQuantity :: (CurrencySymbol /\ TokenName /\ BigInt) -> BigInt - tokenQuantity (_ /\ _ /\ quantity) = quantity - - currentMaxTokenQuantity :: BigInt - currentMaxTokenQuantity = - foldl (\quantity tn -> quantity `max` tokenQuantity tn) zero - (flattenNonAdaValue nonAdaAssets) - -unwrapNonAdaAsset :: NonAdaAsset -> Map CurrencySymbol (Map TokenName BigInt) -unwrapNonAdaAsset (NonAdaAsset mp) = mp - --- We shouldn't need this check if we don't export unsafeAdaSymbol etc. --- | Create a singleton `NonAdaAsset` which by definition should be safe since --- | `CurrencySymbol` and `TokenName` are safe -mkSingletonNonAdaAsset - :: CurrencySymbol - -> TokenName - -> BigInt - -> NonAdaAsset -mkSingletonNonAdaAsset curSymbol tokenName amount - | amount == zero = mempty - | otherwise = - NonAdaAsset $ Map.singleton curSymbol $ Map.singleton tokenName amount - --- Assume all CurrencySymbol are well-formed at this point, since they come from --- mkCurrencySymbol and mkTokenName. --- | Given the relevant map, create a normalized `NonAdaAsset`. -mkNonAdaAsset :: Map CurrencySymbol (Map TokenName BigInt) -> NonAdaAsset -mkNonAdaAsset = normalizeNonAdaAsset <<< NonAdaAsset - -mkNonAdaAssetsFromTokenMap' - :: forall (t :: Type -> Type) - . Traversable t - => t (ByteArray /\ Map TokenName BigInt) - -> Maybe (Map CurrencySymbol (Map TokenName BigInt)) -mkNonAdaAssetsFromTokenMap' = - traverse (ltraverse mkCurrencySymbol) >>> map Map.fromFoldable - --- | Creates a `NonAdaAsset` from bytearrays and already safely created `TokenName` --- | map -mkNonAdaAssetsFromTokenMap - :: forall (t :: Type -> Type) - . Traversable t - => t (ByteArray /\ Map TokenName BigInt) - -> Maybe NonAdaAsset -mkNonAdaAssetsFromTokenMap xs = mkNonAdaAssetsFromTokenMap' xs <#> mkNonAdaAsset - -mkNonAdaAssets' - :: forall (s :: Type -> Type) (t :: Type -> Type) - . Traversable s - => Traversable t - => s (ByteArray /\ t (ByteArray /\ BigInt)) - -> Maybe (Map CurrencySymbol (Map TokenName BigInt)) -mkNonAdaAssets' = - traverse (bitraverse mkCurrencySymbol mkTokenNames) >>> map Map.fromFoldable - --- | Given a `Traversable` of `ByteArray`s and amounts to safely convert into a --- | `NonAdaAsset` -mkNonAdaAssets - :: forall (s :: Type -> Type) (t :: Type -> Type) - . Traversable s - => Traversable t - => s (ByteArray /\ t (ByteArray /\ BigInt)) - -> Maybe NonAdaAsset -mkNonAdaAssets xs = mkNonAdaAssets' xs <#> mkNonAdaAsset - -getNonAdaAsset :: Value -> NonAdaAsset -getNonAdaAsset (Value _ nonAdaAsset) = nonAdaAsset - --- This is safe assuming we don't export `unsafeAdaSymbol` as user would need to --- construct `CurrencySymbol` and `TokenName` safely. -getNonAdaAsset' :: Value -> Map CurrencySymbol (Map TokenName BigInt) -getNonAdaAsset' (Value _ (NonAdaAsset nonAdaAsset)) = nonAdaAsset - --------------------------------------------------------------------------------- --- Value --------------------------------------------------------------------------------- --- | In Plutus, Ada is is stored inside the map (with currency symbol and token --- | name being empty bytestrings). cardano-serialization-lib makes semantic --- | distinction between native tokens and Ada, and we follow this convention. -data Value = Value Coin NonAdaAsset - -derive instance Generic Value _ -derive instance Eq Value - -instance Arbitrary Value where - arbitrary = Value <$> arbitrary <*> arbitrary - -instance Show Value where - show = genericShow - -instance Semigroup Value where - append (Value c1 m1) (Value c2 m2) = Value (c1 <> c2) (m1 <> m2) - -instance Monoid Value where - mempty = Value mempty mempty - -instance JoinSemilattice Value where - join (Value c1 m1) (Value c2 m2) = Value (c1 `join` c2) (m1 `join` m2) - -instance MeetSemilattice Value where - meet (Value c1 m1) (Value c2 m2) = Value (c1 `meet` c2) (m1 `meet` m2) - -instance Negate Value where - negation (Value coin nonAdaAsset) = - Value (negation coin) (negation nonAdaAsset) - -instance Split Value where - split (Value coin nonAdaAsset) = - bimap (flip Value mempty) (flip Value mempty) (split coin) - <> bimap (Value mempty) (Value mempty) (split nonAdaAsset) - -instance EncodeAeson Value where - encodeAeson (Value coin nonAdaAsset) = encodeAeson - { coin - , nonAdaAsset - } - -instance Equipartition Value where - equipartition (Value coin nonAdaAssets) numParts = - NEArray.zipWith mkValue - (equipartition coin numParts) - (equipartition nonAdaAssets numParts) - -pprintValue :: Value -> TagSet -pprintValue value = TagSet.fromArray $ - [ "Lovelace" `tag` BigInt.toString (unwrap (valueToCoin value)) ] - <> - if nonAdaAssets /= mempty then - [ "Assets" `tagSetTag` pprintNonAdaAsset nonAdaAssets ] - else [] - where - nonAdaAssets = getNonAdaAsset value - --- | Partitions a `Value` into smaller `Value`s, where the Ada amount and the --- | quantity of each token is equipartitioned across the resultant `Value`s, --- | with the goal that no token quantity in any of the resultant `Value`s --- | exceeds the given upper bound. --- | Taken from cardano-wallet: --- | https://github.com/input-output-hk/cardano-wallet/blob/d4b30de073f2b5eddb25bf12c2453abb42e8b352/lib/wallet/src/Cardano/Wallet/Primitive/Types/TokenBundle.hs#L381 -equipartitionValueWithTokenQuantityUpperBound - :: BigInt -> Value -> NonEmptyArray Value -equipartitionValueWithTokenQuantityUpperBound maxTokenQuantity value = - let - Value coin nonAdaAssets = value - ms /\ numParts = - equipartitionAssetsWithTokenQuantityUpperBound nonAdaAssets - maxTokenQuantity - in - NEArray.zipWith mkValue (equipartition coin numParts) ms - --- | Create a `Value` from `Coin` and `NonAdaAsset`, the latter should have been --- | constructed safely at this point. -mkValue :: Coin -> NonAdaAsset -> Value -mkValue = Value - --- | Creates a singleton value given two byte arrays for currency symbol and --- | token name respectively -mkSingletonValue :: ByteArray -> ByteArray -> BigInt -> Maybe Value -mkSingletonValue curSymbol' tokenName' amount = do - curSymbol <- mkCurrencySymbol curSymbol' <|> mkUnsafeAdaSymbol curSymbol' - tokenName <- mkTokenName tokenName' - mkSingletonValue' curSymbol tokenName amount - --- Similar to `mkSingletonValue` but the user has a `CurrencySymbol` and `TokenName` --- at hand. This could be exported (and used only for `NonAdaAsset`) or internally --- for both `Coin` and `NonAdaAsset`. -mkSingletonValue' :: CurrencySymbol -> TokenName -> BigInt -> Maybe Value -mkSingletonValue' curSymbol tokenName amount = do - let isAdaCs = curSymbol == unsafeAdaSymbol - -- Can't have a non-empty TokenName with Ada CurrencySymbol. I.e. It's either - -- not an Ada currency symbol (with any valid TokenName) or an Ada currency - -- symbol with an empty TokenName - guard $ not isAdaCs || (isAdaCs && tokenName == adaToken) - pure - if isAdaCs then Value (Coin amount) mempty - else Value mempty $ mkSingletonNonAdaAsset curSymbol tokenName amount - --------------------------------------------------------------------------------- --- AssetClass --------------------------------------------------------------------------------- - -data AssetClass = AssetClass CurrencySymbol TokenName - -derive instance Generic AssetClass _ -derive instance Eq AssetClass -derive instance Ord AssetClass - -instance Arbitrary AssetClass where - arbitrary = AssetClass <$> arbitrary <*> arbitrary - -instance Show AssetClass where - show = genericShow - -assetToValue :: AssetClass -> BigInt -> Value -assetToValue (AssetClass cs tn) quantity = - mkValue mempty (mkSingletonNonAdaAsset cs tn quantity) - -getAssetQuantity :: AssetClass -> Value -> BigInt -getAssetQuantity (AssetClass cs tn) value = valueOf value cs tn - -valueAssets :: Value -> Array (AssetClass /\ BigInt) -valueAssets (Value _ assets) = - Array.fromFoldable (flattenNonAdaValue assets) - <#> \(cs /\ tn /\ quantity) -> AssetClass cs tn /\ quantity - -valueAssetClasses :: Value -> Array AssetClass -valueAssetClasses = map fst <<< valueAssets - --------------------------------------------------------------------------------- --- Helpers --------------------------------------------------------------------------------- - --- | Normalize `NonAdaAsset` so that it doesn't contain zero-valued tokens. -normalizeNonAdaAsset :: NonAdaAsset -> NonAdaAsset -normalizeNonAdaAsset = filterNonAdaAsset (notEq zero) - -posNonAdaAsset :: NonAdaAsset -> NonAdaAsset -posNonAdaAsset = filterNonAdaAsset (\x -> x > zero) - -filterNonAdaAsset :: (BigInt -> Boolean) -> NonAdaAsset -> NonAdaAsset -filterNonAdaAsset p (NonAdaAsset mp) = - NonAdaAsset $ Map.filter (not Map.isEmpty) $ Map.filter p <$> mp - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-tx/html/src/PlutusTx.AssocMap.html#union --- | Combine two `Map`s. -union :: ∀ k v r. Ord k => Map k v -> Map k r -> Map k (These v r) -union l r = - let - ls :: Array (k /\ v) - ls = Map.toUnfoldable l - - rs :: Array (k /\ r) - rs = Map.toUnfoldable r - - f :: v -> Maybe r -> These v r - f a b' = case b' of - Nothing -> This a - Just b -> Both a b - - ls' :: Array (k /\ These v r) - ls' = map (\(c /\ i) -> (c /\ f i (Map.lookup c (Map.fromFoldable rs)))) ls - - rs' :: Array (k /\ r) - rs' = filter (\(c /\ _) -> not (any (\(c' /\ _) -> c' == c) ls)) rs - - rs'' :: Array (k /\ These v r) - rs'' = map (map That) rs' - in - Map.fromFoldable (ls' <> rs'') - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#unionVal --- | Combine two `NonAdaAsset` maps -unionNonAda - :: NonAdaAsset - -> NonAdaAsset - -> Map CurrencySymbol (Map TokenName (These BigInt BigInt)) -unionNonAda (NonAdaAsset l) (NonAdaAsset r) = - let - combined - :: Map CurrencySymbol - (These (Map TokenName BigInt) (Map TokenName BigInt)) - combined = union l r - - unBoth - :: These (Map TokenName BigInt) (Map TokenName BigInt) - -> Map TokenName (These BigInt BigInt) - unBoth k = case k of - This a -> This <$> a - That b -> That <$> b - Both a b -> union a b - in - unBoth <$> combined - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#unionWith --- | Same as `unionWith` but specifically for `NonAdaAsset` -unionWithNonAda - :: (BigInt -> BigInt -> BigInt) - -> NonAdaAsset - -> NonAdaAsset - -> NonAdaAsset -unionWithNonAda f ls rs = - let - combined :: Map CurrencySymbol (Map TokenName (These BigInt BigInt)) - combined = unionNonAda ls rs - - unBoth :: These BigInt BigInt -> BigInt - unBoth k' = case k' of - This a -> f a zero - That b -> f zero b - Both a b -> f a b - in - normalizeNonAdaAsset $ - NonAdaAsset (map unBoth <$> combined) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#unionWith --- | Combines `Value` with a binary function on `BigInt`s. -unionWith - :: (BigInt -> BigInt -> BigInt) - -> Value - -> Value - -> Value -unionWith f (Value (Coin c) na) (Value (Coin c') na') = - Value (Coin $ f c c') (unionWithNonAda f na na') - --- Based on https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#flattenValue --- Flattens non-Ada Value into a list -flattenNonAdaValue - :: NonAdaAsset -> List (CurrencySymbol /\ TokenName /\ BigInt) -flattenNonAdaValue (NonAdaAsset nonAdaAsset) = do - cs /\ m <- toUnfoldable nonAdaAsset - tn /\ a <- toUnfoldable m - guard $ a /= zero - pure $ cs /\ tn /\ a - --- Flattens Value guarding against zeros -unsafeFlattenValue :: Value -> List (CurrencySymbol /\ TokenName /\ BigInt) -unsafeFlattenValue (Value coin@(Coin lovelaces) nonAdaAsset) = - let - flattenedNonAda :: List (CurrencySymbol /\ TokenName /\ BigInt) - flattenedNonAda = flattenNonAdaValue nonAdaAsset - in - case coin == mempty of - true -> flattenedNonAda - false -> (unsafeAdaSymbol /\ adaToken /\ lovelaces) : flattenedNonAda - --- From https://github.com/mlabs-haskell/bot-plutus-interface/blob/master/src/BotPlutusInterface/PreBalance.hs --- Converts a single tuple to Value -unflattenValue :: CurrencySymbol /\ TokenName /\ BigInt -> Maybe Value -unflattenValue (curSymbol /\ tokenName /\ amount) = - mkSingletonValue' curSymbol tokenName amount - --- | Predicate on whether some `Value` contains Ada only. -isAdaOnly :: Value -> Boolean -isAdaOnly v = - case unsafeFlattenValue v of - (cs /\ tn /\ _) : Nil -> - cs == unsafeAdaSymbol && - tn == adaToken - _ -> false - -minus :: Value -> Value -> Value -minus lhs rhs = - let - negativeValues :: List (CurrencySymbol /\ TokenName /\ BigInt) - negativeValues = unsafeFlattenValue rhs <#> - (\(c /\ t /\ a) -> c /\ t /\ negate a) - in - unsafePartial $ - lhs <> fold (fromJust $ traverse unflattenValue negativeValues) - --- From https://github.com/mlabs-haskell/bot-plutus-interface/blob/master/src/BotPlutusInterface/PreBalance.hs --- "isValueNat" uses unsafeFlattenValue which guards against zeros, so non-strict --- inequality is redundant. So we use strict equality instead. -isPos :: Value -> Boolean -isPos = all (\(_ /\ _ /\ a) -> a > zero) <<< unsafeFlattenValue - --- From https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#isZero --- | Check whether a `Value` is zero. -isZero :: Value -> Boolean -isZero (Value coin (NonAdaAsset nonAdaAsset)) = - all (all ((==) zero)) nonAdaAsset && coin == mempty - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#checkPred -checkPred :: (These BigInt BigInt -> Boolean) -> Value -> Value -> Boolean -checkPred f (Value (Coin l) ls) (Value (Coin r) rs) = - let - inner :: Map TokenName (These BigInt BigInt) -> Boolean - inner = all f -- this "all" may need to be checked? - in - f (Both l r) && all inner (unionNonAda ls rs) -- this "all" may need to be checked? - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#checkBinRel --- Check whether a binary relation holds for value pairs of two `Value` maps, --- supplying 0 where a key is only present in one of them. -checkBinRel :: (BigInt -> BigInt -> Boolean) -> Value -> Value -> Boolean -checkBinRel f l r = - let - unThese :: These BigInt BigInt -> Boolean - unThese k' = case k' of - This a -> f a zero - That b -> f zero b - Both a b -> f a b - in - checkPred unThese l r - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#geq --- | Check whether one `Value` is greater than or equal to another. See `Value` for an explanation of how operations on `Value`s work. -geq :: Value -> Value -> Boolean --- If both are zero then checkBinRel will be vacuously true, but this is fine. -geq = checkBinRel (>=) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#gt --- | Check whether one `Value` is strictly greater than another. See `Value` for an explanation of how operations on `Value`s work. -gt :: Value -> Value -> Boolean --- If both are zero then checkBinRel will be vacuously true. So we have a special case. -gt l r = not (isZero l && isZero r) && checkBinRel (>) l r - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#leq --- | Check whether one `Value` is less than or equal to another. See `Value` for an explanation of how operations on `Value`s work. -leq :: Value -> Value -> Boolean --- If both are zero then checkBinRel will be vacuously true, but this is fine. -leq = checkBinRel (<=) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#lt --- | Check whether one `Value` is strictly less than another. See `Value` for an explanation of how operations on `Value`s work. -lt :: Value -> Value -> Boolean --- If both are zero then checkBinRel will be vacuously true. So we have a special case. -lt l r = not (isZero l && isZero r) && checkBinRel (<) l r - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#eq --- | Check whether one `Value` is equal to another. See `Value` for an explanation of how operations on `Value`s work. -eq :: Value -> Value -> Boolean --- If both are zero then checkBinRel will be vacuously true, but this is fine. -eq = checkBinRel (==) - -unsafeIsAda :: CurrencySymbol -> TokenName -> Boolean -unsafeIsAda curSymbol tokenName = - curSymbol == unsafeAdaSymbol && - tokenName == adaToken - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#valueOf --- | Get the quantity of the given currency in the `Value`. -valueOf :: Value -> CurrencySymbol -> TokenName -> BigInt -valueOf (Value (Coin lovelaces) (NonAdaAsset nonAdaAsset)) curSymbol tokenName = - case unsafeIsAda curSymbol tokenName of - false -> - case lookup curSymbol nonAdaAsset of - Nothing -> zero - Just i -> case lookup tokenName i of - Nothing -> zero - Just v -> v - true -> lovelaces - --- | The number of distinct non-Ada assets. -numNonAdaAssets :: Value -> BigInt -numNonAdaAssets (Value _ nonAdaAssets) = - length (flattenNonAdaValue nonAdaAssets) - --- | The number of distinct non-Ada currency symbols, i.e. the number of policy --- | IDs not including Ada in `Coin`. -numNonAdaCurrencySymbols :: Value -> BigInt -numNonAdaCurrencySymbols (Value _ nonAdaAssets) = - fromInt <<< length <<< List.nubByEq ((==) `on` fst) $ - flattenNonAdaValue nonAdaAssets - --- | The number of distinct currency symbols, i.e. the number of policy IDs --- | including Ada in `Coin`. -numCurrencySymbols :: Value -> BigInt -numCurrencySymbols value@(Value coin _) - | coin == mempty = - numNonAdaCurrencySymbols value - | otherwise = - one + numNonAdaCurrencySymbols value - --- Don't export this, we don't really care about the v in k,v. -unsafeAllTokenNames' :: Value -> Map TokenName BigInt -unsafeAllTokenNames' (Value coin@(Coin lovelaces) (NonAdaAsset nonAdaAsset)) = - let - nonAdaUnion :: Map TokenName BigInt - nonAdaUnion = unions $ values nonAdaAsset - in - case coin == mempty of - false -> nonAdaUnion - true -> Map.singleton adaToken lovelaces `Map.union` nonAdaUnion - --- Don't export as we don't to expose tokenNames although may be it's okay --- given `mkTokenName` doesn't need to be `Maybe`. -unsafeAllTokenNames :: Value -> Set TokenName -unsafeAllTokenNames = keys <<< unsafeAllTokenNames' - --- | The number of distinct token names. -numTokenNames :: Value -> BigInt -numTokenNames = length <<< unsafeAllTokenNames' - --- https://cardano-ledger.readthedocs.io/en/latest/explanations/min-utxo-mary.html --- The formula is actually based on the length of the bytestring --- representation - test this. --- | Sum of the length of the strings of distinct token names. -sumTokenNameLengths :: Value -> BigInt -sumTokenNameLengths = foldl lenAdd zero <<< unsafeAllTokenNames - where - lenAdd :: BigInt -> TokenName -> BigInt - lenAdd = \c a -> c + (fromInt <<< byteLength <<< getTokenName $ a) - --- From https://github.com/mlabs-haskell/bot-plutus-interface/blob/master/src/BotPlutusInterface/PreBalance.hs --- | Filter a value to contain only non Ada assets -filterNonAda :: Value -> Value -filterNonAda (Value _ nonAda) = Value mempty nonAda - --- I think this is safe because a CurrencySymbol can only be constructed by --- checking scriptHashFromBytes so it must be a valid ScriptHash too. Otherwise --- we'd have a Maybe context from scriptHashFromBytes again from something we --- already know is a valid CurrencySymbol -currencyScriptHash :: CurrencySymbol -> ScriptHash -currencyScriptHash (CurrencySymbol byteArray) = - unsafePartial fromJust $ scriptHashFromBytes byteArray - -scriptHashAsCurrencySymbol :: ScriptHash -> CurrencySymbol -scriptHashAsCurrencySymbol = CurrencySymbol <<< unwrap <<< scriptHashToBytes - --- | The minting policy hash of a currency symbol -currencyMPSHash :: CurrencySymbol -> MintingPolicyHash -currencyMPSHash = MintingPolicyHash <<< currencyScriptHash - --- We haven't provided any safety on MintingPolicyHash, analagous to --- CurrencySymbol, so we need Maybe context. We could remove Maybe if we do. --- Plutus doesn't use Maybe here. --- | The currency symbol of a monetary policy hash -mpsSymbol :: MintingPolicyHash -> Maybe CurrencySymbol -mpsSymbol (MintingPolicyHash h) = mkCurrencySymbol $ unwrap $ scriptHashToBytes - h - --- Like `mapEither` that works with 'These'. -mapThese - :: forall (a :: Type) (b :: Type) (k :: Type) (v :: Type) - . Ord k - => (v -> These a b) - -> Map k v - -> Map k a /\ Map k b -mapThese f mps = - bimap Map.fromFoldable Map.fromFoldable $ foldrWithIndex f' ([] /\ []) mps' - where - mps' :: Map k (These a b) - mps' = map f mps - - f' - :: k - -> These a b - -> Array (k /\ a) /\ Array (k /\ b) - -> Array (k /\ a) /\ Array (k /\ b) - f' k v (as /\ bs) = case v of - This a -> (k /\ a) `cons` as /\ bs - That b -> as /\ (k /\ b) `cons` bs - Both a b -> (k /\ a) `cons` as /\ (k /\ b) `cons` bs diff --git a/src/Internal/CardanoCli.purs b/src/Internal/CardanoCli.purs new file mode 100644 index 0000000000..05e44adfd9 --- /dev/null +++ b/src/Internal/CardanoCli.purs @@ -0,0 +1,228 @@ +module Ctl.Internal.CardanoCli + ( CardanoNodeInstance + , CardanoCliTxOutInfo + , queryUtxosViaCardanoCli + , cardanoCliTxOutInfoToUtxo + ) where + +import Contract.Prelude + +import Cardano.Serialization.Lib as CSL +import Cardano.Types as Cardano.Types +import Cardano.Types.Address as Cardano.Types.Address +import Cardano.Types.AssetName as Cardano.Types.AssetName +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Value as Cardano.Types.Value +import Contract.Value as Contract.Value +import Control.Alt ((<|>)) +import Control.Monad.Except (throwError) +import Control.Parallel (parallel, sequential) +import Ctl.Internal.Spawn as Ctl.Internal.Spawn +import Ctl.Internal.Testnet.Utils (annotateError) +import Data.Array as Array +import Data.Bifunctor (lmap) +import Data.ByteArray (ByteArray) +import Data.ByteArray as Data.ByteArray +import Data.List as List +import Data.String (Pattern(Pattern), split, trim) as String +import Data.String.CodeUnits (fromCharArray) as String +import Data.UInt (UInt) +import Data.UInt as UInt +import Effect.Exception (error) +import Node.Buffer as Node.Buffer +import Node.ChildProcess as Node.ChildProcess +import Node.Encoding as Node.Encoding +import Node.Path as Node.Path +import Node.Stream.Aff as Node.Stream.Aff +import Parsing as Parsing +import Parsing.Combinators as Parsing.Combinators +import Parsing.String as Parsing.String +import Parsing.String.Basic as Parsing.String.Basic + +type CardanoNodeInstance = + { socketPath :: Node.Path.FilePath + , testnetMagic :: Int + } + +cardanoCliTxOutInfoToUtxo + :: Cardano.Types.Address + -> CardanoCliTxOutInfo + -> Cardano.Types.TransactionInput /\ Cardano.Types.TransactionOutput +cardanoCliTxOutInfoToUtxo address { input: { txHash, txOutId }, amount } = + let + txIn = Cardano.Types.TransactionInput + { index: txOutId, transactionId: txHash } + txOut = Cardano.Types.TransactionOutput + { address + , amount + , datum: Nothing + , scriptRef: Nothing + } + in + txIn /\ txOut + +type CardanoCliTxOutInfo = + { input :: + { txHash :: Cardano.Types.TransactionHash + , txOutId :: UInt + } + , amount :: Cardano.Types.Value -- Coin + } + +-- | A line of the CLI output of 'cardano-cli query utxo' containing utxo information +newtype CliUtxo = CliUtxo String + +parseTxOutIgnoringDatums + :: CliUtxo -> Either Parsing.ParseError CardanoCliTxOutInfo +parseTxOutIgnoringDatums (CliUtxo src) = Parsing.runParser src do + Parsing.String.Basic.skipSpaces + txHash <- parseTxHash + Parsing.String.Basic.skipSpaces + txOutId <- parseTxOutputIndex + let + txDatumBegin = + Parsing.String.string "TxOutDatumNone" + <|> Parsing.String.string "TxOutDatumInline" + <|> Parsing.String.string "TxOutDatumHash" + + Parsing.String.Basic.skipSpaces + rawValues <- Parsing.Combinators.manyTill + (parseAsset <* Parsing.String.string " + ") + txDatumBegin + value <- + noteParser "Can't sum up asset amounts" + $ Contract.Value.sum + $ Array.fromFoldable rawValues + pure + { input: { txHash, txOutId } + , amount: value + } + +-- | Queries address funds via cardano-cli and returns the first UTxO data. +-- Note, that it assumes no output datum and script ref. +queryUtxosViaCardanoCli + :: CardanoNodeInstance + -> Cardano.Types.Address + -> Aff (Array CardanoCliTxOutInfo) +queryUtxosViaCardanoCli { socketPath, testnetMagic } address = + annotateError "queryUtxosViaCardanoCli" do + { stdout } <- execCardanoCli + [ "query" + , "utxo" + , "--socket-path" + , socketPath + , "--testnet-magic" + , show testnetMagic + , "--address" + , Cardano.Types.Address.toBech32 address + ] + let + parsingError utxos (Parsing.ParseError msg pos) = mconcat + [ "Cannot parse UTxOs: " + , show utxos + , " because of " + , msg + , " at " + , show pos + ] + case List.fromFoldable stdout of + List.Cons _ (List.Cons _ utxos) -> + map Array.fromFoldable + <<< liftEither + <<< lmap (error <<< parsingError utxos) + $ for utxos (parseTxOutIgnoringDatums <<< CliUtxo) + _ -> throwError $ error $ "Output is too short " <> show stdout + +execCardanoCli + :: Array String + -> Aff + { stdout :: Array String + , process :: Node.ChildProcess.ChildProcess + } +execCardanoCli params = annotateError "execCardanoCli" do + let cmd = "cardano-cli " <> intercalate " " params + { channels, process } <- Ctl.Internal.Spawn.exec cmd + let + bufferToLines = + map (String.split (String.Pattern "\n") <<< String.trim) + <<< liftEffect + <<< Node.Buffer.toString Node.Encoding.UTF8 + output <- sequential ado + stderr <- parallel + $ map join + <<< traverse bufferToLines + <<< fst + =<< Node.Stream.Aff.readAll channels.stderr + stdout <- parallel + $ map join + $ traverse bufferToLines + <<< fst + =<< Node.Stream.Aff.readAll channels.stdout + in { stderr, stdout } + when (not $ Array.null output.stderr) do + throwError + $ error + $ intercalate "\n" output.stderr + pure { stdout: output.stdout, process } + +-- * Parsing + +parseTxOutputIndex :: Parsing.Parser String UInt +parseTxOutputIndex = parseNatural \n -> + note ("Can't parse Tx output index: " <> n) + $ UInt.fromString n + +parseAsset :: Parsing.Parser String Cardano.Types.Value +parseAsset = do + amount <- parseAmount + Parsing.String.Basic.skipSpaces + parseLovelace amount <|> parseNativeAsset amount + where + parseAmount = parseNatural \n -> + note ("Can't parse asset amount: " <> n) + $ BigNum.fromString n + parseLovelace amount = ado + void $ Parsing.String.string "lovelace" + in Cardano.Types.Value.coinToValue $ wrap amount + parseNativeAsset amount = ado + cs <- parseScriptHash + void $ Parsing.String.char '.' + tn <- parseAssetName + in Contract.Value.singleton cs tn amount + +parseTxHash :: Parsing.Parser String Cardano.Types.TransactionHash +parseTxHash = map wrap + <<< noteParser "Cannot parse tx hash from byte array" + <<< CSL.fromBytes + =<< parseHex + +parseScriptHash :: Parsing.Parser String Cardano.Types.ScriptHash +parseScriptHash = parseHex >>= \bytes -> + map wrap + $ noteParser ("Cannot parse script hash from byte array" <> show bytes) + $ CSL.fromBytes bytes + +parseAssetName :: Parsing.Parser String Cardano.Types.AssetName +parseAssetName = + noteParser "Cannot create asset name from the parsed bytes" + <<< Cardano.Types.AssetName.mkAssetName + =<< parseHex + +makeString :: forall f. Foldable f => f Char -> String +makeString = String.fromCharArray <<< Array.fromFoldable + +parseNatural :: forall n. (String -> Either String n) -> Parsing.Parser String n +parseNatural toNumber = Parsing.liftEither + <<< toNumber + <<< makeString + =<< Parsing.Combinators.many Parsing.String.Basic.digit + +noteParser :: forall s a. String -> Maybe a -> Parsing.Parser s a +noteParser err = Parsing.liftEither <<< note err + +parseHex :: Parsing.Parser String ByteArray +parseHex = + noteParser "Cannot parse hex-encoded byte array" + <<< Data.ByteArray.hexToByteArray + <<< makeString + =<< Parsing.Combinators.many Parsing.String.Basic.hexDigit diff --git a/src/Internal/CardanoCli/QueryHandler.purs b/src/Internal/CardanoCli/QueryHandler.purs new file mode 100644 index 0000000000..3ab6b09383 --- /dev/null +++ b/src/Internal/CardanoCli/QueryHandler.purs @@ -0,0 +1,93 @@ +module Internal.CardanoCli.QueryHandler + ( withCardanoCliCompletion + ) where + +import Contract.Prelude + +import Cardano.Types as Cardano.Types +import Cardano.Types.Address (Address) +import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.TransactionOutput (TransactionOutput) +import Contract.ClientError as Contract.ClientError +import Contract.Monad (Contract, ContractEnv) +import Control.Alt ((<|>)) +import Control.Monad.Error.Class (try) +import Control.Monad.Except (ExceptT(ExceptT), runExceptT) +import Control.Monad.Reader (local) +import Ctl.Internal.CardanoCli as CardanoCli +import Data.Bifunctor (bimap) +import Data.Lens (Lens', (%~)) +import Data.Lens.Record (prop) +import Data.Map as Map +import Effect.Exception (Error, message) +import Type.Proxy (Proxy(Proxy)) + +type UtxosAtQuery = + Cardano.Types.Address + -> Aff (Either Contract.ClientError.ClientError Cardano.Types.UtxoMap) + +type GetUtxoByOrefQuery = + TransactionInput + -> Aff (Either Contract.ClientError.ClientError (Maybe TransactionOutput)) + +-- | Adds to the utxosAt results UTxOs found by cardano-cli but not found by the current 'utxosAt' query. +-- UTxOs found by cardano-cli assumed to have no datum or script ref. +withCardanoCliCompletion + :: forall a + . CardanoCli.CardanoNodeInstance + -> Address + -> Contract a + -> Contract a +withCardanoCliCompletion node genesisAddr = + local $ (utxosAtL %~ completeUtxosAt node) >>> + (getUtxoByOrefL %~ completeGetUtxoByOref node genesisAddr) + +utxosAtL :: Lens' ContractEnv UtxosAtQuery +utxosAtL = prop (Proxy :: _ "handle") <<< prop (Proxy :: _ "utxosAt") + +getUtxoByOrefL :: Lens' ContractEnv GetUtxoByOrefQuery +getUtxoByOrefL = prop (Proxy :: _ "handle") <<< prop + (Proxy :: _ "getUtxoByOref") + +-- | Adds to the results UTxOs found by cardano-cli but not found by the given 'utxosAt' query. +-- UTxOs found by cardano-cli assumed to have no datum or script ref. +completeUtxosAt + :: CardanoCli.CardanoNodeInstance + -> UtxosAtQuery + -> UtxosAtQuery +completeUtxosAt node utxosAt address = runExceptT do + let + toCliError :: Error -> Contract.ClientError.ClientError + toCliError = Contract.ClientError.ClientOtherError <<< message + + toUtxoMap :: Array CardanoCli.CardanoCliTxOutInfo -> Cardano.Types.UtxoMap + toUtxoMap = Map.fromFoldable + <<< map (CardanoCli.cardanoCliTxOutInfoToUtxo address) + cardanoCliUtxos <- ExceptT + $ map (bimap toCliError toUtxoMap) + $ try + $ CardanoCli.queryUtxosViaCardanoCli node address + kupoUtxos <- ExceptT $ utxosAt address + pure $ Map.union kupoUtxos cardanoCliUtxos + +-- | Adds to the results UTxOs found by cardano-cli but not found by the given 'getUtxoByOref' query. +-- UTxOs found by cardano-cli assumed to have no datum or script ref. +completeGetUtxoByOref -- FIXME + :: CardanoCli.CardanoNodeInstance + -> Address + -> GetUtxoByOrefQuery + -> GetUtxoByOrefQuery +completeGetUtxoByOref node address getUtxoByOref oref = runExceptT do + let + toCliError :: Error -> Contract.ClientError.ClientError + toCliError = Contract.ClientError.ClientOtherError <<< message + + toUtxoMap :: Array CardanoCli.CardanoCliTxOutInfo -> Cardano.Types.UtxoMap + toUtxoMap = Map.fromFoldable + <<< map (CardanoCli.cardanoCliTxOutInfoToUtxo address) + cardanoCliUtxos <- ExceptT + $ map (bimap toCliError toUtxoMap) + $ try + $ CardanoCli.queryUtxosViaCardanoCli node address + mUtxo <- ExceptT $ getUtxoByOref oref + pure $ mUtxo <|> Map.lookup oref cardanoCliUtxos diff --git a/src/Internal/CoinSelection/UtxoIndex.purs b/src/Internal/CoinSelection/UtxoIndex.purs index 3ee70c1fe2..b0905d889d 100644 --- a/src/Internal/CoinSelection/UtxoIndex.purs +++ b/src/Internal/CoinSelection/UtxoIndex.purs @@ -1,6 +1,5 @@ module Ctl.Internal.CoinSelection.UtxoIndex - ( Asset(Asset, AssetLovelace) - , SelectionFilter(SelectAnyWith, SelectPairWith, SelectSingleton) + ( SelectionFilter(SelectAnyWith, SelectPairWith, SelectSingleton) , TxUnspentOutput , UtxoIndex , UtxoIndexInvariantStatus @@ -22,18 +21,18 @@ module Ctl.Internal.CoinSelection.UtxoIndex import Prelude -import Ctl.Internal.Cardano.Types.Transaction - ( TransactionOutput(TransactionOutput) - , UtxoMap - ) -import Ctl.Internal.Cardano.Types.Value (AssetClass, Value) -import Ctl.Internal.Cardano.Types.Value - ( getAssetQuantity - , valueAssetClasses +import Cardano.Types (AssetClass, Value) +import Cardano.Types.Asset (Asset(AdaAsset)) +import Cardano.Types.Asset as Asset +import Cardano.Types.BigNum as BigNum +import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.TransactionOutput (TransactionOutput(TransactionOutput)) +import Cardano.Types.UtxoMap (UtxoMap) +import Cardano.Types.Value + ( valueAssetClasses , valueAssets - , valueToCoin' + , valueOf ) as Value -import Ctl.Internal.Types.Transaction (TransactionInput) import Data.Array (all, foldl) as Array import Data.Array ((!!)) import Data.Array.NonEmpty (cons') @@ -107,20 +106,6 @@ instance Show UtxoIndex where utxoIndexUniverse :: UtxoIndex -> UtxoMap utxoIndexUniverse = view _utxos --- | Taken from cardano-wallet: --- | https://github.com/input-output-hk/cardano-wallet/blob/791541da69b9b3f434bb9ead43de406cc18b0373/lib/primitive/lib/Cardano/Wallet/Primitive/Types/UTxOIndex/Internal.hs#L485 -data Asset = AssetLovelace | Asset AssetClass - -derive instance Generic Asset _ -derive instance Eq Asset -derive instance Ord Asset - -instance Show Asset where - show = genericShow - -instance Arbitrary Asset where - arbitrary = oneOf $ cons' (pure AssetLovelace) [ Asset <$> arbitrary ] - -- | Indicates whether or not a given bundle includes a given asset. -- | -- | Both ada and non-ada assets can be queried. @@ -128,10 +113,8 @@ instance Arbitrary Asset where -- | Taken from cardano-wallet: -- | https://github.com/input-output-hk/cardano-wallet/blob/9d73b57e23392e25148cfc8db560cb8f656cb56a/lib/primitive/lib/Cardano/Wallet/Primitive/Types/UTxOIndex/Internal.hs#L526 valueHasAsset :: Value -> Asset -> Boolean -valueHasAsset amount AssetLovelace = - (Value.valueToCoin' amount) > (BigInt.fromInt 0) -valueHasAsset amount (Asset asset) = - Value.getAssetQuantity asset amount >= one +valueHasAsset amount asset = + Value.valueOf asset amount > BigNum.zero -------------------------------------------------------------------------------- -- Builders @@ -203,17 +186,20 @@ updateUtxoIndex updateUtxoIndex out manageEntry = case categorizeUtxoEntry out of BundleWithNoAssets -> - _indexSingletons %~ manageEntry AssetLovelace - BundleWithOneAsset asset -> - (_indexPairs %~ manageEntry AssetLovelace) - <<< (_indexSingletons %~ manageEntry (Asset asset)) + _indexSingletons %~ manageEntry AdaAsset + BundleWithOneAsset assetClass -> + (_indexPairs %~ manageEntry AdaAsset) + <<< (_indexSingletons %~ manageEntry (Asset.fromAssetClass assetClass)) BundleWithTwoAssets asset0 asset1 -> - (_indexAnyWith %~ manageEntry AssetLovelace) - <<< (_indexPairs %~ manageEntry (Asset asset0)) - <<< (_indexPairs %~ manageEntry (Asset asset1)) + (_indexAnyWith %~ manageEntry AdaAsset) + <<< (_indexPairs %~ manageEntry (Asset.fromAssetClass asset0)) + <<< (_indexPairs %~ manageEntry (Asset.fromAssetClass asset1)) BundleWithMultipleAssets assets -> - (_indexAnyWith %~ flip (foldl (flip (manageEntry <<< Asset))) assets) - <<< (_indexAnyWith %~ manageEntry AssetLovelace) + ( _indexAnyWith %~ flip + (foldl (flip (manageEntry <<< Asset.fromAssetClass))) + assets + ) + <<< (_indexAnyWith %~ manageEntry AdaAsset) -- | Taken from cardano-wallet: -- | https://github.com/input-output-hk/cardano-wallet/blob/791541da69b9b3f434bb9ead43de406cc18b0373/lib/primitive/lib/Cardano/Wallet/Primitive/Types/UTxOIndex/Internal.hs#L537 @@ -373,18 +359,18 @@ checkUtxoIndexComplete utxoIndex = hasEntries (oref /\ out) = case categorizeUtxoEntry out of BundleWithNoAssets -> - _indexSingletons `hasEntryForAsset` AssetLovelace + _indexSingletons `hasEntryForAsset` AdaAsset BundleWithOneAsset asset -> - _indexPairs `hasEntryForAsset` AssetLovelace - && _indexSingletons `hasEntryForAsset` Asset asset + _indexPairs `hasEntryForAsset` AdaAsset + && _indexSingletons `hasEntryForAsset` Asset.fromAssetClass asset BundleWithTwoAssets asset0 asset1 -> - _indexAnyWith `hasEntryForAsset` AssetLovelace - && _indexPairs `hasEntryForAsset` Asset asset0 - && _indexPairs `hasEntryForAsset` Asset asset1 + _indexAnyWith `hasEntryForAsset` AdaAsset + && _indexPairs `hasEntryForAsset` Asset.fromAssetClass asset0 + && _indexPairs `hasEntryForAsset` Asset.fromAssetClass asset1 BundleWithMultipleAssets assets -> - _indexAnyWith `hasEntryForAsset` AssetLovelace && + _indexAnyWith `hasEntryForAsset` AdaAsset && flip Foldable.all assets \asset -> - (_indexAnyWith `hasEntryForAsset` Asset asset) + (_indexAnyWith `hasEntryForAsset` Asset.fromAssetClass asset) where hasEntryForAsset :: Lens' UtxoIndex (Map Asset UtxoMap) -> Asset -> Boolean @@ -422,22 +408,23 @@ checkUtxoIndexMinimal utxoIndex = Map.lookup oref (utxoIndexUniverse utxoIndex) txOutputHasOneAsset :: TransactionOutput -> Asset -> Boolean - txOutputHasOneAsset txOutput AssetLovelace = + txOutputHasOneAsset txOutput AdaAsset = txOutputAssetCount txOutput == zero txOutputHasOneAsset txOutput asset = txOutputHasAsset txOutput asset && txOutputAssetCount txOutput == one txOutputHasTwoAssetsWith :: TransactionOutput -> Asset -> Boolean - txOutputHasTwoAssetsWith txOutput AssetLovelace = + txOutputHasTwoAssetsWith txOutput AdaAsset = txOutputAssetCount txOutput == one txOutputHasTwoAssetsWith txOutput asset = txOutputHasAsset txOutput asset && txOutputAssetCount txOutput == BigInt.fromInt 2 txOutputHasAsset :: TransactionOutput -> Asset -> Boolean - txOutputHasAsset _ AssetLovelace = true - txOutputHasAsset (TransactionOutput { amount }) (Asset asset) = - Value.getAssetQuantity asset amount >= one + txOutputHasAsset _ AdaAsset = true + -- ^ TODO: shouldn't we check if it is greater than 0? + txOutputHasAsset (TransactionOutput { amount }) (asset) = + Value.valueOf asset amount >= BigNum.one txOutputAssetCount :: TransactionOutput -> BigInt txOutputAssetCount = diff --git a/src/Internal/Contract.purs b/src/Internal/Contract.purs index 17ac25415c..9e7075194d 100644 --- a/src/Internal/Contract.purs +++ b/src/Internal/Contract.purs @@ -23,4 +23,3 @@ getChainTip = do getProtocolParameters :: Contract ProtocolParameters getProtocolParameters = asks $ _.ledgerConstants >>> _.pparams - diff --git a/src/Internal/Contract/AwaitTxConfirmed.purs b/src/Internal/Contract/AwaitTxConfirmed.purs index e2100035cf..32afcbd80b 100644 --- a/src/Internal/Contract/AwaitTxConfirmed.purs +++ b/src/Internal/Contract/AwaitTxConfirmed.purs @@ -7,6 +7,8 @@ module Ctl.Internal.Contract.AwaitTxConfirmed import Prelude +import Cardano.Types (Slot, TransactionHash, TransactionInput(TransactionInput)) +import Cardano.Types.BigNum as BigNum import Contract.Monad (liftedE) import Control.Monad.Reader.Class (asks) import Control.Parallel (parOneOf) @@ -14,13 +16,7 @@ import Ctl.Internal.BalanceTx.Sync (syncWalletWithTransaction) import Ctl.Internal.Contract (getChainTip) import Ctl.Internal.Contract.Monad (Contract, getQueryHandle) import Ctl.Internal.Contract.QueryBackend (getBlockfrostBackend) -import Ctl.Internal.Serialization.Address (Slot) -import Ctl.Internal.Types.BigNum as BigNum import Ctl.Internal.Types.Chain as Chain -import Ctl.Internal.Types.Transaction - ( TransactionHash - , TransactionInput(TransactionInput) - ) import Data.Either (either) import Data.Maybe (isJust, maybe) import Data.Newtype (unwrap, wrap) @@ -81,12 +77,13 @@ awaitTxConfirmedWithTimeout timeoutSeconds txHash = do waitForConfirmation = do { delay: delayMs } <- asks (_.timeParams >>> _.awaitTxConfirmed) tryUntilTrue delayMs (doesTxExist txHash) - confirmTxDelay <- - asks _.backend <#> (getBlockfrostBackend >=> _.confirmTxDelay) - isBlockfrost <- asks _.backend <#> getBlockfrostBackend >>> isJust - when isBlockfrost do - tryUntilTrue delayMs (utxosPresentForTxHash txHash) - for_ confirmTxDelay (liftAff <<< delay <<< fromDuration) + do + confirmTxDelay <- + asks _.backend <#> (getBlockfrostBackend >=> _.confirmTxDelay) + isBlockfrost <- asks _.backend <#> getBlockfrostBackend >>> isJust + when isBlockfrost do + tryUntilTrue delayMs (utxosPresentForTxHash txHash) + for_ confirmTxDelay (liftAff <<< delay <<< fromDuration) whenM ( asks $ _.synchronizationParams >>> _.syncWalletWithTransaction diff --git a/src/Internal/Contract/Hooks.purs b/src/Internal/Contract/Hooks.purs index efd552c6c7..52a2d55582 100644 --- a/src/Internal/Contract/Hooks.purs +++ b/src/Internal/Contract/Hooks.purs @@ -1,8 +1,13 @@ -module Ctl.Internal.Contract.Hooks (Hooks, emptyHooks) where +module Ctl.Internal.Contract.Hooks + ( Hooks + , ClusterParameters + , emptyHooks + ) where import Prelude -import Ctl.Internal.Cardano.Types.Transaction (Transaction) +import Cardano.Types.PrivateKey (PrivateKey) +import Cardano.Types.Transaction (Transaction) import Data.Maybe (Maybe(Nothing)) import Effect (Effect) import Effect.Exception (Error) @@ -13,6 +18,14 @@ type Hooks = , onSuccess :: Maybe (Effect Unit) , onError :: Maybe (Error -> Effect Unit) , onSubmit :: Maybe (Transaction -> Effect Unit) + , onClusterStartup :: Maybe (ClusterParameters -> Effect Unit) + } + +type ClusterParameters = + { privateKeys :: Array PrivateKey + , nodeSocketPath :: String + , nodeConfigPath :: String + , privateKeysDirectory :: String } emptyHooks :: Hooks @@ -22,4 +35,5 @@ emptyHooks = , onSuccess: Nothing , onError: Nothing , onSubmit: Nothing + , onClusterStartup: Nothing } diff --git a/src/Internal/Contract/MinFee.purs b/src/Internal/Contract/MinFee.purs index 7e0f9da5ce..677abf3f21 100644 --- a/src/Internal/Contract/MinFee.purs +++ b/src/Internal/Contract/MinFee.purs @@ -2,42 +2,71 @@ module Ctl.Internal.Contract.MinFee (calculateMinFee) where import Prelude -import Ctl.Internal.Cardano.Types.Transaction - ( Transaction +import Cardano.Types + ( Certificate + ( StakeRegistration + , StakeDeregistration + , StakeDelegation + , PoolRegistration + , PoolRetirement + , VoteDelegCert + , StakeVoteDelegCert + , StakeRegDelegCert + , VoteRegDelegCert + , StakeVoteRegDelegCert + , AuthCommitteeHotCert + , ResignCommitteeColdCert + , RegDrepCert + , UnregDrepCert + , UpdateDrepCert + ) + , Coin + , Credential + , Ed25519KeyHash + , RewardAddress + , Transaction , UtxoMap + , Voter(Cc, Drep, Spo) , _body + , _certs , _collateral , _inputs + , _withdrawals ) -import Ctl.Internal.Cardano.Types.Value (Coin) +import Cardano.Types.Address (Address, getPaymentCredential, getStakeCredential) +import Cardano.Types.Credential (asPubKeyHash) +import Cardano.Types.Credential (asPubKeyHash) as Credential +import Cardano.Types.TransactionBody (_votingProcedures) +import Cardano.Types.TransactionInput (TransactionInput) import Ctl.Internal.Contract (getProtocolParameters) import Ctl.Internal.Contract.Monad (Contract, getQueryHandle) import Ctl.Internal.Contract.Wallet (getWalletAddresses) import Ctl.Internal.Helpers (liftM, liftedM) -import Ctl.Internal.Serialization.Address - ( Address - , addressPaymentCred - , addressStakeCred - , stakeCredentialToKeyHash - ) -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash) import Ctl.Internal.Serialization.MinFee (calculateMinFeeCsl) -import Ctl.Internal.Types.Transaction (TransactionInput) import Data.Array (fromFoldable, mapMaybe) import Data.Array as Array import Data.Either (hush) -import Data.Lens (non) +import Data.Foldable (foldl) +import Data.Lens (view) import Data.Lens.Getter ((^.)) import Data.Map (keys, lookup, values) as Map -import Data.Maybe (Maybe(Just, Nothing)) +import Data.Maybe (Maybe(Just, Nothing), maybe) import Data.Newtype (unwrap) import Data.Set (Set) -import Data.Set (difference, fromFoldable, intersection, mapMaybe, union) as Set +import Data.Set + ( difference + , empty + , fromFoldable + , insert + , intersection + , mapMaybe + , union + ) as Set import Data.Traversable (for) import Effect.Aff (error) import Effect.Aff.Class (liftAff) --- | Calculate `min_fee` using CSL with protocol parameters from Ogmios. +-- | Calculate the minimum transaction fee. calculateMinFee :: Transaction -> UtxoMap -> Contract Coin calculateMinFee tx additionalUtxos = do selfSigners <- getSelfSigners tx additionalUtxos @@ -55,7 +84,7 @@ getSelfSigners tx additionalUtxos = do txInputs :: Set TransactionInput txInputs = Set.difference - (tx ^. _body <<< _inputs) + (Set.fromFoldable $ tx ^. _body <<< _inputs) (Map.keys additionalUtxos) additionalUtxosAddrs :: Set Address @@ -71,7 +100,7 @@ getSelfSigners tx additionalUtxos = do Just utxo -> pure $ Just utxo let - collateralInputs = tx ^. _body <<< _collateral <<< non [] + collateralInputs = tx ^. _body <<< _collateral (collateralAddresses :: Set Address) <- setFor (Set.fromFoldable collateralInputs) $ \txInput -> @@ -97,16 +126,23 @@ getSelfSigners tx additionalUtxos = do liftM ( error $ "Could not extract payment credential from Address: " <> show addr - ) $ addressPaymentCred addr - pure $ stakeCredentialToKeyHash paymentCred + ) $ getPaymentCredential addr + pure $ asPubKeyHash $ unwrap paymentCred -- Extract stake pub key hashes from addresses let stakePkhs = Set.fromFoldable $ - (stakeCredentialToKeyHash <=< addressStakeCred) `mapMaybe` + (asPubKeyHash <<< unwrap <=< getStakeCredential) `mapMaybe` Array.fromFoldable txOwnAddrs - pure $ paymentPkhs <> stakePkhs + -- Extract signers for certificates, withdrawals, and voting procedures + let + certsPkhs = getSignersForCerts tx + withdrawalsPkhs = getSignersForWithdrawals tx + votingProceduresPkhs = getSignersForVotingProcedures tx + + pure $ paymentPkhs <> stakePkhs <> certsPkhs <> withdrawalsPkhs + <> votingProceduresPkhs where setFor :: forall (a :: Type) (b :: Type) (m :: Type -> Type) @@ -117,3 +153,54 @@ getSelfSigners tx additionalUtxos = do -> (a -> m b) -> m (Set b) setFor txIns f = Set.fromFoldable <$> for (fromFoldable txIns) f + +getSignersForCerts :: Transaction -> Set Ed25519KeyHash +getSignersForCerts = foldl worker Set.empty <<< view (_body <<< _certs) + where + worker :: Set Ed25519KeyHash -> Certificate -> Set Ed25519KeyHash + worker acc = + case _ of + StakeRegistration _ -> acc + StakeDeregistration cred -> addSigner $ unwrap cred + StakeDelegation cred _ -> addSigner $ unwrap cred + PoolRegistration poolParams -> Set.insert + (unwrap (unwrap poolParams).operator) + acc + PoolRetirement { poolKeyHash } -> Set.insert (unwrap poolKeyHash) acc + VoteDelegCert cred _ -> addSigner $ unwrap cred + StakeVoteDelegCert cred _ _ -> addSigner $ unwrap cred + StakeRegDelegCert cred _ _ -> addSigner $ unwrap cred + VoteRegDelegCert cred _ _ -> addSigner $ unwrap cred + StakeVoteRegDelegCert cred _ _ _ -> addSigner $ unwrap cred + AuthCommitteeHotCert { coldCred } -> addSigner coldCred + ResignCommitteeColdCert cred _ -> addSigner cred + RegDrepCert cred _ _ -> addSigner cred + UnregDrepCert cred _ -> addSigner cred + UpdateDrepCert cred _ -> addSigner cred + where + addSigner :: Credential -> Set Ed25519KeyHash + addSigner = maybe acc (flip Set.insert acc) <<< Credential.asPubKeyHash + +getSignersForWithdrawals :: Transaction -> Set Ed25519KeyHash +getSignersForWithdrawals = + foldl worker Set.empty <<< Map.keys <<< view (_body <<< _withdrawals) + where + worker :: Set Ed25519KeyHash -> RewardAddress -> Set Ed25519KeyHash + worker acc = + maybe acc (flip Set.insert acc) <<< Credential.asPubKeyHash <<< unwrap + <<< _.stakeCredential + +getSignersForVotingProcedures :: Transaction -> Set Ed25519KeyHash +getSignersForVotingProcedures = + foldl worker Set.empty <<< Map.keys <<< unwrap + <<< view (_body <<< _votingProcedures) + where + worker :: Set Ed25519KeyHash -> Voter -> Set Ed25519KeyHash + worker acc = + case _ of + Cc cred -> addSigner cred + Drep cred -> addSigner cred + Spo poolKeyHash -> Set.insert poolKeyHash acc + where + addSigner :: Credential -> Set Ed25519KeyHash + addSigner = maybe acc (flip Set.insert acc) <<< Credential.asPubKeyHash diff --git a/src/Internal/Contract/Monad.purs b/src/Internal/Contract/Monad.purs index 8c811989e6..aa632f5399 100644 --- a/src/Internal/Contract/Monad.purs +++ b/src/Internal/Contract/Monad.purs @@ -22,6 +22,7 @@ module Ctl.Internal.Contract.Monad import Prelude +import Cardano.Types (NetworkId(TestnetId, MainnetId), TransactionHash, UtxoMap) import Contract.Prelude (liftEither) import Control.Alt (class Alt) import Control.Alternative (class Alternative) @@ -36,7 +37,6 @@ import Control.Monad.Reader.Trans (ReaderT, runReaderT, withReaderT) import Control.Monad.Rec.Class (class MonadRec) import Control.Parallel (class Parallel, parallel, sequential) import Control.Plus (class Plus) -import Ctl.Internal.Cardano.Types.Transaction (UtxoMap) import Ctl.Internal.Contract.Hooks (Hooks) import Ctl.Internal.Contract.LogParams (LogParams) import Ctl.Internal.Contract.QueryBackend @@ -65,7 +65,6 @@ import Ctl.Internal.QueryM , underlyingWebSocket ) import Ctl.Internal.QueryM.Kupo (isTxConfirmedAff) -import Ctl.Internal.Serialization.Address (NetworkId(TestnetId, MainnetId)) import Ctl.Internal.Service.Blockfrost ( BlockfrostServiceM , runBlockfrostServiceM @@ -74,7 +73,6 @@ import Ctl.Internal.Service.Blockfrost as Blockfrost import Ctl.Internal.Service.Error (ClientError) import Ctl.Internal.Types.ProtocolParameters (ProtocolParameters) import Ctl.Internal.Types.SystemStart (SystemStart) -import Ctl.Internal.Types.Transaction (TransactionHash) import Ctl.Internal.Types.UsedTxOuts (UsedTxOuts, isTxOutRefUsed, newUsedTxOuts) import Ctl.Internal.Wallet (Wallet(GenericCip30)) import Ctl.Internal.Wallet.Spec (WalletSpec, mkWalletBySpec) @@ -83,7 +81,7 @@ import Data.Either (Either(Left, Right), isRight) import Data.Log.Level (LogLevel) import Data.Log.Message (Message) import Data.Maybe (Maybe(Just, Nothing), fromMaybe) -import Data.Newtype (class Newtype, unwrap, wrap) +import Data.Newtype (class Newtype, unwrap) import Data.Set (Set) import Data.Set as Set import Data.Time.Duration (Milliseconds, Seconds) @@ -272,7 +270,7 @@ buildBackend logger = case _ of where buildCtlBackend :: CtlBackendParams -> Aff CtlBackend buildCtlBackend { ogmiosConfig, kupoConfig } = do - let isTxConfirmed = map isRight <<< isTxConfirmedAff kupoConfig <<< wrap + let isTxConfirmed = map isRight <<< isTxConfirmedAff kupoConfig ogmiosWs <- mkOgmiosWebSocketAff isTxConfirmed logger ogmiosConfig pure { ogmios: diff --git a/src/Internal/Contract/QueryHandle.purs b/src/Internal/Contract/QueryHandle.purs index 5531fe5ae4..c678c78548 100644 --- a/src/Internal/Contract/QueryHandle.purs +++ b/src/Internal/Contract/QueryHandle.purs @@ -6,12 +6,13 @@ module Ctl.Internal.Contract.QueryHandle import Prelude +import Cardano.AsCbor (encodeCbor) +import Cardano.Types.Transaction (hash) as Transaction import Contract.Log (logDebug') import Control.Monad.Error.Class (throwError) import Ctl.Internal.Contract.LogParams (LogParams) import Ctl.Internal.Contract.QueryBackend (BlockfrostBackend, CtlBackend) import Ctl.Internal.Contract.QueryHandle.Type (QueryHandle) -import Ctl.Internal.Hashing (transactionHash) as Hashing import Ctl.Internal.Helpers (logWithLevel) import Ctl.Internal.QueryM (QueryM) import Ctl.Internal.QueryM (evaluateTxOgmios, getChainTip, submitTxOgmios) as QueryM @@ -21,7 +22,7 @@ import Ctl.Internal.QueryM.Kupo ( getDatumByHash , getOutputAddressesByTxHash , getScriptByHash - , getTxMetadata + , getTxAuxiliaryData , getUtxoByOref , isTxConfirmed , utxosAt @@ -32,7 +33,6 @@ import Ctl.Internal.QueryM.Pools , getPubKeyHashDelegationsAndRewards , getValidatorHashDelegationsAndRewards ) as QueryM -import Ctl.Internal.Serialization (convertTransaction, toBytes) as Serialization import Ctl.Internal.Service.Blockfrost ( BlockfrostServiceM , runBlockfrostServiceM @@ -41,9 +41,8 @@ import Ctl.Internal.Service.Blockfrost as Blockfrost import Ctl.Internal.Service.Error (ClientError(ClientOtherError)) import Data.Either (Either(Left, Right)) import Data.Maybe (fromMaybe, isJust) -import Data.Newtype (unwrap, wrap) +import Data.Newtype (wrap) import Effect.Aff (Aff) -import Effect.Class (liftEffect) import Effect.Exception (error) queryHandleForCtlBackend @@ -58,22 +57,25 @@ queryHandleForCtlBackend runQueryM params backend = , getUtxoByOref: runQueryM' <<< Kupo.getUtxoByOref , getOutputAddressesByTxHash: runQueryM' <<< Kupo.getOutputAddressesByTxHash , doesTxExist: runQueryM' <<< map (map isJust) <<< Kupo.isTxConfirmed - , getTxMetadata: runQueryM' <<< Kupo.getTxMetadata + , getTxAuxiliaryData: runQueryM' <<< Kupo.getTxAuxiliaryData , utxosAt: runQueryM' <<< Kupo.utxosAt , getChainTip: Right <$> runQueryM' QueryM.getChainTip , getCurrentEpoch: runQueryM' QueryM.getCurrentEpoch , submitTx: \tx -> runQueryM' do - cslTx <- liftEffect $ Serialization.convertTransaction tx - let txHash = Hashing.transactionHash cslTx + let txHash = Transaction.hash tx logDebug' $ "Pre-calculated tx hash: " <> show txHash - let txCborBytes = Serialization.toBytes cslTx - result <- QueryM.submitTxOgmios (unwrap txHash) txCborBytes - case result of - SubmitTxSuccess a -> pure $ pure $ wrap a - SubmitFail err -> pure $ Left $ ClientOtherError $ show err + let txCborBytes = encodeCbor tx + result <- QueryM.submitTxOgmios txHash txCborBytes + pure $ case result of + SubmitTxSuccess th -> do + if th == txHash then Right th + else Left + ( ClientOtherError + "Computed TransactionHash is not equal to the one returned by Ogmios, please report as bug!" + ) + SubmitFail err -> Left $ ClientOtherError $ show err , evaluateTx: \tx additionalUtxos -> runQueryM' do - txBytes <- Serialization.toBytes <$> liftEffect - (Serialization.convertTransaction tx) + let txBytes = encodeCbor tx QueryM.evaluateTxOgmios txBytes additionalUtxos , getEraSummaries: Right <$> runQueryM' QueryM.getEraSummaries , getPoolIds: Right <$> runQueryM' QueryM.getPoolIds @@ -82,7 +84,7 @@ queryHandleForCtlBackend runQueryM params backend = (QueryM.getPubKeyHashDelegationsAndRewards pubKeyHash) , getValidatorHashDelegationsAndRewards: \_ validatorHash -> Right <$> runQueryM' - (QueryM.getValidatorHashDelegationsAndRewards validatorHash) + (QueryM.getValidatorHashDelegationsAndRewards $ wrap validatorHash) } where @@ -98,7 +100,7 @@ queryHandleForBlockfrostBackend logParams backend = , getOutputAddressesByTxHash: runBlockfrostServiceM' <<< Blockfrost.getOutputAddressesByTxHash , doesTxExist: runBlockfrostServiceM' <<< Blockfrost.doesTxExist - , getTxMetadata: runBlockfrostServiceM' <<< Blockfrost.getTxMetadata + , getTxAuxiliaryData: runBlockfrostServiceM' <<< Blockfrost.getTxAuxiliaryData , utxosAt: runBlockfrostServiceM' <<< Blockfrost.utxosAt , getChainTip: runBlockfrostServiceM' Blockfrost.getChainTip , getCurrentEpoch: @@ -118,7 +120,7 @@ queryHandleForBlockfrostBackend logParams backend = , getValidatorHashDelegationsAndRewards: \networkId stakeValidatorHash -> runBlockfrostServiceM' ( Blockfrost.getValidatorHashDelegationsAndRewards networkId - stakeValidatorHash + (wrap stakeValidatorHash) ) } where diff --git a/src/Internal/Contract/QueryHandle/Type.purs b/src/Internal/Contract/QueryHandle/Type.purs index 6102dfdb48..10afe6510b 100644 --- a/src/Internal/Contract/QueryHandle/Type.purs +++ b/src/Internal/Contract/QueryHandle/Type.purs @@ -3,30 +3,32 @@ module Ctl.Internal.Contract.QueryHandle.Type , AffE ) where -import Ctl.Internal.Cardano.Types.ScriptRef (ScriptRef) -import Ctl.Internal.Cardano.Types.Transaction - ( PoolPubKeyHash +import Cardano.Types + ( Address + , DataHash + , NetworkId + , PlutusData + , PoolPubKeyHash + , ScriptHash + , ScriptRef + , StakePubKeyHash , Transaction + , TransactionHash + , TransactionInput , TransactionOutput , UtxoMap ) +import Cardano.Types.AuxiliaryData (AuxiliaryData) import Ctl.Internal.Contract.QueryHandle.Error (GetTxMetadataError) import Ctl.Internal.QueryM.Ogmios ( AdditionalUtxoSet , CurrentEpoch , TxEvaluationR ) -import Ctl.Internal.QueryM.Pools (DelegationsAndRewards) -import Ctl.Internal.Serialization.Address (Address, NetworkId) -import Ctl.Internal.Serialization.Hash (ScriptHash) import Ctl.Internal.Service.Error (ClientError) -import Ctl.Internal.Types.Chain as Chain -import Ctl.Internal.Types.Datum (DataHash, Datum) +import Ctl.Internal.Types.Chain (Tip) as Chain +import Ctl.Internal.Types.DelegationsAndRewards (DelegationsAndRewards) import Ctl.Internal.Types.EraSummaries (EraSummaries) -import Ctl.Internal.Types.PubKeyHash (StakePubKeyHash) -import Ctl.Internal.Types.Scripts (StakeValidatorHash) -import Ctl.Internal.Types.Transaction (TransactionHash, TransactionInput) -import Ctl.Internal.Types.TransactionMetadata (GeneralTransactionMetadata) import Data.Either (Either) import Data.Maybe (Maybe) import Effect.Aff (Aff) @@ -34,11 +36,11 @@ import Effect.Aff (Aff) type AffE (a :: Type) = Aff (Either ClientError a) type QueryHandle = - { getDatumByHash :: DataHash -> AffE (Maybe Datum) + { getDatumByHash :: DataHash -> AffE (Maybe PlutusData) , getScriptByHash :: ScriptHash -> AffE (Maybe ScriptRef) - , getTxMetadata :: + , getTxAuxiliaryData :: TransactionHash - -> Aff (Either GetTxMetadataError GeneralTransactionMetadata) + -> Aff (Either GetTxMetadataError AuxiliaryData) , getUtxoByOref :: TransactionInput -> AffE (Maybe TransactionOutput) , getOutputAddressesByTxHash :: TransactionHash -> AffE (Array Address) , doesTxExist :: TransactionHash -> AffE Boolean @@ -53,5 +55,5 @@ type QueryHandle = , getPubKeyHashDelegationsAndRewards :: NetworkId -> StakePubKeyHash -> AffE (Maybe DelegationsAndRewards) , getValidatorHashDelegationsAndRewards :: - NetworkId -> StakeValidatorHash -> AffE (Maybe DelegationsAndRewards) + NetworkId -> ScriptHash -> AffE (Maybe DelegationsAndRewards) } diff --git a/src/Internal/Contract/Sign.purs b/src/Internal/Contract/Sign.purs index f6164335bb..98c347a91b 100644 --- a/src/Internal/Contract/Sign.purs +++ b/src/Internal/Contract/Sign.purs @@ -4,19 +4,12 @@ module Ctl.Internal.Contract.Sign import Prelude +import Cardano.Types (Transaction, _body, _inputs, _witnessSet) import Control.Monad.Reader (asks) import Ctl.Internal.BalanceTx.Sync (isCip30Wallet, syncWalletWithTxInputs) -import Ctl.Internal.Cardano.Types.Transaction - ( Transaction - , _body - , _inputs - , _witnessSet - ) import Ctl.Internal.Contract.Monad (Contract) import Ctl.Internal.Contract.Wallet (withWallet) -import Ctl.Internal.Wallet - ( Wallet(GenericCip30, KeyWallet) - ) +import Ctl.Internal.Wallet (Wallet(GenericCip30, KeyWallet)) import Data.Array (fromFoldable) import Data.Lens ((<>~)) import Data.Lens.Getter ((^.)) @@ -26,6 +19,7 @@ import Effect.Aff.Class (liftAff) import Effect.Class (liftEffect) import Effect.Exception (try) +-- | Signs a transaction with potential failure. signTransaction :: Transaction -> Contract Transaction signTransaction tx = do diff --git a/src/Internal/Contract/WaitUntilSlot.purs b/src/Internal/Contract/WaitUntilSlot.purs index 149dd70064..84e022f70b 100644 --- a/src/Internal/Contract/WaitUntilSlot.purs +++ b/src/Internal/Contract/WaitUntilSlot.purs @@ -7,14 +7,14 @@ module Ctl.Internal.Contract.WaitUntilSlot import Prelude +import Cardano.Types (BigNum, Slot(Slot)) +import Cardano.Types.BigNum as BigNum import Contract.Log (logTrace') import Control.Monad.Error.Class (liftEither, liftMaybe) import Control.Monad.Reader (asks) import Ctl.Internal.Contract (getChainTip) import Ctl.Internal.Contract.Monad (Contract, getQueryHandle) import Ctl.Internal.Helpers (liftM) -import Ctl.Internal.Serialization.Address (Slot(Slot)) -import Ctl.Internal.Types.BigNum as BigNum import Ctl.Internal.Types.Chain as Chain import Ctl.Internal.Types.EraSummaries (EraSummaries(EraSummaries)) import Ctl.Internal.Types.Interval @@ -24,8 +24,6 @@ import Ctl.Internal.Types.Interval , getSlotLength , slotToPosixTime ) -import Ctl.Internal.Types.Natural (Natural) -import Ctl.Internal.Types.Natural as Natural import Ctl.Internal.Types.SystemStart (SystemStart) import Data.Array (length, mapMaybe) import Data.Bifunctor (lmap) @@ -166,15 +164,13 @@ posixTimeToSeconds (POSIXTime futureTimeBigInt) = do $ futureTimeBigInt / BigInt.fromInt 1000 -- | Wait at least `offset` number of slots. -waitNSlots :: Natural -> Contract Chain.Tip +waitNSlots :: BigNum -> Contract Chain.Tip waitNSlots offset = do - offsetBigNum <- liftM (error "Unable to convert BigInt to BigNum") - $ (BigNum.fromBigInt <<< Natural.toBigInt) offset - if offsetBigNum == BigNum.fromInt 0 then getChainTip + if offset == BigNum.fromInt 0 then getChainTip else do slot <- currentSlot - newSlot <- liftM (error "Unable to advance slot") - $ wrap <$> BigNum.add (unwrap slot) offsetBigNum + newSlot <- liftM (error "waitNSlots: Unable to advance slot") + $ wrap <$> BigNum.add (unwrap slot) offset waitUntilSlot newSlot currentSlot :: Contract Slot diff --git a/src/Internal/Contract/Wallet.purs b/src/Internal/Contract/Wallet.purs index 472aad2f82..1eec8391e2 100644 --- a/src/Internal/Contract/Wallet.purs +++ b/src/Internal/Contract/Wallet.purs @@ -5,9 +5,13 @@ module Ctl.Internal.Contract.Wallet , getWalletAddresses , signData , getWallet + , ownDrepPubKey + , ownDrepPubKeyHash , ownPubKeyHashes , ownPaymentPubKeyHashes + , ownRegisteredPubStakeKeys , ownStakePubKeyHashes + , ownUnregisteredPubStakeKeys , withWallet , getWalletCollateral , getWalletBalance @@ -16,37 +20,42 @@ module Ctl.Internal.Contract.Wallet import Prelude +import Cardano.Types (Ed25519KeyHash, RawBytes) +import Cardano.Types.Address + ( Address(RewardAddress) + , getPaymentCredential + , getStakeCredential + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Credential as Credential +import Cardano.Types.PaymentPubKeyHash (PaymentPubKeyHash) +import Cardano.Types.PrivateKey (toPublicKey) as PrivateKey +import Cardano.Types.PublicKey (PublicKey) +import Cardano.Types.PublicKey (hash) as PublicKey +import Cardano.Types.StakePubKeyHash (StakePubKeyHash) +import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput) +import Cardano.Types.UtxoMap (UtxoMap) +import Cardano.Types.Value (Value, valueToCoin) +import Cardano.Types.Value (geq, lovelaceValueOf, sum) as Value +import Cardano.Wallet.Key + ( PrivateStakeKey(PrivateStakeKey) + , getPrivateDrepKey + , getPrivateStakeKey + ) +import Contract.Log (logWarn') import Control.Monad.Reader.Trans (asks) import Control.Parallel (parTraverse) -import Ctl.Internal.Cardano.Types.Transaction (UtxoMap) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput - ) -import Ctl.Internal.Cardano.Types.Value (Value, valueToCoin) -import Ctl.Internal.Cardano.Types.Value (geq, lovelaceValueOf) as Value +import Ctl.Internal.BalanceTx.Collateral.Select (minRequiredCollateral) import Ctl.Internal.Contract (getProtocolParameters) import Ctl.Internal.Contract.Monad (Contract, filterLockedUtxos, getQueryHandle) -import Ctl.Internal.Helpers (liftM, liftedM) -import Ctl.Internal.Serialization.Address - ( Address - , addressPaymentCred - , baseAddressDelegationCred - , baseAddressFromAddress - , stakeCredentialToKeyHash - ) +import Ctl.Internal.Helpers (bugTrackerLink, liftM, liftedM) import Ctl.Internal.Service.Error (pprintClientError) -import Ctl.Internal.Types.PubKeyHash - ( PaymentPubKeyHash - , PubKeyHash - , StakePubKeyHash - ) -import Ctl.Internal.Types.RawBytes (RawBytes) import Ctl.Internal.Wallet (Wallet, actionBasedOnWallet) import Ctl.Internal.Wallet.Cip30 (DataSignature) -import Data.Array (cons, foldMap, foldr) +import Data.Array (cons, foldr) import Data.Array as Array import Data.Either (Either(Left, Right), hush) -import Data.Foldable (fold, foldl) +import Data.Foldable (foldl) import Data.Function (on) import Data.Map as Map import Data.Maybe (Maybe(Nothing, Just), fromMaybe, maybe) @@ -57,7 +66,7 @@ import Data.UInt as UInt import Effect.Aff.Class (liftAff) import Effect.Class (liftEffect) import Effect.Exception (error, throw) -import JS.BigInt as BigInt +import Effect.Unsafe (unsafePerformEffect) getUnusedAddresses :: Contract (Array Address) getUnusedAddresses = @@ -68,19 +77,30 @@ getChangeAddress = withWallet do actionBasedOnWallet _.getChangeAddress \kw -> do networkId <- asks _.networkId - pure $ (unwrap kw).address networkId + addr <- liftAff $ (unwrap kw).address networkId + pure addr getRewardAddresses :: Contract (Array Address) getRewardAddresses = withWallet $ actionBasedOnWallet _.getRewardAddresses - \kw -> asks _.networkId <#> Array.singleton <<< (unwrap kw).address + \kw -> do + networkId <- asks _.networkId + mStakeCred <- liftAff $ getStakeCredential <$> (unwrap kw).address + networkId + pure $ maybe mempty + ( Array.singleton <<< RewardAddress <<< + { networkId, stakeCredential: _ } + ) + mStakeCred +-- | Get all `Address`es of the browser wallet. getWalletAddresses :: Contract (Array Address) getWalletAddresses = withWallet do actionBasedOnWallet _.getUsedAddresses ( \kw -> do networkId <- asks _.networkId - pure $ Array.singleton $ (unwrap kw).address networkId + addr <- liftAff $ (unwrap kw).address networkId + pure $ Array.singleton $ addr ) signData :: Address -> RawBytes -> Contract DataSignature @@ -88,24 +108,29 @@ signData address payload = withWallet $ actionBasedOnWallet (\w -> w.signData address payload) - \kw -> do - networkId <- asks _.networkId - liftAff $ (unwrap kw).signData networkId payload + ( \kw -> do + mDataSig <- liftAff $ (unwrap kw).signData address payload + liftM + ( error + "signData via KeyWallet: Unable to sign data for the supplied address" + ) + mDataSig + ) getWallet :: Contract (Maybe Wallet) getWallet = asks _.wallet -ownPubKeyHashes :: Contract (Array PubKeyHash) +ownPubKeyHashes :: Contract (Array Ed25519KeyHash) ownPubKeyHashes = do getWalletAddresses >>= traverse \address -> do paymentCred <- liftM (error $ "Unable to get payment credential from Address") $ - addressPaymentCred address + getPaymentCredential address -- scripts are impossible here, so `stakeCredentialToKeyHash` will never -- return `Nothing` (`catMaybes` is safe) liftM (error "Impossible happened: CIP-30 method returned script address") - $ stakeCredentialToKeyHash paymentCred <#> wrap + $ Credential.asPubKeyHash (unwrap paymentCred) -- | Gets all wallet `PaymentPubKeyHash`es via `getWalletAddresses`. ownPaymentPubKeyHashes :: Contract (Array PaymentPubKeyHash) @@ -119,9 +144,8 @@ ownStakePubKeyHashes = do addressToMStakePubKeyHash :: Address -> Maybe StakePubKeyHash addressToMStakePubKeyHash address = do - baseAddress <- baseAddressFromAddress address - wrap <<< wrap <$> stakeCredentialToKeyHash - (baseAddressDelegationCred baseAddress) + cred <- unwrap <$> getStakeCredential address + wrap <$> Credential.asPubKeyHash cred withWallet :: forall (a :: Type). (Wallet -> Contract a) -> Contract a @@ -131,19 +155,21 @@ withWallet act = do getWalletCollateral :: Contract (Maybe (Array TransactionUnspentOutput)) getWalletCollateral = do - { maxCollateralInputs, coinsPerUtxoUnit } <- unwrap <$> getProtocolParameters + { maxCollateralInputs, coinsPerUtxoByte } <- unwrap <$> getProtocolParameters mbCollateralUTxOs <- getWallet >>= maybe (pure Nothing) do actionBasedOnWallet _.getCollateral \kw -> do queryHandle <- getQueryHandle networkId <- asks _.networkId - let addr = (unwrap kw).address networkId + addr <- liftAff $ (unwrap kw).address networkId utxos <- (liftAff $ queryHandle.utxosAt addr) <#> hush >>> fromMaybe Map.empty >>= filterLockedUtxos - liftEffect $ (unwrap kw).selectCollateral coinsPerUtxoUnit + mColl <- liftAff $ (unwrap kw).selectCollateral + minRequiredCollateral + coinsPerUtxoByte (UInt.toInt maxCollateralInputs) utxos - + pure mColl let {- This is a workaround for the case where Eternl wallet, in addition to designated collateral UTxO, returns all UTxO's with @@ -155,25 +181,28 @@ getWalletCollateral = do N UTxO's returned by `getCollateral`, such that their total Ada value is greater than or equal to 5 Ada. -} - targetCollateral = Value.lovelaceValueOf $ BigInt.fromInt 5_000_000 + targetCollateral = Value.lovelaceValueOf $ BigNum.fromInt 5_000_000 utxoValue u = (unwrap (unwrap u).output).amount -- used for sorting by ADA value in descending order compareNegatedAdaValues :: TransactionUnspentOutput -> TransactionUnspentOutput -> Ordering compareNegatedAdaValues = - compare `on` - ( unwrap >>> _.output >>> unwrap >>> _.amount >>> valueToCoin >>> unwrap - >>> negate - ) + flip compare `on` + (unwrap >>> _.output >>> unwrap >>> _.amount >>> valueToCoin >>> unwrap) consumeUntilEnough :: Array TransactionUnspentOutput -> TransactionUnspentOutput -> Array TransactionUnspentOutput consumeUntilEnough utxos utxo = - if foldMap utxoValue utxos `Value.geq` targetCollateral then utxos - else cons utxo utxos + case + Value.geq <$> Value.sum (utxoValue <$> utxos) <*> Just targetCollateral + of + Just true -> utxos + Just false -> cons utxo utxos + _ -> unsafePerformEffect $ throw $ + "Overflow while calculating collateral. " <> bugTrackerLink mbSufficientUtxos = mbCollateralUTxOs <#> foldl consumeUntilEnough [] <<< Array.sortBy compareNegatedAdaValues for_ mbSufficientUtxos \sufficientUtxos -> do @@ -197,17 +226,29 @@ getWalletBalance = do queryHandle <- getQueryHandle wallet <- getWallet >>= liftM (error "getWalletBalance: no wallet is active") let + getKeyWalletBalance :: _ -> Contract Value getKeyWalletBalance = \_ -> do -- Implement via `utxosAt` addresses <- getWalletAddresses - fold <$> flip parTraverse addresses \address -> do - eiResponse <- liftAff $ queryHandle.utxosAt address - case eiResponse of - Left err -> liftEffect $ throw $ - "getWalletBalance via KeyWallet: utxosAt call error: " <> - pprintClientError err - Right utxoMap -> - pure $ fold $ map _.amount $ map unwrap $ Map.values utxoMap + liftM + ( error $ + "getWalletBalance: Unable to get payment credential from Address" + ) + =<< Value.sum <$> flip parTraverse addresses \address -> do + eiResponse <- liftAff $ queryHandle.utxosAt address + case eiResponse of + Left err -> liftEffect $ throw $ + "getWalletBalance: utxosAt call error: " <> + pprintClientError err + Right utxoMap -> do + liftM + ( error $ + "getWalletBalance: Unable to get payment credential from Address" + ) + $ Value.sum + ( map _.amount $ map unwrap $ Array.fromFoldable $ + Map.values utxoMap + ) actionBasedOnWallet _.getBalance getKeyWalletBalance wallet getWalletUtxos :: Contract (Maybe UtxoMap) @@ -237,3 +278,58 @@ getWalletUtxos = do toUtxoMap :: Array TransactionUnspentOutput -> UtxoMap toUtxoMap = Map.fromFoldable <<< map (unwrap >>> \({ input, output }) -> input /\ output) + +ownDrepPubKey :: Contract PublicKey +ownDrepPubKey = + withWallet do + actionBasedOnWallet _.getPubDrepKey + ( \kw -> do + drepKey <- liftAff $ liftedM + (error "ownDrepPubKey: Unable to get KeyWallet DRep key") + (getPrivateDrepKey kw) + pure $ PrivateKey.toPublicKey $ unwrap drepKey + ) + +ownDrepPubKeyHash :: Contract Ed25519KeyHash +ownDrepPubKeyHash = + withWallet do + actionBasedOnWallet (map PublicKey.hash <<< _.getPubDrepKey) + ( \kw -> do + drepKey <- liftAff $ liftedM + (error "ownDrepPubKeyHash: Unable to get KeyWallet DRep key") + (getPrivateDrepKey kw) + pure $ PublicKey.hash $ PrivateKey.toPublicKey $ + unwrap drepKey + ) + +ownRegisteredPubStakeKeys :: Contract (Array PublicKey) +ownRegisteredPubStakeKeys = + withWallet do + actionBasedOnWallet _.getRegisteredPubStakeKeys + ( \_kw -> do + logWarn' $ kwStakeKeysRegStatusWarning "ownRegisteredPubStakeKeys" + pure mempty + ) + +ownUnregisteredPubStakeKeys :: Contract (Array PublicKey) +ownUnregisteredPubStakeKeys = + withWallet do + actionBasedOnWallet _.getUnregisteredPubStakeKeys + ( \kw -> do + logWarn' $ kwStakeKeysRegStatusWarning "ownUnregisteredPubStakeKeys" + liftAff (getPrivateStakeKey kw) <#> case _ of + Just (PrivateStakeKey stakeKey) -> + Array.singleton $ PrivateKey.toPublicKey stakeKey + Nothing -> + mempty + ) + +kwStakeKeysRegStatusWarning :: String -> String +kwStakeKeysRegStatusWarning funName = + funName <> + " via KeyWallet: KeyWallet does not distinguish between \ + \registered and unregistered stake keys due to the limitations \ + \of the underlying query layer. This means that all controlled \ + \stake keys are returned as part of ownUnregisteredPubStakeKeys, \ + \and the response of ownRegisteredPubStakeKeys is always an \ + \empty array." diff --git a/src/Internal/Deserialization/BigInt.js b/src/Internal/Deserialization/BigInt.js deleted file mode 100644 index 0fd6fef55d..0000000000 --- a/src/Internal/Deserialization/BigInt.js +++ /dev/null @@ -1,3 +0,0 @@ -export function _BigInt_to_str(x) { - return x.to_str(); -} diff --git a/src/Internal/Deserialization/BigInt.purs b/src/Internal/Deserialization/BigInt.purs deleted file mode 100644 index 370a99d9c6..0000000000 --- a/src/Internal/Deserialization/BigInt.purs +++ /dev/null @@ -1,14 +0,0 @@ -module Ctl.Internal.Deserialization.BigInt - ( convertBigInt - ) where - -import Prelude - -import Ctl.Internal.Serialization.Types (BigInt) -import Data.Maybe (Maybe) -import JS.BigInt as BigInt - -convertBigInt :: BigInt -> Maybe BigInt.BigInt -convertBigInt = BigInt.fromString <<< _BigInt_to_str - -foreign import _BigInt_to_str :: BigInt -> String diff --git a/src/Internal/Deserialization/Error.purs b/src/Internal/Deserialization/Error.purs deleted file mode 100644 index 5edb6631e7..0000000000 --- a/src/Internal/Deserialization/Error.purs +++ /dev/null @@ -1,88 +0,0 @@ --- | Error-centered types and functions used by Deserialization modules. -module Ctl.Internal.Deserialization.Error - ( Err - , FromBytesError - , FromCslRepError - , _fromCslRepError - , addErrTrace - , cslErr - , fromBytesErrorHelper - , fromBytesError - , fromCslRepError - , toError - ) where - -import Prelude - -import Ctl.Internal.Error (E, NotImplementedError, _notImplementedError, noteE) -import Ctl.Internal.FfiHelpers (ErrorFfiHelper, errorHelper) -import Data.Either (Either(Left)) -import Data.Maybe (Maybe) -import Data.Variant (Variant, default, inj, match, onMatch) -import Effect.Exception (Error, error) -import Type.Proxy (Proxy(Proxy)) -import Type.Row (type (+)) - --- | Error type returned by Deserialization modules -type Err r a = E (FromBytesError + NotImplementedError + FromCslRepError + r) a - --- | Error type for errors returned when conversion from CSL representations fails. -type FromCslRepError r = (fromCslRepError :: String | r) - -_fromCslRepError = Proxy :: Proxy "fromCslRepError" - --- | Creates an error E value from a string. -fromCslRepError - :: forall (r :: Row Type) (a :: Type) - . String - -> E (FromCslRepError + r) a -fromCslRepError = Left <<< inj _fromCslRepError - --- | Annotates Maybe's Nothing as a CSL error. -cslErr - :: forall a r - . String - -> Maybe a - -> E (FromCslRepError + r) a -cslErr = noteE <<< fromCslRepError - --- TODO make it so that it detects non-exhaustiveness --- | Add trace string to an error. -addErrTrace :: forall r a. String -> Err r a -> Err r a -addErrTrace s (Left e) = - Left $ e # - ( default e # onMatch - { fromCslRepError: \orig -> inj _fromCslRepError (s <> ": " <> orig) - , notImplementedError: \orig -> inj _notImplementedError - (s <> ": " <> orig) - , fromBytesError: \orig -> inj _fromBytesError (s <> ": " <> orig) - } - ) -addErrTrace _ a = a - --- | Convert a deserialization error into an `Effect` error -toError - :: Variant (FromBytesError + NotImplementedError + FromCslRepError + ()) - -> Error -toError = error <<< match - { fromCslRepError: \err -> "FromCslRepError: " <> err - , fromBytesError: \err -> "FromBytesError: " <> err - , notImplementedError: \err -> "NotImplementedError: " <> err - } - --- | FromBytesError row alias -type FromBytesError r = (fromBytesError :: String | r) - --- | Needed to create a variant type -_fromBytesError = Proxy :: Proxy "fromBytesError" - -fromBytesError - :: forall (r :: Row Type) (a :: Type) - . String - -> E (FromBytesError + r) a -fromBytesError = Left <<< inj _fromBytesError - -fromBytesErrorHelper - :: forall (r :: Row Type) - . ErrorFfiHelper (FromBytesError + r) -fromBytesErrorHelper = errorHelper $ inj _fromBytesError diff --git a/src/Internal/Deserialization/FromBytes.js b/src/Internal/Deserialization/FromBytes.js deleted file mode 100644 index f7b57ae04c..0000000000 --- a/src/Internal/Deserialization/FromBytes.js +++ /dev/null @@ -1,18 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function _fromBytes(helper) { - return name => bytes => { - try { - return helper.valid(lib[name].from_bytes(bytes)); - } catch (e) { - return helper.error(name + ".from_bytes() raised " + e); - } - }; -} diff --git a/src/Internal/Deserialization/FromBytes.purs b/src/Internal/Deserialization/FromBytes.purs deleted file mode 100644 index 5406e8d564..0000000000 --- a/src/Internal/Deserialization/FromBytes.purs +++ /dev/null @@ -1,168 +0,0 @@ -module Ctl.Internal.Deserialization.FromBytes - ( class FromBytes - , fromBytes' - , fromBytes - , fromBytesEffect - ) where - -import Prelude - -import Ctl.Internal.Deserialization.Error (FromBytesError, fromBytesErrorHelper) -import Ctl.Internal.Error (E) -import Ctl.Internal.FfiHelpers (ErrorFfiHelper) -import Ctl.Internal.Serialization.Address - ( Address - , ByronAddress - , StakeCredential - ) -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash, ScriptHash, VRFKeyHash) -import Ctl.Internal.Serialization.Types - ( AuxiliaryDataHash - , DataHash - , Ed25519Signature - , GeneralTransactionMetadata - , GenesisDelegateHash - , GenesisHash - , Mint - , NativeScript - , PlutusData - , PoolMetadataHash - , PublicKey - , Redeemers - , ScriptDataHash - , Transaction - , TransactionBody - , TransactionHash - , TransactionMetadatum - , TransactionOutput - , TransactionUnspentOutput - , TransactionWitnessSet - , Value - , Vkeywitness - , Vkeywitnesses - ) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes) -import Data.Either (hush) -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (unwrap) -import Effect (Effect) -import Effect.Exception (throw) -import Type.Row (type (+)) - --- | Calls `from_bytes` method for the appropriate type -class FromBytes a where - fromBytes' :: forall (r :: Row Type). ByteArray -> E (FromBytesError + r) a - -instance FromBytes Address where - fromBytes' = fromBytesImpl "Address" - -instance FromBytes AuxiliaryDataHash where - fromBytes' = fromBytesImpl "AuxiliaryDataHash" - -instance FromBytes ByronAddress where - fromBytes' = fromBytesImpl "ByronAddress" - -instance FromBytes DataHash where - fromBytes' = fromBytesImpl "DataHash" - -instance FromBytes Ed25519KeyHash where - fromBytes' = fromBytesImpl "Ed25519KeyHash" - -instance FromBytes Ed25519Signature where - fromBytes' = fromBytesImpl "Ed25519Signature" - -instance FromBytes GeneralTransactionMetadata where - fromBytes' = fromBytesImpl "GeneralTransactionMetadata" - -instance FromBytes TransactionMetadatum where - fromBytes' = fromBytesImpl "TransactionMetadatum" - -instance FromBytes GenesisDelegateHash where - fromBytes' = fromBytesImpl "GenesisDelegateHash" - -instance FromBytes GenesisHash where - fromBytes' = fromBytesImpl "GenesisHash" - -instance FromBytes Mint where - fromBytes' = fromBytesImpl "Mint" - -instance FromBytes NativeScript where - fromBytes' = fromBytesImpl "NativeScript" - -instance FromBytes PlutusData where - fromBytes' = fromBytesImpl "PlutusData" - -instance FromBytes PoolMetadataHash where - fromBytes' = fromBytesImpl "PoolMetadataHash" - -instance FromBytes PublicKey where - fromBytes' = fromBytesImpl "PublicKey" - -instance FromBytes Redeemers where - fromBytes' = fromBytesImpl "Redeemers" - -instance FromBytes ScriptDataHash where - fromBytes' = fromBytesImpl "ScriptDataHash" - -instance FromBytes ScriptHash where - fromBytes' = fromBytesImpl "ScriptHash" - -instance FromBytes StakeCredential where - fromBytes' = fromBytesImpl "StakeCredential" - -instance FromBytes Transaction where - fromBytes' = fromBytesImpl "Transaction" - -instance FromBytes TransactionBody where - fromBytes' = fromBytesImpl "TransactionBody" - -instance FromBytes TransactionHash where - fromBytes' = fromBytesImpl "TransactionHash" - -instance FromBytes TransactionOutput where - fromBytes' = fromBytesImpl "TransactionOutput" - -instance FromBytes TransactionUnspentOutput where - fromBytes' = fromBytesImpl "TransactionUnspentOutput" - -instance FromBytes TransactionWitnessSet where - fromBytes' = fromBytesImpl "TransactionWitnessSet" - -instance FromBytes Value where - fromBytes' = fromBytesImpl "Value" - -instance FromBytes VRFKeyHash where - fromBytes' = fromBytesImpl "VRFKeyHash" - -instance FromBytes Vkeywitness where - fromBytes' = fromBytesImpl "Vkeywitness" - -instance FromBytes Vkeywitnesses where - fromBytes' = fromBytesImpl "Vkeywitnesses" - --- for backward compatibility until `Maybe` is abandoned. Then to be renamed. -fromBytes :: forall (a :: Type). FromBytes a => CborBytes -> Maybe a -fromBytes = unwrap >>> fromBytes' >>> hush - -fromBytesEffect :: forall (a :: Type). FromBytes a => CborBytes -> Effect a -fromBytesEffect bytes = - case fromBytes bytes of - Nothing -> throw "from_bytes() call failed" - Just a -> pure a - -fromBytesImpl - :: forall (r :: Row Type) (a :: Type) - . String - -> ByteArray - -> E (FromBytesError + r) a -fromBytesImpl = _fromBytes fromBytesErrorHelper - ----- Foreign imports - -foreign import _fromBytes - :: forall (r :: Row Type) (a :: Type) - . ErrorFfiHelper r - -> String - -> ByteArray - -> E r a diff --git a/src/Internal/Deserialization/Keys.js b/src/Internal/Deserialization/Keys.js deleted file mode 100644 index 4beb728a43..0000000000 --- a/src/Internal/Deserialization/Keys.js +++ /dev/null @@ -1,56 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function freshPrivateKey() { - return lib.PrivateKey.generate_ed25519(); -} - -export function _publicKeyFromBech32(maybe) { - return bech32 => { - try { - return maybe.just(lib.PublicKey.from_bech32(bech32)); - } catch (_) { - return maybe.nothing; - } - }; -} - -export function _ed25519SignatureFromBech32(maybe) { - return bech32 => { - try { - return maybe.just(lib.Ed25519Signature.from_bech32(bech32)); - } catch (_) { - return maybe.nothing; - } - }; -} - -export function _privateKeyFromBytes(maybe) { - return bytes => { - try { - return maybe.just(lib.PrivateKey.from_normal_bytes(bytes)); - } catch (_) { - return maybe.nothing; - } - }; -} - -export function privateKeyToBech32(privateKey) { - return privateKey.to_bech32(); -} - -export function _privateKeyFromBech32(maybe) { - return bech32 => { - try { - return maybe.just(lib.PrivateKey.from_bech32(bech32)); - } catch (_) { - return maybe.nothing; - } - }; -} diff --git a/src/Internal/Deserialization/Keys.purs b/src/Internal/Deserialization/Keys.purs deleted file mode 100644 index 0bd74b990b..0000000000 --- a/src/Internal/Deserialization/Keys.purs +++ /dev/null @@ -1,48 +0,0 @@ -module Ctl.Internal.Deserialization.Keys - ( publicKeyFromBech32 - , privateKeyFromBytes - , ed25519SignatureFromBech32 - , privateKeyToBech32 - , privateKeyFromBech32 - , freshPrivateKey - ) where - -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Ctl.Internal.Serialization.Types - ( Ed25519Signature - , PrivateKey - , PublicKey - ) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.RawBytes (RawBytes) -import Data.Maybe (Maybe) -import Effect (Effect) - -publicKeyFromBech32 :: Bech32String -> Maybe PublicKey -publicKeyFromBech32 = _publicKeyFromBech32 maybeFfiHelper - -privateKeyFromBytes :: RawBytes -> Maybe PrivateKey -privateKeyFromBytes = _privateKeyFromBytes maybeFfiHelper - -ed25519SignatureFromBech32 :: Bech32String -> Maybe Ed25519Signature -ed25519SignatureFromBech32 = _ed25519SignatureFromBech32 maybeFfiHelper - -privateKeyFromBech32 :: Bech32String -> Maybe PrivateKey -privateKeyFromBech32 = _privateKeyFromBech32 maybeFfiHelper - -foreign import freshPrivateKey - :: Effect PrivateKey - -foreign import _ed25519SignatureFromBech32 - :: MaybeFfiHelper -> Bech32String -> Maybe Ed25519Signature - -foreign import _publicKeyFromBech32 - :: MaybeFfiHelper -> Bech32String -> Maybe PublicKey - -foreign import _privateKeyFromBytes - :: MaybeFfiHelper -> RawBytes -> Maybe PrivateKey - -foreign import privateKeyToBech32 :: PrivateKey -> Bech32String - -foreign import _privateKeyFromBech32 - :: MaybeFfiHelper -> Bech32String -> Maybe PrivateKey diff --git a/src/Internal/Deserialization/Language.js b/src/Internal/Deserialization/Language.js deleted file mode 100644 index e39c2a5aac..0000000000 --- a/src/Internal/Deserialization/Language.js +++ /dev/null @@ -1,20 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function _convertLanguage(langCtors) { - return cslLang => { - if (cslLang.kind() == lib.LanguageKind.PlutusV1) { - return langCtors.plutusV1; - } else if (cslLang.kind() == lib.LanguageKind.PlutusV2) { - return langCtors.plutusV2; - } else { - throw "_convertLanguage: Unsupported language kind: " + cslLang.kind(); - } - }; -} diff --git a/src/Internal/Deserialization/Language.purs b/src/Internal/Deserialization/Language.purs deleted file mode 100644 index 8d7c34e436..0000000000 --- a/src/Internal/Deserialization/Language.purs +++ /dev/null @@ -1,19 +0,0 @@ -module Ctl.Internal.Deserialization.Language - ( _convertLanguage - , convertLanguage - ) where - -import Ctl.Internal.Serialization.Types (Language) as Csl -import Ctl.Internal.Types.Scripts (Language(PlutusV1, PlutusV2)) as T - -convertLanguage :: Csl.Language -> T.Language -convertLanguage = _convertLanguage - { plutusV1: T.PlutusV1 - , plutusV2: T.PlutusV2 - } - -foreign import _convertLanguage - :: { plutusV1 :: T.Language, plutusV2 :: T.Language } - -> Csl.Language - -> T.Language - diff --git a/src/Internal/Deserialization/NativeScript.js b/src/Internal/Deserialization/NativeScript.js deleted file mode 100644 index 4ef2dc16ba..0000000000 --- a/src/Internal/Deserialization/NativeScript.js +++ /dev/null @@ -1,49 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function _convertNativeScript(handler) { - return ns => { - switch (ns.kind()) { - case lib.NativeScriptKind.ScriptPubkey: - return handler.scriptPubkey(ns.as_script_pubkey()); - case lib.NativeScriptKind.ScriptAll: - return handler.scriptAll(ns.as_script_all()); - case lib.NativeScriptKind.ScriptAny: - return handler.scriptAny(ns.as_script_any()); - case lib.NativeScriptKind.ScriptNOfK: - return handler.scriptNOfK(ns.as_script_n_of_k()); - case lib.NativeScriptKind.TimelockStart: - return handler.timelockStart(ns.as_timelock_start()); - case lib.NativeScriptKind.TimelockExpiry: - return handler.timelockExpiry(ns.as_timelock_expiry()); - default: - throw "Impossible native script kind: " + ns.kind(); - } - }; -} - -const call = property => object => object[property](); - -export const scriptPubkey_addr_keyhash = call("addr_keyhash"); - -export function scriptAllScripts(helper) { - return helper.unpackFromProperty("native_scripts"); -} - -export function scriptAnyScripts(helper) { - return helper.unpackFromProperty("native_scripts"); -} - -export function scriptNOfKScripts(helper) { - return helper.unpackFromProperty("native_scripts"); -} - -export const scriptNOfK_n = call("n"); -export const timelockStart_slot = call("slot_bignum"); -export const timelockExpiry_slot = call("slot_bignum"); diff --git a/src/Internal/Deserialization/NativeScript.purs b/src/Internal/Deserialization/NativeScript.purs deleted file mode 100644 index 43d9ab3050..0000000000 --- a/src/Internal/Deserialization/NativeScript.purs +++ /dev/null @@ -1,76 +0,0 @@ -module Ctl.Internal.Deserialization.NativeScript - ( convertNativeScript - , decodeNativeScript - ) where - -import Prelude - -import Aeson (JsonDecodeError(TypeMismatch)) -import Ctl.Internal.Cardano.Types.NativeScript as T -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.FfiHelpers - ( ContainerHelper - , containerHelper - ) -import Ctl.Internal.Serialization.Address (Slot(Slot)) -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash) -import Ctl.Internal.Serialization.Types - ( NativeScript - , ScriptAll - , ScriptAny - , ScriptNOfK - , ScriptPubkey - , TimelockExpiry - , TimelockStart - ) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Data.Either (Either, note) -import Data.Newtype (wrap) - -type ConvertNativeScript (r :: Type) = - { scriptPubkey :: ScriptPubkey -> r - , scriptAll :: ScriptAll -> r - , scriptAny :: ScriptAny -> r - , scriptNOfK :: ScriptNOfK -> r - , timelockStart :: TimelockStart -> r - , timelockExpiry :: TimelockExpiry -> r - } - -decodeNativeScript :: ByteArray -> Either JsonDecodeError T.NativeScript -decodeNativeScript scriptBytes = do - nativeScript <- - flip note (fromBytes $ wrap scriptBytes) $ - TypeMismatch "decodeNativeScript: from_bytes() call failed" - pure $ convertNativeScript nativeScript - -convertNativeScript :: NativeScript -> T.NativeScript -convertNativeScript ns = _convertNativeScript - { scriptPubkey: T.ScriptPubkey <<< scriptPubkey_addr_keyhash - , scriptAll: T.ScriptAll <<< map convertNativeScript <<< scriptAllScripts - containerHelper - , scriptAny: T.ScriptAny <<< map convertNativeScript <<< scriptAnyScripts - containerHelper - , scriptNOfK: T.ScriptNOfK <$> scriptNOfK_n <*> - (map convertNativeScript <<< scriptNOfKScripts containerHelper) - , timelockStart: T.TimelockStart <<< Slot <<< timelockStart_slot - , timelockExpiry: T.TimelockExpiry <<< Slot <<< timelockExpiry_slot - } - ns - -foreign import _convertNativeScript - :: ConvertNativeScript T.NativeScript -> NativeScript -> T.NativeScript - -foreign import scriptPubkey_addr_keyhash :: ScriptPubkey -> Ed25519KeyHash -foreign import scriptAllScripts - :: ContainerHelper -> ScriptAll -> Array NativeScript - -foreign import scriptAnyScripts - :: ContainerHelper -> ScriptAny -> Array NativeScript - -foreign import scriptNOfKScripts - :: ContainerHelper -> ScriptNOfK -> Array NativeScript - -foreign import scriptNOfK_n :: ScriptNOfK -> Int -foreign import timelockStart_slot :: TimelockStart -> BigNum -foreign import timelockExpiry_slot :: TimelockExpiry -> BigNum diff --git a/src/Internal/Deserialization/PlutusData.js b/src/Internal/Deserialization/PlutusData.js deleted file mode 100644 index 3d0c288050..0000000000 --- a/src/Internal/Deserialization/PlutusData.js +++ /dev/null @@ -1,52 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function _convertPlutusData(handle) { - return pd => { - switch (pd.kind()) { - case lib.PlutusDataKind.ConstrPlutusData: - return handle.constr(pd.as_constr_plutus_data()); - case lib.PlutusDataKind.Map: - return handle.map(pd.as_map()); - case lib.PlutusDataKind.List: - return handle.list(pd.as_list()); - case lib.PlutusDataKind.Integer: - return handle.integer(pd.as_integer()); - case lib.PlutusDataKind.Bytes: - return handle.bytes(pd.as_bytes()); - default: - throw "Impossible PlutusData kind: " + pd.kind(); - } - }; -} - -export function _unpackPlutusList(containerHelper) { - return containerHelper.unpack; -} - -export function _ConstrPlutusData_alternative(x) { - return x.alternative(); -} - -export function _ConstrPlutusData_data(x) { - return x.data(); -} - -export function _unpackPlutusMap(containerHelper) { - return tuple => plutusMap => { - const keys = containerHelper.unpack(plutusMap.keys()); - const res = []; - for (let key of keys) { - // Assuming that `PlutusMap.get()` never fails on elements from result of - // its `.keys()` call. - res.push(tuple(key)(plutusMap.get(key))); - } - return res; - }; -} diff --git a/src/Internal/Deserialization/PlutusData.purs b/src/Internal/Deserialization/PlutusData.purs deleted file mode 100644 index 7a87147968..0000000000 --- a/src/Internal/Deserialization/PlutusData.purs +++ /dev/null @@ -1,93 +0,0 @@ -module Ctl.Internal.Deserialization.PlutusData - ( convertPlutusData - , deserializeData - ) where - -import Prelude - -import Ctl.Internal.Deserialization.BigInt (convertBigInt) -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.FfiHelpers - ( ContainerHelper - , containerHelper - ) -import Ctl.Internal.FromData (class FromData, fromData) -import Ctl.Internal.Serialization.Types - ( BigInt - , ConstrPlutusData - , PlutusData - , PlutusList - , PlutusMap - ) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes) -import Ctl.Internal.Types.PlutusData - ( PlutusData(Constr, Map, List, Integer, Bytes) - ) as T -import Data.Maybe (Maybe, fromJust) -import Data.Tuple (Tuple(Tuple)) -import Data.Tuple.Nested (type (/\), (/\)) -import Partial.Unsafe (unsafePartial) - -type ConvertPlutusData = - { constr :: ConstrPlutusData -> T.PlutusData - , map :: PlutusMap -> T.PlutusData - , list :: PlutusList -> T.PlutusData - , integer :: BigInt -> T.PlutusData - , bytes :: ByteArray -> T.PlutusData - } - -convertPlutusData :: PlutusData -> T.PlutusData -convertPlutusData pd = _convertPlutusData - { constr: convertPlutusConstr - , map: convertPlutusMap - , list: convertPlutusList - , integer: convertPlutusInteger - , bytes: convertPlutusBytes - } - pd - -convertPlutusConstr :: ConstrPlutusData -> T.PlutusData -convertPlutusConstr constr = do - let - data' = convertPlutusData <$> - _unpackPlutusList containerHelper (_ConstrPlutusData_data constr) - alt = _ConstrPlutusData_alternative constr - T.Constr alt data' - -convertPlutusMap :: PlutusMap -> T.PlutusData -convertPlutusMap = - _unpackPlutusMap containerHelper Tuple - >>> map - (\(k /\ v) -> (convertPlutusData k /\ convertPlutusData v)) - >>> T.Map - -convertPlutusList :: PlutusList -> T.PlutusData -convertPlutusList = - _unpackPlutusList containerHelper >>> map (\d -> convertPlutusData d) >>> - T.List - --- Unsafe fromJust here is correct, due to arbitrary sized integers -convertPlutusInteger :: BigInt -> T.PlutusData -convertPlutusInteger i = T.Integer $ unsafePartial $ fromJust $ convertBigInt i - -convertPlutusBytes :: ByteArray -> T.PlutusData -convertPlutusBytes = T.Bytes - -deserializeData :: forall (a :: Type). FromData a => CborBytes -> Maybe a -deserializeData = fromData <<< convertPlutusData <=< fromBytes - -foreign import _convertPlutusData - :: ConvertPlutusData -> PlutusData -> T.PlutusData - -foreign import _unpackPlutusList - :: ContainerHelper -> PlutusList -> Array PlutusData - -foreign import _ConstrPlutusData_alternative :: ConstrPlutusData -> BigNum -foreign import _ConstrPlutusData_data :: ConstrPlutusData -> PlutusList -foreign import _unpackPlutusMap - :: ContainerHelper - -> (forall a b. a -> b -> Tuple a b) - -> PlutusMap - -> Array (PlutusData /\ PlutusData) diff --git a/src/Internal/Deserialization/Transaction.js b/src/Internal/Deserialization/Transaction.js deleted file mode 100644 index 57faa3572c..0000000000 --- a/src/Internal/Deserialization/Transaction.js +++ /dev/null @@ -1,378 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -const call = property => object => object[property](); -const callMaybe = property => maybe => object => { - const res = object[property](); - return res != null ? maybe.just(res) : maybe.nothing; -}; - -export function _txIsValid(tx) { - return tx.is_valid(); -} - -export function _txWitnessSet(tx) { - return tx.witness_set(); -} - -export function _txBody(tx) { - return tx.body(); -} - -const maybeGetter_ = fmap => propstr => maybe => obj => { - if (typeof propstr != "string") { - const s = "maybeGetter_ propstr must be a string, got " + propstr; - throw s; - } - const res = obj[propstr](); - return res == null ? maybe.nothing : maybe.just(fmap(res)); -}; -const maybeGetter = maybeGetter_(a => a); -const maybeGetterMulti = propstr => containerHelper => - maybeGetter_(o => containerHelper.unpack(o))(propstr); - -export const _txAuxiliaryData = maybeGetter("auxiliary_data"); -export const _adGeneralMetadata = maybeGetter("metadata"); -export const _adNativeScripts = maybeGetter("native_scripts"); -export const _adPlutusScripts = maybeGetter("plutus_scripts"); - -// inputs(): TransactionInputs; -export function _txBodyInputs(containerhelper) { - return body => containerhelper.unpack(body.inputs()); -} - -// outputs(): TransactionOutputs; -export function _txBodyOutputs(containerhelper) { - return body => containerhelper.unpack(body.outputs()); -} - -// fee(): BigNum; -export function _txBodyFee(body) { - return body.fee(); -} - -// ttl(): number | void; -export const _txBodyTtl = maybeGetter("ttl_bignum"); - -// certs(): Certificates | void; -export const _txBodyCerts = maybeGetterMulti("certs"); - -// withdrawals(): Withdrawals | void; -export const _txBodyWithdrawals = maybeGetter("withdrawals"); - -// update(): Update | void; -export const _txBodyUpdate = maybeGetter("update"); - -// auxiliary_data_hash(): AuxiliaryDataHash | void; -export const _txBodyAuxiliaryDataHash = maybeGetter("auxiliary_data_hash"); - -// validity_start_interval(): number | void; -export const _txBodyValidityStartInterval = maybeGetter( - "validity_start_interval_bignum" -); - -// multiassets(): Mint | void; -export const _txBodyMultiAssets = maybeGetter("multiassets"); - -export function _txBodyReferenceInputs(maybe) { - return containerhelper => body => - body.reference_inputs() - ? maybe.just(containerhelper.unpack(body.reference_inputs())) - : maybe.nothing; -} - -// script_data_hash(): ScriptDataHash | void; -export const _txBodyScriptDataHash = maybeGetter("script_data_hash"); - -// collateral(): Array TransactionInput | void; -export const _txBodyCollateral = maybeGetterMulti("collateral"); - -// required_signers(): Ed25519KeyHashes | void; -export const _txBodyRequiredSigners = maybeGetterMulti("required_signers"); - -// network_id(): number | void; -export function _txBodyNetworkId(testnet) { - return mainnet => - maybeGetter_(o => { - switch (o.kind()) { - case lib.NetworkIdKind.Testnet: - return testnet; - case lib.NetworkIdKind.Mainnet: - return mainnet; - default: - throw "Unknown NetworkIdKind: " + o.kind(); - } - })("network_id"); -} - -// collateral_return(): TransactionOutput | void; -export const _txBodyCollateralReturn = maybeGetter("collateral_return"); - -// total_collateral(): BigNum | void -export const _txBodyTotalCollateral = maybeGetter("total_collateral"); - -// foreign import _unpackWithdrawals :: ContainerHelper -> CSL.Withdrawals -> Array(Tuple CSL.RewardAddress CSL.BigNum) -export function _unpackWithdrawals(containerhelper) { - return containerhelper.unpackKeyIndexed; -} - -export function _unpackUpdate(containerhelper) { - return update => { - const pppus = containerhelper.unpackKeyIndexed( - update.proposed_protocol_parameter_updates() - ); - return { epoch: update.epoch(), paramUpdates: pppus }; - }; -} - -export function _unpackMint(containerhelper) { - return containerhelper.unpackKeyIndexed; -} - -export function _unpackMintAssets(containerhelper) { - return containerhelper.unpackKeyIndexed; -} - -export function _convertCert(certConvHelper) { - return cert => { - switch (cert.kind()) { - case lib.CertificateKind.StakeRegistration: - return certConvHelper.stakeRegistration( - cert.as_stake_registration().stake_credential() - ); - case lib.CertificateKind.StakeDeregistration: - return certConvHelper.stakeDeregistration( - cert.as_stake_deregistration().stake_credential() - ); - case lib.CertificateKind.StakeDelegation: - return certConvHelper.stakeDelegation( - cert.as_stake_delegation().stake_credential() - )(cert.as_stake_delegation().pool_keyhash()); - case lib.CertificateKind.PoolRegistration: - return certConvHelper.poolRegistration( - cert.as_pool_registration().pool_params() - ); - case lib.CertificateKind.PoolRetirement: - return certConvHelper.poolRetirement( - cert.as_pool_retirement().pool_keyhash() - )(cert.as_pool_retirement().epoch()); - case lib.CertificateKind.GenesisKeyDelegation: - return certConvHelper.genesisKeyDelegation( - cert.as_genesis_key_delegation().genesishash() - )(cert.as_genesis_key_delegation().genesis_delegate_hash())( - cert.as_genesis_key_delegation().vrf_keyhash() - ); - case lib.CertificateKind.MoveInstantaneousRewardsCert: - const mirCert = cert.as_move_instantaneous_rewards_cert(); - const mir = mirCert.move_instantaneous_reward(); - switch (mir.kind()) { - case lib.MIRKind.ToOtherPot: - return certConvHelper.moveInstantaneousRewardsToOtherPotCert( - mir.pot() - )(mir.as_to_other_pot()); - case lib.MIRKind.ToStakeCredentials: - return certConvHelper.moveInstantaneousRewardsToStakeCreds( - mir.pot() - )(mir.as_to_stake_creds()); - default: - throw ( - "MoveInstantaneousReward convertion failed for kind" + mir.kind() - ); - } - default: - throw ("Cert conversion failed for kind: ", cert.kind()); - } - }; -} - -export function _unpackProtocolParamUpdate(maybe) { - return ppu => { - const optional = x => (x == null ? maybe.nothing : maybe.just(x)); - - return { - minfeeA: optional(ppu.minfee_a()), - minfeeB: optional(ppu.minfee_b()), - maxBlockBodySize: optional(ppu.max_block_body_size()), - maxTxSize: optional(ppu.max_tx_size()), - maxBlockHeaderSize: optional(ppu.max_block_header_size()), - keyDeposit: optional(ppu.key_deposit()), - poolDeposit: optional(ppu.pool_deposit()), - maxEpoch: optional(ppu.max_epoch()), - nOpt: optional(ppu.n_opt()), - poolPledgeInfluence: optional(ppu.pool_pledge_influence()), - expansionRate: optional(ppu.expansion_rate()), - treasuryGrowthRate: optional(ppu.treasury_growth_rate()), - protocolVersion: optional(ppu.protocol_version()), - minPoolCost: optional(ppu.min_pool_cost()), - adaPerUtxoByte: optional(ppu.ada_per_utxo_byte()), - costModels: optional(ppu.cost_models()), - executionCosts: optional(ppu.execution_costs()), - maxTxExUnits: optional(ppu.max_tx_ex_units()), - maxBlockExUnits: optional(ppu.max_block_ex_units()), - maxValueSize: optional(ppu.max_value_size()), - collateralPercentage: optional(ppu.collateral_percentage()), - maxCollateralInputs: optional(ppu.max_collateral_inputs()) - }; - }; -} - -export function _unpackCostModels(containerhelper) { - return containerhelper.unpackKeyIndexed; -} - -export function _unpackCostModel(cm) { - const res = []; - for (let op = 0; op < cm.len(); op++) { - res.push(cm.get(op).to_str()); - } - return res; -} - -export function _convertNonce(nonceCtors) { - return cslNonce => { - const hashBytes = cslNonce.get_hash(); - return hashBytes == null - ? nonceCtors.identityNonce - : nonceCtors.hashNonce(hashBytes); - }; -} - -export function _unpackMetadatums(containerHelper) { - return containerHelper.unpackKeyIndexed; -} - -export function _unpackMetadataMap(containerHelper) { - return containerHelper.unpackKeyIndexed; -} - -export function _unpackMetadataList(containerHelper) { - return containerHelper.unpack; -} - -export function _convertMetadatum(metadataCtors) { - return cslMetadatum => { - switch (cslMetadatum.kind()) { - case lib.TransactionMetadatumKind.MetadataMap: - return metadataCtors.from_map(cslMetadatum.as_map()); - case lib.TransactionMetadatumKind.MetadataList: - return metadataCtors.from_list(cslMetadatum.as_list()); - case lib.TransactionMetadatumKind.Int: - return metadataCtors.from_int(cslMetadatum.as_int()); - case lib.TransactionMetadatumKind.Bytes: - return metadataCtors.from_bytes(cslMetadatum.as_bytes()); - case lib.TransactionMetadatumKind.Text: - return metadataCtors.from_text(cslMetadatum.as_text()); - default: - throw "Could not convert to known types."; - } - }; -} - -export function _unpackExUnits(exunits) { - return { - mem: exunits.mem(), - steps: exunits.steps() - }; -} - -export function _unpackUnitInterval(ui) { - return { - numerator: ui.numerator(), - denominator: ui.denominator() - }; -} - -export function _unpackProtocolVersion(cslPV) { - return { - major: cslPV.major(), - minor: cslPV.minor() - }; -} - -export function _unpackExUnitsPrices(cslEup) { - return { - memPrice: cslEup.mem_price(), - stepPrice: cslEup.step_price() - }; -} - -export const poolParamsOperator = call("operator"); -export const poolParamsVrfKeyhash = call("vrf_keyhash"); -export const poolParamsPledge = call("pledge"); -export const poolParamsCost = call("cost"); -export const poolParamsMargin = call("margin"); -export const poolParamsRewardAccount = call("reward_account"); - -export function poolParamsPoolOwners(containerHelper) { - return poolParams => containerHelper.unpack(poolParams.pool_owners()); -} - -export function poolParamsRelays(containerHelper) { - return poolParams => containerHelper.unpack(poolParams.relays()); -} - -export const poolParamsPoolMetadata = callMaybe("pool_metadata"); - -export function convertRelay_(helper) { - return relay => { - switch (relay.kind()) { - case lib.RelayKind.SingleHostAddr: - return helper.asSingleHostAddr(relay.as_single_host_addr()); - case lib.RelayKind.SingleHostName: - return helper.asSingleHostName(relay.as_single_host_name()); - case lib.RelayKind.MultiHostName: - return helper.asMultiHostName(relay.as_multi_host_name()); - default: - throw "convertRelay_: impossible happened: invalid Relay"; - } - }; -} - -export function convertIpv6_(ipv6) { - return ipv6.ip(); -} - -export function convertIpv4_(ipv6) { - return ipv6.ip(); -} - -export function convertSingleHostAddr_(maybe) { - return cont => singleHostAddr => { - const port = singleHostAddr.port(); - const ipv4 = singleHostAddr.ipv4(); - const ipv6 = singleHostAddr.ipv6(); - - return cont(port ? maybe.just(port) : maybe.nothing)( - ipv4 ? maybe.just(ipv4) : maybe.nothing - )(ipv6 ? maybe.just(ipv6) : maybe.nothing); - }; -} - -export function convertSingleHostName_(maybe) { - return cont => singleHostName => { - const port = singleHostName.port(); - return cont(port ? maybe.just(port) : maybe.nothing)( - singleHostName.dns_name().record() - ); - }; -} - -export function convertMultiHostName_(multiHostName) { - return multiHostName.dns_name().record(); -} - -export function unpackMIRToStakeCredentials_(containerHelper) { - return mirToStakeCredentials => - containerHelper.unpackKeyIndexed(mirToStakeCredentials); -} - -export function convertPoolMetadata_(cont) { - return poolMetadata => - cont(poolMetadata.url().url())(poolMetadata.pool_metadata_hash()); -} diff --git a/src/Internal/Deserialization/Transaction.purs b/src/Internal/Deserialization/Transaction.purs deleted file mode 100644 index 522b5474f8..0000000000 --- a/src/Internal/Deserialization/Transaction.purs +++ /dev/null @@ -1,891 +0,0 @@ -module Ctl.Internal.Deserialization.Transaction - ( CertConvHelper - , MetadatumHelper - , _adGeneralMetadata - , _adNativeScripts - , _adPlutusScripts - , _convertCert - , _convertMetadatum - , _convertNonce - , _txAuxiliaryData - , _txBody - , _txBodyAuxiliaryDataHash - , _txBodyCerts - , _txBodyCollateral - , _txBodyFee - , _txBodyInputs - , _txBodyMultiAssets - , _txBodyNetworkId - , _txBodyOutputs - , _txBodyRequiredSigners - , _txBodyScriptDataHash - , _txBodyTtl - , _txBodyUpdate - , _txBodyValidityStartInterval - , _txBodyWithdrawals - , _txIsValid - , _txWitnessSet - , _unpackCostModel - , _unpackCostModels - , _unpackExUnits - , _unpackExUnitsPrices - , _unpackMetadataList - , _unpackMetadataMap - , _unpackMetadatums - , _unpackMint - , _unpackMintAssets - , _unpackProtocolParamUpdate - , _unpackProtocolVersion - , _unpackUnitInterval - , _unpackUpdate - , _unpackWithdrawals - , convertAuxiliaryData - , convertCertificate - , convertCostModel - , convertCostModels - , convertExUnitPrices - , convertExUnits - , convertGeneralTransactionMetadata - , convertMetadataList - , convertMetadataMap - , convertMetadatum - , convertMint - , convertNonce - , convertProtocolParamUpdate - , convertProtocolVersion - , convertTransaction - , convertTxBody - , convertUpdate - , cslNumberToUInt - , cslRatioToRational - , deserializeTransaction - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.Transaction - ( AuxiliaryData(AuxiliaryData) - , AuxiliaryDataHash(AuxiliaryDataHash) - , Certificate - ( StakeDeregistration - , StakeRegistration - , StakeDelegation - , PoolRegistration - , PoolRetirement - , GenesisKeyDelegation - , MoveInstantaneousRewardsCert - ) - , CostModel(CostModel) - , Costmdls(Costmdls) - , Epoch(Epoch) - , ExUnitPrices - , ExUnits - , GenesisDelegateHash(GenesisDelegateHash) - , GenesisHash(GenesisHash) - , Ipv4(Ipv4) - , Ipv6(Ipv6) - , MIRToStakeCredentials(MIRToStakeCredentials) - , Mint(Mint) - , MoveInstantaneousReward(ToOtherPot, ToStakeCreds) - , Nonce(HashNonce, IdentityNonce) - , PoolMetadata(PoolMetadata) - , PoolMetadataHash(PoolMetadataHash) - , ProposedProtocolParameterUpdates(ProposedProtocolParameterUpdates) - , ProtocolParamUpdate - , ProtocolVersion - , Relay(SingleHostAddr, SingleHostName, MultiHostName) - , RequiredSigner(RequiredSigner) - , ScriptDataHash(ScriptDataHash) - , Transaction(Transaction) - , TxBody(TxBody) - , URL(URL) - , Update - ) as T -import Ctl.Internal.Cardano.Types.Transaction (PoolPubKeyHash(PoolPubKeyHash)) -import Ctl.Internal.Cardano.Types.Value - ( Coin(Coin) - , mkNonAdaAsset - , scriptHashAsCurrencySymbol - ) -import Ctl.Internal.Deserialization.Error - ( Err - , FromCslRepError - , addErrTrace - , cslErr - ) -import Ctl.Internal.Deserialization.FromBytes (fromBytes') -import Ctl.Internal.Deserialization.Language (convertLanguage) -import Ctl.Internal.Deserialization.UnspentOutput (convertInput, convertOutput) -import Ctl.Internal.Deserialization.WitnessSet - ( convertNativeScripts - , convertPlutusScripts - , convertWitnessSet - ) -import Ctl.Internal.Error (E) -import Ctl.Internal.FfiHelpers - ( ContainerHelper - , MaybeFfiHelper - , containerHelper - , maybeFfiHelper - ) -import Ctl.Internal.Serialization (toBytes) -import Ctl.Internal.Serialization.Address - ( NetworkId(TestnetId, MainnetId) - , RewardAddress - , StakeCredential - ) as Csl -import Ctl.Internal.Serialization.Address (Slot(Slot)) -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash, ScriptHash, VRFKeyHash) as Csl -import Ctl.Internal.Serialization.Types - ( AssetName - , AuxiliaryData - , AuxiliaryDataHash - , Certificate - , CostModel - , Costmdls - , ExUnitPrices - , ExUnits - , GeneralTransactionMetadata - , GenesisDelegateHash - , GenesisHash - , Ipv4 - , Ipv6 - , Language - , MIRToStakeCredentials - , MetadataList - , MetadataMap - , Mint - , MintAssets - , MultiHostName - , NativeScripts - , Nonce - , PlutusScripts - , PoolMetadata - , PoolMetadataHash - , PoolParams - , ProtocolParamUpdate - , ProtocolVersion - , Relay - , ScriptDataHash - , SingleHostAddr - , SingleHostName - , Transaction - , TransactionBody - , TransactionInput - , TransactionMetadatum - , TransactionOutput - , TransactionWitnessSet - , UnitInterval - , Update - , Withdrawals - ) as Csl -import Ctl.Internal.Types.BigNum (BigNum) as Csl -import Ctl.Internal.Types.BigNum (toBigInt) as BigNum -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes) -import Ctl.Internal.Types.Int (Int) as Csl -import Ctl.Internal.Types.Int as Int -import Ctl.Internal.Types.RewardAddress (RewardAddress(RewardAddress)) as T -import Ctl.Internal.Types.TokenName (TokenName, tokenNameFromAssetName) -import Ctl.Internal.Types.TransactionMetadata - ( GeneralTransactionMetadata - , TransactionMetadatum(MetadataList, MetadataMap, Bytes, Int, Text) - , TransactionMetadatumLabel(TransactionMetadatumLabel) - ) -import Ctl.Internal.Types.VRFKeyHash (VRFKeyHash(VRFKeyHash)) -import Data.Bifunctor (bimap, lmap) -import Data.Bitraversable (bitraverse) -import Data.Either (Either) -import Data.Map as M -import Data.Maybe (Maybe, fromMaybe) -import Data.Newtype (unwrap, wrap) -import Data.Ratio (Ratio, reduce) -import Data.Set (fromFoldable) as Set -import Data.Traversable (traverse) -import Data.Tuple.Nested (type (/\)) -import Data.UInt (UInt) -import Data.UInt as UInt -import Data.Variant (Variant) -import JS.BigInt (BigInt) -import JS.BigInt as BigInt -import Type.Row (type (+)) - --- | Deserializes CBOR encoded transaction to a CTL's native type. -deserializeTransaction - :: forall (r :: Row Type). CborBytes -> Err r T.Transaction -deserializeTransaction txCbor = fromBytes' (unwrap txCbor) >>= - convertTransaction - --- | Converts transaction from foreign CSL representation to CTL's one. -convertTransaction - :: forall (r :: Row Type). Csl.Transaction -> Err r T.Transaction -convertTransaction tx = addErrTrace "convertTransaction" do - body <- convertTxBody $ _txBody tx - let - witnessSet = convertWitnessSet (_txWitnessSet tx) - auxiliaryData = convertAuxiliaryData <$> - _txAuxiliaryData maybeFfiHelper tx - pure $ T.Transaction - { body - , witnessSet - , isValid: _txIsValid tx - , auxiliaryData - } - --- | Converts transaction body from foreign CSL representation to CTL's one. -convertTxBody :: forall (r :: Row Type). Csl.TransactionBody -> Err r T.TxBody -convertTxBody txBody = do - let - inputs = Set.fromFoldable $ convertInput <$> _txBodyInputs containerHelper - txBody - - outputs <- - _txBodyOutputs containerHelper txBody - # traverse (convertOutput >>> cslErr "TransactionOutput") - let - fee = Coin $ BigNum.toBigInt $ _txBodyFee txBody - networkId = - _txBodyNetworkId Csl.TestnetId Csl.MainnetId maybeFfiHelper txBody - - ws :: Maybe (Array (Csl.RewardAddress /\ Csl.BigNum)) - ws = _unpackWithdrawals containerHelper <$> _txBodyWithdrawals - maybeFfiHelper - txBody - - withdrawals :: Maybe (M.Map T.RewardAddress Coin) <- - -- array -> map - (map <<< map) (M.fromFoldable <<< map (lmap T.RewardAddress)) - -- bignum -> coin - <<< (traverse <<< traverse <<< traverse) - (BigNum.toBigInt >>> Coin >>> pure) - $ ws - - update <- traverse convertUpdate $ _txBodyUpdate maybeFfiHelper txBody - - let - cslReferenceInputs :: Array Csl.TransactionInput - cslReferenceInputs = - _txBodyReferenceInputs maybeFfiHelper containerHelper txBody - # fromMaybe mempty - - referenceInputs = Set.fromFoldable $ convertInput <$> cslReferenceInputs - - certs = map convertCertificate <$> - _txBodyCerts containerHelper - maybeFfiHelper - txBody - - collateralReturn <- - _txBodyCollateralReturn maybeFfiHelper txBody # - traverse (convertOutput >>> cslErr "TransactionOutput") - - let - totalCollateral = _txBodyTotalCollateral maybeFfiHelper txBody <#> - (BigNum.toBigInt >>> Coin) - - pure $ T.TxBody - { inputs - , outputs - , fee - , ttl: Slot <$> _txBodyTtl maybeFfiHelper txBody - , certs - , withdrawals - , update - , auxiliaryDataHash: - T.AuxiliaryDataHash <<< unwrap <<< toBytes <$> - _txBodyAuxiliaryDataHash maybeFfiHelper txBody - , validityStartInterval: - Slot <$> _txBodyValidityStartInterval maybeFfiHelper txBody - , mint: map convertMint $ _txBodyMultiAssets maybeFfiHelper txBody - , referenceInputs - , scriptDataHash: convertScriptDataHash <$> _txBodyScriptDataHash - maybeFfiHelper - txBody - , collateral: _txBodyCollateral containerHelper maybeFfiHelper txBody >>= - map convertInput >>> pure - , requiredSigners: - _txBodyRequiredSigners containerHelper maybeFfiHelper txBody # - (map <<< map) T.RequiredSigner - , networkId - , collateralReturn - , totalCollateral - } - -convertUpdate :: forall (r :: Row Type). Csl.Update -> Err r T.Update -convertUpdate u = do - let { epoch: e, paramUpdates } = _unpackUpdate containerHelper u - epoch <- map T.Epoch $ cslNumberToUInt "convertUpdate: epoch" e - ppus <- traverse - ( bitraverse - (pure <<< T.GenesisHash <<< unwrap <<< toBytes) - convertProtocolParamUpdate - ) - paramUpdates - pure - { epoch - , proposedProtocolParameterUpdates: T.ProposedProtocolParameterUpdates $ - M.fromFoldable ppus - } - -convertCertificate - :: Csl.Certificate -> T.Certificate -convertCertificate = _convertCert certConvHelper - where - certConvHelper :: CertConvHelper T.Certificate - certConvHelper = - { stakeDeregistration: T.StakeDeregistration - , stakeRegistration: T.StakeRegistration - , stakeDelegation: \sc -> T.StakeDelegation sc <<< wrap <<< wrap - , poolRegistration: convertPoolRegistration - , poolRetirement: convertPoolRetirement - , genesisKeyDelegation: \genesisHash genesisDelegateHash vrfKeyhash -> do - T.GenesisKeyDelegation - { genesisHash: T.GenesisHash $ unwrap $ toBytes genesisHash - , genesisDelegateHash: T.GenesisDelegateHash $ unwrap - $ toBytes genesisDelegateHash - , vrfKeyhash: VRFKeyHash vrfKeyhash - } - , moveInstantaneousRewardsToOtherPotCert: \pot amount -> do - T.MoveInstantaneousRewardsCert $ - T.ToOtherPot { pot, amount: amount } - , moveInstantaneousRewardsToStakeCreds: \pot amounts -> do - T.MoveInstantaneousRewardsCert $ - T.ToStakeCreds { pot, amounts: convertMIRToStakeCredentials amounts } - } - -convertMIRToStakeCredentials - :: Csl.MIRToStakeCredentials -> T.MIRToStakeCredentials -convertMIRToStakeCredentials = - T.MIRToStakeCredentials <<< M.fromFoldable <<< unpackMIRToStakeCredentials_ - containerHelper - -convertPoolRegistration :: Csl.PoolParams -> T.Certificate -convertPoolRegistration params = do - let - relays = convertRelay <$> poolParamsRelays containerHelper params - T.PoolRegistration - { operator: PoolPubKeyHash $ wrap $ poolParamsOperator params - , vrfKeyhash: VRFKeyHash $ poolParamsVrfKeyhash params - , pledge: poolParamsPledge params - , cost: poolParamsCost params - , margin: _unpackUnitInterval $ poolParamsMargin params - , rewardAccount: T.RewardAddress $ poolParamsRewardAccount params - , poolOwners: wrap <<< wrap <$> poolParamsPoolOwners containerHelper params - , relays - , poolMetadata: poolParamsPoolMetadata maybeFfiHelper params <#> - convertPoolMetadata_ - \url hash -> T.PoolMetadata - { url: T.URL url - , hash: T.PoolMetadataHash $ unwrap $ toBytes hash - } - } - -type ConvertRelayHelper a = - { asSingleHostAddr :: Csl.SingleHostAddr -> a - , asSingleHostName :: Csl.SingleHostName -> a - , asMultiHostName :: Csl.MultiHostName -> a - } - -convertRelay :: Csl.Relay -> T.Relay -convertRelay relay = do - convertRelay_ - { asSingleHostAddr: convertSingleHostAddr_ maybeFfiHelper - \mbPort mbIpv4 mbIpv6 -> do - let - ipv4 = mbIpv4 <#> convertIpv4 - ipv6 = mbIpv6 <#> convertIpv6 - T.SingleHostAddr { port: mbPort, ipv4, ipv6 } - , asSingleHostName: convertSingleHostName_ maybeFfiHelper - \port mbHost -> T.SingleHostName { port, dnsName: mbHost } - , asMultiHostName: T.MultiHostName <<< { dnsName: _ } <<< - convertMultiHostName_ - } - relay - -convertIpv6 :: Csl.Ipv6 -> T.Ipv6 -convertIpv6 = T.Ipv6 <<< convertIpv6_ - -foreign import convertIpv6_ :: Csl.Ipv6 -> ByteArray - -convertIpv4 :: Csl.Ipv4 -> T.Ipv4 -convertIpv4 = T.Ipv4 <<< convertIpv4_ - -foreign import convertIpv4_ :: Csl.Ipv4 -> ByteArray - -foreign import convertRelay_ :: forall a. ConvertRelayHelper a -> Csl.Relay -> a - -foreign import convertSingleHostAddr_ - :: forall a - . MaybeFfiHelper - -> (Maybe Int -> Maybe Csl.Ipv4 -> Maybe Csl.Ipv6 -> a) - -> Csl.SingleHostAddr - -> a - -foreign import convertSingleHostName_ - :: forall a - . MaybeFfiHelper - -> (Maybe Int -> String -> a) - -> Csl.SingleHostName - -> a - -foreign import convertMultiHostName_ - :: Csl.MultiHostName - -> String - -convertPoolRetirement - :: Csl.Ed25519KeyHash - -> UInt - -> T.Certificate -convertPoolRetirement poolKeyHash epoch = do - T.PoolRetirement { poolKeyHash: wrap $ wrap poolKeyHash, epoch: wrap epoch } - -convertMint :: Csl.Mint -> T.Mint -convertMint mint = T.Mint $ mkNonAdaAsset - $ - -- outer map - M.fromFoldable <<< map (lmap scriptHashAsCurrencySymbol) - -- inner map - <<< (map <<< map) - ( M.fromFoldable <<< map convAssetName <<< _unpackMintAssets - containerHelper - ) - $ _unpackMint containerHelper mint - - where - convAssetName :: Csl.AssetName /\ Int.Int -> TokenName /\ BigInt - convAssetName = bimap tokenNameFromAssetName Int.toBigInt - -convertProtocolParamUpdate - :: forall (r :: Row Type) - . Csl.ProtocolParamUpdate - -> Err r T.ProtocolParamUpdate -convertProtocolParamUpdate cslPpu = do - let - ppu = _unpackProtocolParamUpdate maybeFfiHelper cslPpu - lbl = (<>) "ProtocolParamUpdate." - minfeeA = Coin <<< BigNum.toBigInt <$> ppu.minfeeA - minfeeB = Coin <<< BigNum.toBigInt <$> ppu.minfeeB - maxBlockBodySize <- traverse (cslNumberToUInt (lbl "maxBlockBodySize")) - ppu.maxBlockBodySize - maxTxSize <- traverse (cslNumberToUInt (lbl "maxTxSize")) ppu.maxTxSize - maxBlockHeaderSize <- traverse (cslNumberToUInt (lbl "maxBlockHeaderSize")) - ppu.maxBlockHeaderSize - let - keyDeposit = Coin <<< BigNum.toBigInt <$> ppu.keyDeposit - poolDeposit = Coin <<< BigNum.toBigInt <$> ppu.poolDeposit - maxEpoch <- traverse (map T.Epoch <<< cslNumberToUInt (lbl "maxEpoch")) - ppu.maxEpoch - nOpt <- traverse (cslNumberToUInt (lbl "nOpt")) ppu.nOpt - protocolVersion <- traverse (convertProtocolVersion (lbl "protocolVersion")) - ppu.protocolVersion - costModels <- addErrTrace (lbl "costModels") $ traverse convertCostModels - ppu.costModels - let - maxTxExUnits = convertExUnits <$> ppu.maxTxExUnits - maxBlockExUnits = convertExUnits <$> - ppu.maxBlockExUnits - maxValueSize <- traverse (cslNumberToUInt (lbl "maxValueSize")) - ppu.maxValueSize - collateralPercentage <- traverse - (cslNumberToUInt (lbl "collateralPercentage")) - ppu.collateralPercentage - maxCollateralInputs <- traverse (cslNumberToUInt (lbl "maxCollateralInputs")) - ppu.maxCollateralInputs - pure - { minfeeA - , minfeeB - , maxBlockBodySize - , maxTxSize - , maxBlockHeaderSize - , keyDeposit - , poolDeposit - , maxEpoch - , nOpt - , poolPledgeInfluence: _unpackUnitInterval <$> ppu.poolPledgeInfluence - , expansionRate: _unpackUnitInterval <$> ppu.expansionRate - , treasuryGrowthRate: _unpackUnitInterval <$> ppu.treasuryGrowthRate - , protocolVersion - , minPoolCost: ppu.minPoolCost - , adaPerUtxoByte: ppu.adaPerUtxoByte - , costModels - , executionCosts: convertExUnitPrices <$> ppu.executionCosts - , maxTxExUnits - , maxBlockExUnits - , maxValueSize - , collateralPercentage - , maxCollateralInputs - } - -convertNonce :: Csl.Nonce -> T.Nonce -convertNonce = _convertNonce - { hashNonce: T.HashNonce, identityNonce: T.IdentityNonce } - -convertCostModels - :: forall (r :: Row Type) - . Csl.Costmdls - -> Err r T.Costmdls -convertCostModels cslCostMdls = - let - mdls :: Array (Csl.Language /\ Csl.CostModel) - mdls = _unpackCostModels containerHelper cslCostMdls - in - (T.Costmdls <<< M.fromFoldable) <$> traverse - (bitraverse (pure <<< convertLanguage) convertCostModel) - mdls - -convertCostModel - :: forall (r :: Row Type) - . Csl.CostModel - -> E (FromCslRepError + r) T.CostModel -convertCostModel = map T.CostModel <<< traverse stringToInt <<< - _unpackCostModel - where - stringToInt - :: String -> Either (Variant (fromCslRepError :: String | r)) Int.Int - stringToInt s = cslErr (": string (" <> s <> ") -> int") $ - Int.fromBigInt =<< BigInt.fromString s - -convertAuxiliaryData - :: Csl.AuxiliaryData -> T.AuxiliaryData -convertAuxiliaryData ad = do - let - metadata = convertGeneralTransactionMetadata <$> - _adGeneralMetadata maybeFfiHelper ad - T.AuxiliaryData - { metadata - , nativeScripts: pure <<< convertNativeScripts =<< _adNativeScripts - maybeFfiHelper - ad - , plutusScripts: pure <<< convertPlutusScripts =<< _adPlutusScripts - maybeFfiHelper - ad - } - -convertGeneralTransactionMetadata - :: Csl.GeneralTransactionMetadata - -> GeneralTransactionMetadata -convertGeneralTransactionMetadata gtm = wrap - $ M.fromFoldable - $ bimap (TransactionMetadatumLabel <<< BigNum.toBigInt) convertMetadatum - <$> _unpackMetadatums containerHelper gtm - -convertMetadatum :: Csl.TransactionMetadatum -> TransactionMetadatum -convertMetadatum tm = _convertMetadatum - { from_bytes: Bytes - , from_int: Int - , from_text: Text - , from_map: convertMetadataMap - , from_list: convertMetadataList - } - tm - -convertMetadataList - :: Csl.MetadataList - -> TransactionMetadatum -convertMetadataList ml = MetadataList - $ convertMetadatum <$> _unpackMetadataList containerHelper ml - -convertMetadataMap - :: Csl.MetadataMap - -> TransactionMetadatum -convertMetadataMap mm = MetadataMap - $ M.fromFoldable - $ bimap convertMetadatum convertMetadatum - <$> _unpackMetadataMap containerHelper mm - --- unpack to array of tuples - ----- conversion helpers - -cslNumberToUInt - :: forall (r :: Row Type). String -> Number -> E (FromCslRepError + r) UInt -cslNumberToUInt nm nb = cslErr (nm <> ": Number (" <> show nb <> ") -> UInt") $ - UInt.fromNumber' nb - -cslRatioToRational - :: forall (r :: Row Type) - . { denominator :: Csl.BigNum, numerator :: Csl.BigNum } - -> Ratio BigInt -cslRatioToRational { numerator, denominator } = - reduce (BigNum.toBigInt numerator) (BigNum.toBigInt denominator) - -convertExUnits - :: forall (r :: Row Type) - . Csl.ExUnits - -> T.ExUnits -convertExUnits cslExunits = - let - { mem, steps } = _unpackExUnits cslExunits - in - { mem: _, steps: _ } (BigNum.toBigInt mem) (BigNum.toBigInt steps) - -convertScriptDataHash :: Csl.ScriptDataHash -> T.ScriptDataHash -convertScriptDataHash = toBytes >>> unwrap >>> T.ScriptDataHash - -convertProtocolVersion - :: forall (r :: Row Type) - . String - -> Csl.ProtocolVersion - -> E (FromCslRepError + r) T.ProtocolVersion -convertProtocolVersion nm cslPV = - _unpackProtocolVersion cslPV # - ( \{ major, minor } -> - { major: _, minor: _ } - <$> cslNumberToUInt (nm <> " major") major - <*> cslNumberToUInt (nm <> " minor") minor - ) - ----- foreign imports - -foreign import _convertNonce - :: { identityNonce :: T.Nonce, hashNonce :: ByteArray -> T.Nonce } - -> Csl.Nonce - -> T.Nonce - -foreign import _unpackProtocolParamUpdate - :: MaybeFfiHelper - -> Csl.ProtocolParamUpdate - -> { minfeeA :: Maybe Csl.BigNum - , minfeeB :: Maybe Csl.BigNum - , maxBlockBodySize :: Maybe Number - , maxTxSize :: Maybe Number - , maxBlockHeaderSize :: Maybe Number - , keyDeposit :: Maybe Csl.BigNum - , poolDeposit :: Maybe Csl.BigNum - , maxEpoch :: Maybe Number - , nOpt :: Maybe Number - , poolPledgeInfluence :: Maybe Csl.UnitInterval - , expansionRate :: - Maybe Csl.UnitInterval - , treasuryGrowthRate :: - Maybe Csl.UnitInterval - , protocolVersion :: Maybe Csl.ProtocolVersion - , minPoolCost :: Maybe Csl.BigNum - , adaPerUtxoByte :: Maybe Csl.BigNum - , costModels :: Maybe Csl.Costmdls - , executionCosts :: Maybe Csl.ExUnitPrices - , maxTxExUnits :: Maybe Csl.ExUnits - , maxBlockExUnits :: Maybe Csl.ExUnits - , maxValueSize :: Maybe Number - , collateralPercentage :: Maybe Number - , maxCollateralInputs :: Maybe Number - } - -foreign import _unpackCostModels - :: ContainerHelper -> Csl.Costmdls -> Array (Csl.Language /\ Csl.CostModel) - -foreign import _unpackCostModel :: Csl.CostModel -> Array String - -foreign import _unpackMetadataMap - :: ContainerHelper - -> Csl.MetadataMap - -> Array (Csl.TransactionMetadatum /\ Csl.TransactionMetadatum) - -foreign import _unpackMetadataList - :: ContainerHelper -> Csl.MetadataList -> Array Csl.TransactionMetadatum - -type MetadatumHelper = - { from_map :: Csl.MetadataMap -> TransactionMetadatum - , from_list :: Csl.MetadataList -> TransactionMetadatum - , from_int :: Csl.Int -> TransactionMetadatum - , from_text :: String -> TransactionMetadatum - , from_bytes :: ByteArray -> TransactionMetadatum - } - -foreign import _unpackProtocolVersion - :: Csl.ProtocolVersion - -> { major :: Number, minor :: Number } - -foreign import _unpackExUnits - :: Csl.ExUnits -> { mem :: Csl.BigNum, steps :: Csl.BigNum } - -foreign import _unpackUnitInterval - :: Csl.UnitInterval -> { numerator :: Csl.BigNum, denominator :: Csl.BigNum } - -convertExUnitPrices :: Csl.ExUnitPrices -> T.ExUnitPrices -convertExUnitPrices cslEUP = - let - { memPrice, stepPrice } = _unpackExUnitsPrices cslEUP - in - { memPrice: _unpackUnitInterval memPrice - , stepPrice: _unpackUnitInterval stepPrice - } - -foreign import _unpackExUnitsPrices - :: Csl.ExUnitPrices - -> { memPrice :: Csl.UnitInterval, stepPrice :: Csl.UnitInterval } - -foreign import _convertMetadatum - :: MetadatumHelper - -> Csl.TransactionMetadatum - -> TransactionMetadatum - -foreign import _unpackMetadatums - :: ContainerHelper - -> Csl.GeneralTransactionMetadata - -> Array (Csl.BigNum /\ Csl.TransactionMetadatum) - -foreign import _txBody :: Csl.Transaction -> Csl.TransactionBody -foreign import _txIsValid :: Csl.Transaction -> Boolean -foreign import _txWitnessSet :: Csl.Transaction -> Csl.TransactionWitnessSet -foreign import _txAuxiliaryData - :: MaybeFfiHelper -> Csl.Transaction -> Maybe Csl.AuxiliaryData - -foreign import _adGeneralMetadata - :: MaybeFfiHelper -> Csl.AuxiliaryData -> Maybe Csl.GeneralTransactionMetadata - -foreign import _adNativeScripts - :: MaybeFfiHelper -> Csl.AuxiliaryData -> Maybe Csl.NativeScripts - -foreign import _adPlutusScripts - :: MaybeFfiHelper -> Csl.AuxiliaryData -> Maybe Csl.PlutusScripts - --- inputs(): TransactionInputs; -foreign import _txBodyInputs - :: ContainerHelper -> Csl.TransactionBody -> Array Csl.TransactionInput - --- outputs(): TransactionOutputs; -foreign import _txBodyOutputs - :: ContainerHelper -> Csl.TransactionBody -> Array Csl.TransactionOutput - --- fee(): BigNum; -foreign import _txBodyFee :: Csl.TransactionBody -> Csl.BigNum --- ttl(): number | void; -foreign import _txBodyTtl - :: MaybeFfiHelper -> Csl.TransactionBody -> Maybe Csl.BigNum - --- certs(): Certificates | void; -foreign import _txBodyCerts - :: ContainerHelper - -> MaybeFfiHelper - -> Csl.TransactionBody - -> Maybe (Array Csl.Certificate) - --- withdrawals(): Withdrawals | void -foreign import _txBodyWithdrawals - :: MaybeFfiHelper -> Csl.TransactionBody -> Maybe Csl.Withdrawals - --- update(): Update | void -foreign import _txBodyUpdate - :: MaybeFfiHelper -> Csl.TransactionBody -> Maybe Csl.Update - --- auxiliary_data_hash(): AuxiliaryDataHash | void -foreign import _txBodyAuxiliaryDataHash - :: MaybeFfiHelper -> Csl.TransactionBody -> Maybe Csl.AuxiliaryDataHash - --- validity_start_interval(): number | void -foreign import _txBodyValidityStartInterval - :: MaybeFfiHelper -> Csl.TransactionBody -> Maybe Csl.BigNum - --- multiassets(): Mint | void -foreign import _txBodyMultiAssets - :: MaybeFfiHelper -> Csl.TransactionBody -> Maybe Csl.Mint - --- reference_inputs(): TransactionInputs | void; -foreign import _txBodyReferenceInputs - :: MaybeFfiHelper - -> ContainerHelper - -> Csl.TransactionBody - -> Maybe (Array Csl.TransactionInput) - --- script_data_hash(): ScriptDataHash | void -foreign import _txBodyScriptDataHash - :: MaybeFfiHelper -> Csl.TransactionBody -> Maybe Csl.ScriptDataHash - --- collateral(): TransactionInputs | void -foreign import _txBodyCollateral - :: ContainerHelper - -> MaybeFfiHelper - -> Csl.TransactionBody - -> Maybe (Array Csl.TransactionInput) - --- required_signers(): Ed25519KeyHashes | void -foreign import _txBodyRequiredSigners - :: ContainerHelper - -> MaybeFfiHelper - -> Csl.TransactionBody - -> Maybe (Array Csl.Ed25519KeyHash) - --- network_id(): NetworkId | void -foreign import _txBodyNetworkId - :: Csl.NetworkId - -> Csl.NetworkId - -> MaybeFfiHelper - -> Csl.TransactionBody - -> Maybe Csl.NetworkId - --- collateral_return(): TransactionOutput | void -foreign import _txBodyCollateralReturn - :: MaybeFfiHelper - -> Csl.TransactionBody - -> Maybe Csl.TransactionOutput - --- total_collateral(): BigNum | void -foreign import _txBodyTotalCollateral - :: MaybeFfiHelper - -> Csl.TransactionBody - -> Maybe Csl.BigNum - -foreign import _unpackWithdrawals - :: ContainerHelper - -> Csl.Withdrawals - -> Array (Csl.RewardAddress /\ Csl.BigNum) - -foreign import _unpackUpdate - :: ContainerHelper - -> Csl.Update - -> { epoch :: Number - , paramUpdates :: Array (Csl.GenesisHash /\ Csl.ProtocolParamUpdate) - } - -foreign import _unpackMint - :: ContainerHelper -> Csl.Mint -> Array (Csl.ScriptHash /\ Csl.MintAssets) - -foreign import _unpackMintAssets - :: ContainerHelper -> Csl.MintAssets -> Array (Csl.AssetName /\ Csl.Int) - -type CertConvHelper (r :: Type) = - { stakeDeregistration :: Csl.StakeCredential -> r - , stakeRegistration :: Csl.StakeCredential -> r - , stakeDelegation :: - Csl.StakeCredential -> Csl.Ed25519KeyHash -> r - , poolRegistration :: Csl.PoolParams -> r - , poolRetirement :: Csl.Ed25519KeyHash -> UInt -> r - , genesisKeyDelegation :: - Csl.GenesisHash - -> Csl.GenesisDelegateHash - -> Csl.VRFKeyHash - -> r - , moveInstantaneousRewardsToOtherPotCert :: - Number -> Csl.BigNum -> r - , moveInstantaneousRewardsToStakeCreds :: - Number -> Csl.MIRToStakeCredentials -> r - } - -foreign import _convertCert - :: CertConvHelper T.Certificate - -> Csl.Certificate - -> T.Certificate - -foreign import poolParamsOperator :: Csl.PoolParams -> Csl.Ed25519KeyHash -foreign import poolParamsVrfKeyhash :: Csl.PoolParams -> Csl.VRFKeyHash -foreign import poolParamsPledge :: Csl.PoolParams -> Csl.BigNum -foreign import poolParamsCost :: Csl.PoolParams -> Csl.BigNum -foreign import poolParamsMargin :: Csl.PoolParams -> Csl.UnitInterval -foreign import poolParamsRewardAccount :: Csl.PoolParams -> Csl.RewardAddress -foreign import poolParamsPoolOwners - :: ContainerHelper -> Csl.PoolParams -> Array Csl.Ed25519KeyHash - -foreign import poolParamsRelays - :: ContainerHelper -> Csl.PoolParams -> Array Csl.Relay - -foreign import poolParamsPoolMetadata - :: MaybeFfiHelper -> Csl.PoolParams -> Maybe Csl.PoolMetadata - -foreign import unpackMIRToStakeCredentials_ - :: ContainerHelper - -> Csl.MIRToStakeCredentials - -> Array (Csl.StakeCredential /\ Csl.Int) - -foreign import convertPoolMetadata_ - :: forall a. (String -> Csl.PoolMetadataHash -> a) -> Csl.PoolMetadata -> a diff --git a/src/Internal/Deserialization/UnspentOutput.js b/src/Internal/Deserialization/UnspentOutput.js deleted file mode 100644 index 61f5ecbee3..0000000000 --- a/src/Internal/Deserialization/UnspentOutput.js +++ /dev/null @@ -1,71 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -const call = property => object => object[property](); -const callMaybe = property => maybe => object => { - const res = object[property](); - return res != null ? maybe.just(res) : maybe.nothing; -}; - -// Classes like TransactionInputs are just monomorphic containers with `len` -// and `get()` methods. This function abstracts away converting them to Array -// of something. -const containerExtractor = obj => { - const res = []; - - for (let i = 0; i < obj.len(); i++) { - res.push(obj.get(i)); - } - - return res; -}; - -// Dictionary wrappers share the same interface (with functions keys() and -// get(k)). -const extractDict = tuple => dict => { - const keys = containerExtractor(dict.keys()); - const res = []; - for (let key of keys) { - // We assume that something that is in keys() is always present in the - // structure as well. - res.push(tuple(key)(dict.get(key))); - } - return res; -}; - -export const getInput = call("input"); -export const getOutput = call("output"); -export const getTransactionHash = call("transaction_id"); -export const getTransactionIndex = call("index"); -export const getAddress = call("address"); -export const getPlutusData = callMaybe("plutus_data"); -export const getScriptRef = callMaybe("script_ref"); - -export function withScriptRef(ccNativeScript) { - return ccPlutusScript => scriptRef => { - if (scriptRef.is_native_script()) { - return ccNativeScript(scriptRef.native_script()); - } else if (scriptRef.is_plutus_script()) { - return ccPlutusScript(scriptRef.plutus_script()); - } else { - throw "Impossible happened: withScriptRef: not a script"; - } - }; -} - -export const getAmount = call("amount"); -export const getCoin = call("coin"); -export const getMultiAsset = callMaybe("multiasset"); -export { extractDict as extractMultiAsset }; -export { extractDict as extractAssets }; -export const getDataHash = callMaybe("data_hash"); - -export function mkTransactionUnspentOutput(input) { - return output => lib.TransactionUnspentOutput.new(input, output); -} diff --git a/src/Internal/Deserialization/UnspentOutput.purs b/src/Internal/Deserialization/UnspentOutput.purs deleted file mode 100644 index 3068600eee..0000000000 --- a/src/Internal/Deserialization/UnspentOutput.purs +++ /dev/null @@ -1,184 +0,0 @@ -module Ctl.Internal.Deserialization.UnspentOutput - ( convertUnspentOutput - , mkTransactionUnspentOutput - , convertInput - , convertOutput - , convertValue - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.ScriptRef - ( ScriptRef(PlutusScriptRef, NativeScriptRef) - ) as T -import Ctl.Internal.Cardano.Types.Transaction - ( TransactionOutput(TransactionOutput) - ) as T -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - ) as T -import Ctl.Internal.Cardano.Types.Value - ( Coin(Coin) - , CurrencySymbol - , Value - , mkCurrencySymbol - , mkNonAdaAsset - , mkValue - ) as T -import Ctl.Internal.Deserialization.NativeScript (convertNativeScript) -import Ctl.Internal.Deserialization.PlutusData (convertPlutusData) -import Ctl.Internal.Deserialization.WitnessSet (convertPlutusScript) -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Ctl.Internal.Serialization (toBytes) -import Ctl.Internal.Serialization.Address (Address) -import Ctl.Internal.Serialization.Hash (ScriptHash, scriptHashToBytes) -import Ctl.Internal.Serialization.Types - ( AssetName - , Assets - , DataHash - , MultiAsset - , NativeScript - , PlutusData - , PlutusScript - , ScriptRef - , TransactionHash - , TransactionInput - , TransactionOutput - , TransactionUnspentOutput - , Value - ) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum (toBigInt) as BigNum -import Ctl.Internal.Types.OutputDatum - ( OutputDatum(NoOutputDatum, OutputDatumHash, OutputDatum) - ) -import Ctl.Internal.Types.TokenName (TokenName, assetNameName, mkTokenName) as T -import Ctl.Internal.Types.Transaction - ( DataHash(DataHash) - , TransactionHash(TransactionHash) - , TransactionInput(TransactionInput) - ) as T -import Data.Bitraversable (bitraverse, ltraverse) -import Data.Map (Map) -import Data.Map as Map -import Data.Maybe (Maybe(Just, Nothing), fromMaybe) -import Data.Newtype (unwrap, wrap) -import Data.Traversable (for, traverse) -import Data.Tuple (Tuple(Tuple)) -import Data.Tuple.Nested (type (/\)) -import Data.UInt (UInt) - -convertUnspentOutput - :: TransactionUnspentOutput -> Maybe T.TransactionUnspentOutput -convertUnspentOutput tuo = do - let - input = convertInput $ getInput tuo - output <- convertOutput $ getOutput tuo - pure $ T.TransactionUnspentOutput { input, output } - -convertInput :: TransactionInput -> T.TransactionInput -convertInput input = do - let - index = getTransactionIndex input - T.TransactionInput - { transactionId: T.TransactionHash $ unwrap $ toBytes $ - getTransactionHash input - , index - } - -convertOutput :: TransactionOutput -> Maybe T.TransactionOutput -convertOutput output = do - amount <- convertValue $ getAmount output - let - address = getAddress output - mbDataHash = - getDataHash maybeFfiHelper output <#> - toBytes >>> unwrap >>> T.DataHash - mbDatum = getPlutusData maybeFfiHelper output - datum <- case mbDatum, mbDataHash of - Just _, Just _ -> Nothing -- impossible, so it's better to fail - Just datumValue, Nothing -> pure $ OutputDatum $ wrap $ - convertPlutusData datumValue - Nothing, Just datumHash -> pure $ OutputDatumHash datumHash - Nothing, Nothing -> pure NoOutputDatum - let - scriptRef = getScriptRef maybeFfiHelper output <#> convertScriptRef - pure $ T.TransactionOutput - { address, amount, datum, scriptRef } - -convertScriptRef :: ScriptRef -> T.ScriptRef -convertScriptRef = withScriptRef - (convertNativeScript >>> T.NativeScriptRef) - (convertPlutusScript >>> T.PlutusScriptRef) - -convertValue :: Value -> Maybe T.Value -convertValue value = do - let coin = BigNum.toBigInt $ getCoin value - -- multiasset is optional - multiasset <- for (getMultiAsset maybeFfiHelper value) \multiasset -> do - let - -- get multiasset stored in `serialization-lib` types - multiasset' = - multiasset - # extractMultiAsset Tuple >>> map (map (extractAssets Tuple)) - :: Array (ScriptHash /\ Array (AssetName /\ BigNum)) - -- convert to domain types, except of BigNum - multiasset'' :: Map T.CurrencySymbol (Map T.TokenName BigNum) <- - multiasset' # - -- convert transporting out Maybes - ( traverse - ( bitraverse - -- scripthash to currency symbol - (scriptHashToBytes >>> unwrap >>> T.mkCurrencySymbol) - -- nested assetname to tokenname - (traverse (ltraverse (T.assetNameName >>> T.mkTokenName))) - ) - >>> - -- convert inner array - (map >>> map >>> map) Map.fromFoldable - >>> - -- convert outer array - map Map.fromFoldable - ) - -- convert BigNum values, possibly failing - pure $ map (map BigNum.toBigInt) multiasset'' - pure - $ T.mkValue (T.Coin coin) - $ T.mkNonAdaAsset (fromMaybe Map.empty multiasset) - -foreign import getInput :: TransactionUnspentOutput -> TransactionInput -foreign import getOutput :: TransactionUnspentOutput -> TransactionOutput -foreign import getTransactionHash :: TransactionInput -> TransactionHash -foreign import getTransactionIndex :: TransactionInput -> UInt -foreign import getAddress :: TransactionOutput -> Address -foreign import getPlutusData - :: MaybeFfiHelper -> TransactionOutput -> Maybe PlutusData - -foreign import getScriptRef - :: MaybeFfiHelper -> TransactionOutput -> Maybe ScriptRef - -foreign import withScriptRef - :: forall (a :: Type) - . (NativeScript -> a) - -> (PlutusScript -> a) - -> ScriptRef - -> a - -foreign import getAmount :: TransactionOutput -> Value -foreign import getCoin :: Value -> BigNum -foreign import getMultiAsset :: MaybeFfiHelper -> Value -> Maybe MultiAsset -foreign import extractMultiAsset - :: (forall (a :: Type) (b :: Type). a -> b -> a /\ b) - -> MultiAsset - -> Array (ScriptHash /\ Assets) - -foreign import extractAssets - :: (forall (a :: Type) (b :: Type). a -> b -> a /\ b) - -> Assets - -> Array (AssetName /\ BigNum) - -foreign import getDataHash - :: MaybeFfiHelper -> TransactionOutput -> Maybe DataHash - -foreign import mkTransactionUnspentOutput - :: TransactionInput -> TransactionOutput -> TransactionUnspentOutput diff --git a/src/Internal/Deserialization/WitnessSet.js b/src/Internal/Deserialization/WitnessSet.js deleted file mode 100644 index ea8b41a80d..0000000000 --- a/src/Internal/Deserialization/WitnessSet.js +++ /dev/null @@ -1,56 +0,0 @@ -const call = property => object => object[property](); - -const callMaybe = property => maybe => object => { - const res = object[property](); - return res != null ? maybe.just(res) : maybe.nothing; -}; - -// Classes like TransactionInputs are just monomorphic containers with `len` -// and `get()` methods. This function abstracts away converting them to Array -// of something. -const containerExtractor = obj => { - const res = []; - - for (let i = 0; i < obj.len(); i++) { - res.push(obj.get(i)); - } - - return res; -}; - -export const getVkeywitnesses = callMaybe("vkeys"); -export { containerExtractor as extractWitnesses }; -export const getVkey = call("vkey"); -export const getSignature = call("signature"); -export const vkeyPublicKey = call("public_key"); -export const publicKeyToBech32 = call("to_bech32"); -export const signatureToBech32 = call("to_bech32"); -export const getNativeScripts = callMaybe("native_scripts"); -export { containerExtractor as extractNativeScripts }; - -export function nativeScriptAs(maybe) { - return prop => res => ns => - ns[prop]() == null ? maybe.nothing : maybe.just(res); -} - -export const getBootstraps = callMaybe("bootstraps"); -export { containerExtractor as extractBootstraps }; -export const getBootstrapVkey = call("vkey"); -export const getBootstrapSignature = call("signature"); -export const getBootstrapChainCode = call("chain_code"); -export const getBootstrapAttributes = call("attributes"); -export const getPlutusScripts = callMaybe("plutus_scripts"); -export { containerExtractor as extractPlutusScripts }; -export const plutusScriptBytes = call("bytes"); -export const plutusScriptVersion = call("language_version"); -export const getWitnessSetPlutusData = callMaybe("plutus_data"); -export { containerExtractor as extractPlutusData }; -export const getRedeemers = callMaybe("redeemers"); -export const getRedeemerTag = call("tag"); -export const getRedeemerIndex = call("index"); -export { containerExtractor as extractRedeemers }; -export const getRedeemerTagKind = call("kind"); -export const getRedeemerPlutusData = call("data"); -export const getExUnits = call("ex_units"); -export const getExUnitsMem = call("mem"); -export const getExUnitsSteps = call("steps"); diff --git a/src/Internal/Deserialization/WitnessSet.purs b/src/Internal/Deserialization/WitnessSet.purs deleted file mode 100644 index f4783aa407..0000000000 --- a/src/Internal/Deserialization/WitnessSet.purs +++ /dev/null @@ -1,202 +0,0 @@ -module Ctl.Internal.Deserialization.WitnessSet - ( convertNativeScripts - , convertPlutusScripts - , convertPlutusScript - , convertVkeyWitnesses - , convertVkeyWitness - , convertWitnessSet - , plutusScriptBytes - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.NativeScript (NativeScript) as T -import Ctl.Internal.Cardano.Types.Transaction - ( BootstrapWitness - , ExUnits - , Redeemer(Redeemer) - , TransactionWitnessSet(TransactionWitnessSet) - , Vkey(Vkey) - , Vkeywitness(Vkeywitness) - , mkFromCslEd25519Signature - , mkFromCslPubKey - ) as T -import Ctl.Internal.Deserialization.Language (convertLanguage) -import Ctl.Internal.Deserialization.NativeScript (convertNativeScript) -import Ctl.Internal.Deserialization.PlutusData (convertPlutusData) -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Ctl.Internal.Serialization.Types - ( BootstrapWitness - , BootstrapWitnesses - , Ed25519Signature - , ExUnits - , Language - , NativeScript - , NativeScripts - , PlutusData - , PlutusList - , PlutusScript - , PlutusScripts - , PublicKey - , Redeemer - , RedeemerTag - , Redeemers - , TransactionWitnessSet - , Vkey - , Vkeywitness - , Vkeywitnesses - ) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum (toBigInt) as BigNum -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.PlutusData (PlutusData) as T -import Ctl.Internal.Types.RedeemerTag as Tag -import Ctl.Internal.Types.Scripts (PlutusScript(PlutusScript)) as S -import Data.Maybe (Maybe) -import Data.Tuple (curry) -import Data.Tuple.Nested ((/\)) -import Effect.Exception (throw) -import Effect.Unsafe (unsafePerformEffect) - -convertWitnessSet :: TransactionWitnessSet -> T.TransactionWitnessSet -convertWitnessSet ws = - let - vkeys = getVkeywitnesses maybeFfiHelper ws <#> convertVkeyWitnesses - nativeScripts = getNativeScripts maybeFfiHelper ws <#> convertNativeScripts - bootstraps = getBootstraps maybeFfiHelper ws <#> convertBootstraps - plutusScripts = getPlutusScripts maybeFfiHelper ws <#> convertPlutusScripts - plutusData = getWitnessSetPlutusData maybeFfiHelper ws <#> convertPlutusList - redeemers = getRedeemers maybeFfiHelper ws <#> convertRedeemers - in - T.TransactionWitnessSet - { vkeys - , nativeScripts - , bootstraps - , plutusScripts - , plutusData - , redeemers - } - -convertVkeyWitnesses :: Vkeywitnesses -> Array T.Vkeywitness -convertVkeyWitnesses = extractWitnesses >>> map convertVkeyWitness - -convertVkeyWitness :: Vkeywitness -> T.Vkeywitness -convertVkeyWitness witness = - let - vkey = getVkey witness - publicKey = convertVkey vkey - signature = T.mkFromCslEd25519Signature $ getSignature witness - in - T.Vkeywitness $ publicKey /\ signature - -convertVkey :: Vkey -> T.Vkey -convertVkey = T.Vkey <<< T.mkFromCslPubKey <<< vkeyPublicKey - -convertNativeScripts :: NativeScripts -> Array T.NativeScript -convertNativeScripts nativeScripts = - extractNativeScripts nativeScripts <#> convertNativeScript - -convertBootstraps :: BootstrapWitnesses -> Array T.BootstrapWitness -convertBootstraps = extractBootstraps >>> map \bootstrap -> - { vkey: convertVkey $ getBootstrapVkey bootstrap - , signature: T.mkFromCslEd25519Signature $ getBootstrapSignature bootstrap - , chainCode: getBootstrapChainCode bootstrap - , attributes: getBootstrapAttributes bootstrap - } - -convertPlutusScripts :: PlutusScripts -> Array S.PlutusScript -convertPlutusScripts plutusScripts = - extractPlutusScripts plutusScripts <#> convertPlutusScript - -convertPlutusScript :: PlutusScript -> S.PlutusScript -convertPlutusScript plutusScript = do - let - language = convertLanguage $ plutusScriptVersion plutusScript - curry S.PlutusScript (plutusScriptBytes plutusScript) language - -convertPlutusList :: PlutusList -> Array T.PlutusData -convertPlutusList = extractPlutusData >>> map convertPlutusData - -convertRedeemers :: Redeemers -> Array T.Redeemer -convertRedeemers = extractRedeemers >>> map convertRedeemer - -convertRedeemer :: Redeemer -> T.Redeemer -convertRedeemer redeemer = - let - tag = convertRedeemerTag $ getRedeemerTag redeemer - index = BigNum.toBigInt $ getRedeemerIndex redeemer - exUnits = convertExUnits $ getExUnits redeemer - data_ = convertPlutusData $ getRedeemerPlutusData redeemer - in - T.Redeemer - { tag - , index - , data: data_ - , exUnits - } - -convertRedeemerTag :: RedeemerTag -> Tag.RedeemerTag -convertRedeemerTag tag = case getRedeemerTagKind tag of - 0 -> Tag.Spend - 1 -> Tag.Mint - 2 -> Tag.Cert - 3 -> Tag.Reward - _ -> unsafePerformEffect $ throw "convertRedeemerTag: impossible happened" - -convertExUnits :: ExUnits -> T.ExUnits -convertExUnits eu = - let - mem = BigNum.toBigInt $ getExUnitsMem eu - steps = BigNum.toBigInt $ getExUnitsSteps eu - in - { mem, steps } - -foreign import getVkeywitnesses - :: MaybeFfiHelper -> TransactionWitnessSet -> Maybe Vkeywitnesses - -foreign import extractWitnesses :: Vkeywitnesses -> Array Vkeywitness -foreign import getVkey :: Vkeywitness -> Vkey -foreign import getSignature :: Vkeywitness -> Ed25519Signature -foreign import vkeyPublicKey :: Vkey -> PublicKey -foreign import publicKeyToBech32 :: PublicKey -> String -foreign import signatureToBech32 :: Ed25519Signature -> String -foreign import getNativeScripts - :: MaybeFfiHelper -> TransactionWitnessSet -> Maybe NativeScripts - -foreign import extractNativeScripts :: NativeScripts -> Array NativeScript -foreign import nativeScriptAs - :: MaybeFfiHelper - -> String - -> T.NativeScript - -> NativeScript - -> Maybe T.NativeScript - -foreign import getBootstraps - :: MaybeFfiHelper -> TransactionWitnessSet -> Maybe BootstrapWitnesses - -foreign import extractBootstraps :: BootstrapWitnesses -> Array BootstrapWitness -foreign import getBootstrapVkey :: BootstrapWitness -> Vkey -foreign import getBootstrapSignature :: BootstrapWitness -> Ed25519Signature -foreign import getBootstrapChainCode :: BootstrapWitness -> ByteArray -foreign import getBootstrapAttributes :: BootstrapWitness -> ByteArray -foreign import getPlutusScripts - :: MaybeFfiHelper -> TransactionWitnessSet -> Maybe PlutusScripts - -foreign import extractPlutusScripts :: PlutusScripts -> Array PlutusScript -foreign import plutusScriptBytes :: PlutusScript -> ByteArray -foreign import plutusScriptVersion :: PlutusScript -> Language -foreign import getWitnessSetPlutusData - :: MaybeFfiHelper -> TransactionWitnessSet -> Maybe PlutusList - -foreign import extractPlutusData :: PlutusList -> Array PlutusData -foreign import getRedeemers - :: MaybeFfiHelper -> TransactionWitnessSet -> Maybe Redeemers - -foreign import extractRedeemers :: Redeemers -> Array Redeemer -foreign import getRedeemerTag :: Redeemer -> RedeemerTag -foreign import getRedeemerTagKind :: RedeemerTag -> Int -foreign import getRedeemerIndex :: Redeemer -> BigNum -foreign import getRedeemerPlutusData :: Redeemer -> PlutusData -foreign import getExUnits :: Redeemer -> ExUnits -foreign import getExUnitsMem :: ExUnits -> BigNum -foreign import getExUnitsSteps :: ExUnits -> BigNum diff --git a/src/Internal/Equipartition.purs b/src/Internal/Equipartition.purs deleted file mode 100644 index f78c0c389d..0000000000 --- a/src/Internal/Equipartition.purs +++ /dev/null @@ -1,38 +0,0 @@ -module Ctl.Internal.Equipartition - ( class Equipartition - , equipartition - ) where - -import Prelude - -import Data.Array (replicate) -import Data.Array.NonEmpty (NonEmptyArray) -import Data.Array.NonEmpty (appendArray, replicate, singleton) as NEArray -import Data.Maybe (fromJust) -import JS.BigInt (BigInt) -import JS.BigInt (fromInt, toInt) as BigInt -import Partial.Unsafe (unsafePartial) - --- | Represents types whose values can be equally divided into several parts. -class Equipartition a where - equipartition :: a -> Int -> NonEmptyArray a - --- | Computes the equipartition of a `BigInt` into `numParts` smaller `BigInt`s --- | whose values differ by no more than 1. The resultant array is sorted in --- | ascending order. --- | Taken from cardano-wallet: --- | https://github.com/input-output-hk/cardano-wallet/blob/d4b30de073f2b5eddb25bf12c2453abb42e8b352/lib/numeric/src/Cardano/Numeric/Util.hs#L127 -instance Equipartition BigInt where - equipartition bi numParts - | numParts <= one = - NEArray.singleton bi - | otherwise = - let - quot = bi / BigInt.fromInt numParts - rem = toIntUnsafe (bi `mod` BigInt.fromInt numParts) - in - NEArray.replicate (numParts - rem) quot - `NEArray.appendArray` replicate rem (quot + one) - where - toIntUnsafe :: BigInt -> Int - toIntUnsafe = unsafePartial fromJust <<< BigInt.toInt diff --git a/src/Internal/FfiHelpers.js b/src/Internal/FfiHelpers.js index dadcaab78d..bff66f8baa 100644 --- a/src/Internal/FfiHelpers.js +++ b/src/Internal/FfiHelpers.js @@ -44,3 +44,11 @@ export function _containerHelper(r) { } }; } + +export const _partialToMaybe = f => nothing => just => { + try { + return just(f()); + } catch (_) { + return nothing; + } +}; diff --git a/src/Internal/FfiHelpers.purs b/src/Internal/FfiHelpers.purs index 9fdddaadc9..357b954449 100644 --- a/src/Internal/FfiHelpers.purs +++ b/src/Internal/FfiHelpers.purs @@ -5,6 +5,7 @@ module Ctl.Internal.FfiHelpers , containerHelper , ErrorFfiHelper , errorHelper + , partialToMaybe ) where import Ctl.Internal.Error (E) @@ -13,6 +14,8 @@ import Data.Function ((<<<), (>>>)) import Data.Maybe (Maybe(Just, Nothing), fromMaybe) import Data.Tuple (Tuple(Tuple)) import Data.Variant (Variant) +import Partial.Unsafe (unsafePartial) +import Prelude (Unit) type MaybeFfiHelper = { nothing :: forall (x :: Type). Maybe x @@ -46,3 +49,13 @@ containerHelper = _containerHelper { untuple, tuple: Tuple } untuple :: forall a. Tuple a a -> Array a untuple (Tuple a b) = [ a, b ] + +partialToMaybe :: forall a. (Unit -> Partial => a) -> Maybe a +partialToMaybe f = _partialToMaybe (\x -> unsafePartial (f x)) Nothing Just + +foreign import _partialToMaybe + :: forall a + . (Unit -> a) + -> (forall x. Maybe x) + -> (forall x. x -> Maybe x) + -> Maybe a diff --git a/src/Internal/FromData.purs b/src/Internal/FromData.purs deleted file mode 100644 index fa4d284e29..0000000000 --- a/src/Internal/FromData.purs +++ /dev/null @@ -1,375 +0,0 @@ -module Ctl.Internal.FromData - ( FromDataError - ( ArgsWantedButGot - , FromDataFailed - , BigNumToIntFailed - , IndexWantedButGot - , WantedConstrGot - ) - , class FromData - , class FromDataArgs - , class FromDataArgsRL - , class FromDataWithSchema - , fromData - , fromDataArgs - , fromDataArgsRec - , fromDataWithSchema - , genericFromData - ) where - -import Prelude - -import Contract.Crypto.Secp256k1 (Secp256k1PrivateKey) -import Contract.Crypto.Secp256k1.ECDSA (ECDSAPublicKey) -import Control.Alternative ((<|>)) -import Ctl.Internal.Helpers (bigIntToUInt) -import Ctl.Internal.Plutus.Types.DataSchema - ( class HasPlutusSchema - , class ValidPlutusSchema - ) -import Ctl.Internal.TypeLevel.Nat (class KnownNat, natVal) -import Ctl.Internal.TypeLevel.RowList.Unordered.Indexed - ( class GetIndexWithLabel - , class GetWithLabel - ) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum as BigNum -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes) -import Ctl.Internal.Types.PlutusData (PlutusData(Bytes, Constr, List, Integer)) -import Ctl.Internal.Types.RawBytes (RawBytes) -import Data.Array (uncons) -import Data.Array as Array -import Data.ArrayBuffer.Types (Uint8Array) -import Data.Either (Either(Left, Right), hush, note) -import Data.Generic.Rep as G -import Data.List (List) -import Data.Maybe (Maybe(Nothing, Just), maybe) -import Data.Newtype (unwrap, wrap) -import Data.NonEmpty (NonEmpty(NonEmpty)) -import Data.Ratio (Ratio, reduce) -import Data.Show.Generic (genericShow) -import Data.Symbol (class IsSymbol, reflectSymbol) -import Data.TextDecoder (decodeUtf8) -import Data.Traversable (traverse) -import Data.Tuple (Tuple(Tuple)) -import Data.UInt (UInt) -import Data.Unfoldable (class Unfoldable) -import JS.BigInt (BigInt) -import Noble.Secp256k1.ECDSA - ( ECDSASignature - , MessageHash - , mkECDSAPublicKey - , mkMessageHash - , mkPrivateKey - ) -import Noble.Secp256k1.Schnorr - ( SchnorrPublicKey - , SchnorrSignature - , mkSchnorrPublicKey - ) -import Prim.Row as Row -import Prim.RowList as RL -import Prim.TypeError (class Fail, Text) -import Record as Record -import Type.Proxy (Proxy(Proxy)) - --- | Errors -data FromDataError - = ArgsWantedButGot String Int (Array PlutusData) - | FromDataFailed String PlutusData - | BigNumToIntFailed String BigNum - | IndexWantedButGot String Int Int - | WantedConstrGot String PlutusData - -derive instance G.Generic FromDataError _ - -instance Show FromDataError where - show = genericShow - -noteB :: forall (a :: Type). a -> Boolean -> Either a Unit -noteB _ true = pure unit -noteB n false = Left n - --- | Classes - -class FromData :: Type -> Constraint -class FromData a where - fromData :: PlutusData -> Maybe a - --- | Replacement for 'FromDataWithIndex'. This converts a type into its Plutus Data representation with the help of a Plutus Data Schema (see TypeLevel.DataSchema) --- | We cannot require that the first type argument 't' is an instance of 'HasPlutusSchema' but in practice instances of this class must have a 't' with a --- | 'HasPlutusSchema' instance as well. -class FromDataWithSchema :: Type -> Type -> Constraint -class FromDataWithSchema t a where - fromDataWithSchema - :: Proxy t -> Proxy a -> PlutusData -> Either FromDataError a - --- NOTE: Using the 'parser' approach as in https://github.com/purescript-contrib/purescript-argonaut-generic/blob/3ae9622814fd3f3f06fa8e5e58fd58d2ef256b91/src/Data/Argonaut/Decode/Generic.purs -class FromDataArgs :: Type -> Symbol -> Type -> Constraint -class FromDataArgs t c a where - fromDataArgs - :: IsSymbol c - => Proxy t - -> Proxy c - -> Array PlutusData - -> Either FromDataError { head :: a, tail :: Array PlutusData } - --- | A helper typeclass to implement `FromDataArgs` for records. --- | Adapted from https://github.com/purescript/purescript-quickcheck/blob/v7.1.0/src/Test/QuickCheck/Arbitrary.purs#L247 --- | --- | The second argument is a symbol which represents the name of a record constructor. --- | --- | The third argument to the class is a RowList. - -class FromDataArgsRL - :: Type -> Symbol -> RL.RowList Type -> Row Type -> Constraint -class FromDataArgsRL t constr list row | t constr list -> row where - fromDataArgsRec - :: forall (rlproxy :: RL.RowList Type -> Type) - . IsSymbol constr - => Proxy t - -> Proxy constr - -> rlproxy list - -> Array PlutusData - -> Either FromDataError { head :: Record row, tail :: Array PlutusData } - --- | FromDataWithSchema instances for Data.Generic.Rep --- | See https://purescript-simple-json.readthedocs.io/en/latest/generics-rep.html - -instance - ( FromDataWithSchema t l - , FromDataWithSchema t r - ) => - FromDataWithSchema t (G.Sum l r) where - fromDataWithSchema _ _ pd = - G.Inl <$> fromDataWithSchema (Proxy :: Proxy t) (Proxy :: Proxy l) pd - <|> G.Inr <$> fromDataWithSchema (Proxy :: Proxy t) (Proxy :: Proxy r) pd - -else instance - ( IsSymbol constr - , HasPlutusSchema t schema - , ValidPlutusSchema schema rList - , GetIndexWithLabel constr rList ix - , FromDataArgs t constr args - , KnownNat ix - ) => - FromDataWithSchema t (G.Constructor constr args) where - fromDataWithSchema _ _ (Constr i pdArgs) = do - let constrName = reflectSymbol (Proxy :: Proxy constr) - gotIx <- note (BigNumToIntFailed constrName i) (BigNum.toInt i) - wantedIx <- pure $ natVal (Proxy :: Proxy ix) - noteB (IndexWantedButGot constrName wantedIx gotIx) (wantedIx == gotIx) - { head: repArgs, tail: pdArgs' } <- fromDataArgs (Proxy :: Proxy t) - (Proxy :: Proxy constr) - pdArgs - noteB (ArgsWantedButGot constrName 0 pdArgs') (pdArgs' == []) - pure $ G.Constructor repArgs - fromDataWithSchema _ _ pd = Left $ WantedConstrGot - (reflectSymbol (Proxy :: Proxy constr)) - pd -else instance - ( FromDataWithSchema t a - ) => - FromDataWithSchema t (G.Argument a) where - fromDataWithSchema _ _ pd = G.Argument <$> fromDataWithSchema - (Proxy :: Proxy t) - (Proxy :: Proxy a) - pd - --- | FromDataArgs instance for Data.Generic.Rep -instance FromDataArgs t c (G.NoArguments) where - fromDataArgs _ _ [] = Right { head: G.NoArguments, tail: [] } - fromDataArgs _ c pdArgs = Left $ ArgsWantedButGot (reflectSymbol c) 0 pdArgs - -instance - ( FromDataArgsRL t constr rList row - , HasPlutusSchema t schema - , ValidPlutusSchema schema rrList - , GetWithLabel constr rrList rList - ) => - FromDataArgs t constr (G.Argument (Record row)) where - fromDataArgs _ _ pdArgs = do - { head, tail } <- fromDataArgsRec (Proxy :: Proxy t) (Proxy :: Proxy constr) - (Proxy :: Proxy rList) - pdArgs - pure { head: G.Argument head, tail } -else instance (FromData a) => FromDataArgs t constr (G.Argument a) where - fromDataArgs _ _ pdArgs = do - let constrName = reflectSymbol (Proxy :: Proxy constr) - { head: pd, tail: pds } <- note (ArgsWantedButGot constrName 1 pdArgs) $ - uncons pdArgs - repArg <- note (FromDataFailed constrName pd) $ fromData pd - pure { head: G.Argument repArg, tail: pds } - -instance - ( FromDataArgs t c a - , FromDataArgs t c b - ) => - FromDataArgs t c (G.Product a b) where - fromDataArgs _ _ pdArgs = do - { head: repFst, tail: pdArgs' } <- fromDataArgs (Proxy :: Proxy t) - (Proxy :: Proxy c) - pdArgs - { head: repSnd, tail: pdArgs'' } <- fromDataArgs (Proxy :: Proxy t) - (Proxy :: Proxy c) - pdArgs' - pure { head: G.Product repFst repSnd, tail: pdArgs'' } - --- | FromDataArgsRL instances - -instance FromDataArgsRL t constr RL.Nil () where - fromDataArgsRec _ _ _ [] = Right { head: {}, tail: [] } - fromDataArgsRec _ c _ pdArgs = Left $ ArgsWantedButGot (reflectSymbol c) 0 - pdArgs - -instance - ( FromData a - , FromDataArgsRL t constr rListRest rowRest - , Row.Lacks key rowRest - , Row.Cons key a rowRest rowFull - , IsSymbol key - ) => - FromDataArgsRL t constr (RL.Cons key a rListRest) rowFull where - fromDataArgsRec _ c _ pdArgs = do - let keyProxy = Proxy :: Proxy key - { head: pdArg, tail: pdArgs' } <- - note (ArgsWantedButGot (reflectSymbol c) 1 pdArgs) $ uncons - pdArgs - field <- note (FromDataFailed (reflectSymbol c) pdArg) $ fromData pdArg - { head: rec, tail: pdArgs'' } <- fromDataArgsRec (Proxy :: Proxy t) - (Proxy :: Proxy constr) - (Proxy :: Proxy rListRest) - pdArgs' - pure $ - { head: (Record.insert keyProxy field rec) - , tail: pdArgs'' - } - --- TODO: Unhush the errors in FromData -genericFromData - :: forall (t :: Type) (rep :: Type) - . G.Generic t rep - => FromDataWithSchema t rep - => PlutusData - -> Maybe t -genericFromData pd = G.to <$> hush - (fromDataWithSchema (Proxy :: Proxy t) (Proxy :: Proxy rep) pd) - --- | Base FromData instances - -instance FromData Void where - fromData _ = Nothing - -instance FromData Unit where - fromData (Constr n []) - | n == BigNum.zero = Just unit - fromData _ = Nothing - --- NOTE: For the sake of compatibility the following fromDatas have to match --- https://github.com/input-output-hk/plutus/blob/1f31e640e8a258185db01fa899da63f9018c0e85/plutus-tx/src/PlutusTx/IsData/Instances.hs -instance FromData Boolean where - fromData (Constr n []) - | n == BigNum.zero = Just false - | n == BigNum.one = Just true - fromData _ = Nothing - -instance FromData a => FromData (Maybe a) where - fromData (Constr n [ pd ]) - | n == BigNum.zero = maybe Nothing (Just <<< Just) (fromData pd) -- Just is zero-indexed by Plutus - fromData (Constr n []) - | n == BigNum.one = Just Nothing - fromData _ = Nothing - -instance (FromData a, FromData b) => FromData (Either a b) where - fromData (Constr n [ pd ]) - | n == BigNum.zero = maybe Nothing (Just <<< Left) (fromData pd) - | n == BigNum.one = maybe Nothing (Just <<< Right) (fromData pd) - fromData _ = Nothing - -instance Fail (Text "Int is not supported, use BigInt instead") => FromData Int where - fromData _ = Nothing - -instance FromData BigInt where - fromData (Integer n) = Just n - fromData _ = Nothing - -instance FromData BigNum where - fromData (Integer n) = BigNum.fromBigInt n - fromData _ = Nothing - -instance FromData UInt where - fromData (Integer n) = bigIntToUInt n - fromData _ = Nothing - -instance FromData a => FromData (Array a) where - fromData = fromDataUnfoldable - -instance FromData a => FromData (NonEmpty Array a) where - fromData d = do - { head, tail } <- Array.uncons =<< fromData d - pure $ NonEmpty head tail - -instance FromData a => FromData (List a) where - fromData = fromDataUnfoldable - -instance (FromData a, FromData b) => FromData (Tuple a b) where - fromData (Constr n [ a, b ]) - | n == BigNum.zero = Tuple <$> fromData a <*> fromData b - fromData _ = Nothing - -instance FromData ByteArray where - fromData (Bytes res) = Just res - fromData _ = Nothing - -instance FromData CborBytes where - fromData = map wrap <<< fromData - -instance FromData RawBytes where - fromData = map wrap <<< fromData - -instance FromData String where - fromData (Bytes bytes) = hush $ decodeUtf8 $ unwrap bytes - fromData _ = Nothing - --- Nothing prevents fromData b ~ Maybe BigInt from being zero here, perhaps --- we want more safety: -instance (Ord a, EuclideanRing a, FromData a) => FromData (Ratio a) where - fromData (List [ a, b ]) = reduce <$> fromData a <*> fromData b - fromData _ = Nothing - -instance FromData PlutusData where - fromData = Just - -instance FromData Uint8Array where - fromData x = (fromData x :: Maybe ByteArray) <#> unwrap - --- Instances for purescript-noble-secp256k1 types - -instance FromData Secp256k1PrivateKey where - fromData = map wrap <<< mkPrivateKey <=< fromData - -instance FromData MessageHash where - fromData = mkMessageHash <=< fromData - -instance FromData ECDSAPublicKey where - fromData = mkECDSAPublicKey <=< fromData - -instance FromData ECDSASignature where - fromData = map wrap <<< fromData - -instance FromData SchnorrPublicKey where - fromData = mkSchnorrPublicKey <=< fromData - -instance FromData SchnorrSignature where - fromData = map wrap <<< fromData - -fromDataUnfoldable - :: forall (a :: Type) (t :: Type -> Type) - . Unfoldable t - => FromData a - => PlutusData - -> Maybe (t a) -fromDataUnfoldable (List entries) = Array.toUnfoldable <$> traverse fromData - entries -fromDataUnfoldable _ = Nothing diff --git a/src/Internal/Hashing.purs b/src/Internal/Hashing.purs deleted file mode 100644 index 2d75443a1d..0000000000 --- a/src/Internal/Hashing.purs +++ /dev/null @@ -1,90 +0,0 @@ -module Ctl.Internal.Hashing - ( blake2b224Hash - , blake2b224HashHex - , blake2b256Hash - , blake2b256HashHex - , datumHash - , hashPlutusData - , md5HashHex - , plutusScriptHash - , scriptRefHash - , sha256Hash - , sha256HashHex - , sha3_256Hash - , sha3_256HashHex - , transactionHash - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.ScriptRef - ( ScriptRef(NativeScriptRef, PlutusScriptRef) - ) -import Ctl.Internal.Deserialization.Transaction (_txBody) -import Ctl.Internal.Serialization (toBytes) -import Ctl.Internal.Serialization.Hash (ScriptHash, nativeScriptHash) -import Ctl.Internal.Serialization.NativeScript (convertNativeScript) -import Ctl.Internal.Serialization.PlutusData (convertPlutusData) -import Ctl.Internal.Serialization.PlutusScript (convertPlutusScript) -import Ctl.Internal.Serialization.Types - ( DataHash - , PlutusData - , PlutusScript - , Transaction - ) as Serialization -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.Datum (Datum) -import Ctl.Internal.Types.Scripts (PlutusScript) -import Ctl.Internal.Types.Transaction (DataHash, TransactionHash) -import Data.Newtype (unwrap, wrap) -import Effect (Effect) -import Node.Buffer (fromString, toString) as Buffer -import Node.Crypto.Hash (createHash, digest, update) as Hash -import Node.Encoding (Encoding(Hex, UTF8)) - -foreign import blake2b224Hash :: ByteArray -> ByteArray - -foreign import blake2b224HashHex :: ByteArray -> String - -foreign import blake2b256Hash :: ByteArray -> ByteArray - -foreign import blake2b256HashHex :: ByteArray -> String - -foreign import hashPlutusData - :: Serialization.PlutusData -> Serialization.DataHash - -foreign import hashPlutusScript :: Serialization.PlutusScript -> ScriptHash - -foreign import sha256Hash :: ByteArray -> ByteArray - -foreign import sha256HashHex :: ByteArray -> String - -foreign import sha3_256Hash :: ByteArray -> ByteArray - -foreign import sha3_256HashHex :: ByteArray -> String - -md5HashHex :: String -> Effect String -md5HashHex contents = do - buf <- Buffer.fromString contents UTF8 - digest <- Hash.createHash "md5" >>= Hash.update buf >>= Hash.digest - Buffer.toString Hex digest - -datumHash :: Datum -> DataHash -datumHash = - wrap <<< unwrap <<< toBytes <<< hashPlutusData - <<< convertPlutusData - <<< unwrap - --- | Calculates the hash of the transaction by applying `blake2b256Hash` to --- | the cbor-encoded transaction body. -transactionHash :: Serialization.Transaction -> TransactionHash -transactionHash = - wrap <<< blake2b256Hash <<< unwrap <<< toBytes <<< _txBody - -plutusScriptHash :: PlutusScript -> ScriptHash -plutusScriptHash = hashPlutusScript <<< convertPlutusScript - -scriptRefHash :: ScriptRef -> ScriptHash -scriptRefHash (PlutusScriptRef plutusScript) = plutusScriptHash plutusScript -scriptRefHash (NativeScriptRef nativeScript) = - nativeScriptHash $ convertNativeScript nativeScript diff --git a/src/Internal/Helpers.purs b/src/Internal/Helpers.purs index 6b73836555..2c6b907fac 100644 --- a/src/Internal/Helpers.purs +++ b/src/Internal/Helpers.purs @@ -11,7 +11,6 @@ module Ctl.Internal.Helpers , bigIntToUInt , bugTrackerLink , concatPaths - , contentsProp , encodeMap , encodeTagged , encodeTagged' @@ -28,22 +27,46 @@ module Ctl.Internal.Helpers , logWithLevel , maybeArrayMerge , mkErrorRecord - , notImplemented , showWithParens - , tagProp , uIntToBigInt , pprintTagSet + , eqOrd + , showFromBytes + , showFromCbor + , compareViaCslBytes + , decodeMap + , decodeTaggedNewtype + , unsafeFromJust ) where import Prelude -import Aeson (class EncodeAeson, Aeson, encodeAeson, toString) -import Control.Monad.Error.Class (class MonadError, throwError) +import Aeson + ( class DecodeAeson + , class DecodeTupleAux + , class EncodeAeson + , Aeson + , JsonDecodeError(TypeMismatch) + , caseAesonObject + , decodeAeson + , encodeAeson + , getField + , toString + ) +import Cardano.Serialization.Lib (class IsBytes, toBytes) +import Cardano.Serialization.Lib.Internal (class IsCsl) +import Control.Alt ((<|>)) +import Control.Monad.Error.Class + ( class MonadError + , class MonadThrow + , throwError + ) import Ctl.Internal.Helpers.Formatter (showTags) import Data.Array (union) import Data.Bifunctor (bimap) import Data.Bitraversable (ltraverse) -import Data.Either (Either(Right), either) +import Data.ByteArray (byteArrayToHex) +import Data.Either (Either(Left, Right), either) import Data.Function (on) import Data.JSDate (now) import Data.List.Lazy as LL @@ -57,21 +80,21 @@ import Data.Maybe (Maybe(Just, Nothing), fromJust, fromMaybe, maybe) import Data.Maybe.First (First(First)) import Data.Maybe.Last (Last(Last)) import Data.String (Pattern(Pattern), null, stripPrefix, stripSuffix) -import Data.Traversable (traverse) +import Data.Traversable (for, traverse) import Data.Tuple (snd, uncurry) import Data.Tuple.Nested (type (/\), (/\)) -import Data.Typelevel.Undefined (undefined) import Data.UInt (UInt) import Data.UInt as UInt import Effect (Effect) import Effect.Class (class MonadEffect) import Effect.Class.Console (log) import Effect.Exception (throw) +import Effect.Unsafe (unsafePerformEffect) +import Foreign.Object (Object) import Foreign.Object as Obj import JS.BigInt (BigInt) import JS.BigInt as BigInt import Partial.Unsafe (unsafePartial) -import Prim.TypeError (class Warn, Text) bugTrackerLink :: String bugTrackerLink = @@ -89,7 +112,7 @@ fromJustEff e = case _ of liftEither :: forall (a :: Type) (e :: Type) (m :: Type -> Type) - . MonadError e m + . MonadThrow e m => Either e a -> m a liftEither = either throwError pure @@ -109,7 +132,7 @@ liftedM err mma = mma >>= maybe (throwError err) Right >>> liftEither -- | Given an error and a `Maybe` value, lift the context via `liftEither`. liftM :: forall (e :: Type) (m :: Type -> Type) (a :: Type) - . MonadError e m + . MonadThrow e m => e -> Maybe a -> m a @@ -207,9 +230,6 @@ uIntToBigInt = unsafePartial fromJust <<< BigInt.fromString <<< UInt.toString bigIntToUInt :: BigInt -> Maybe UInt bigIntToUInt = UInt.fromString <<< BigInt.toString -notImplemented :: forall a. Warn (Text "Function not implemented!") => a -notImplemented = undefined - -- | Log a message by printing it to the console, depending on the provided -- | `LogLevel` logWithLevel @@ -264,19 +284,45 @@ encodeMap m = pairs :: Array (Aeson /\ Aeson) pairs = map (bimap encodeAeson encodeAeson) $ toUnfoldable m -tagProp :: String -tagProp = "tag" - -contentsProp :: String -contentsProp = "contents" +-- TODO: test with encodeMap +decodeMap + :: forall (k :: Type) (v :: Type) + . DecodeAeson k + => Ord k + => DecodeAeson v + => DecodeTupleAux (k /\ v) + => Aeson + -> Either JsonDecodeError (Map k v) +decodeMap aeson = do + decodeAsArray <|> decodeAsObject + where + decodeAsObject = do + props <- (decodeAeson aeson :: Either _ (Object v)) + Map.fromFoldable <$> for (Obj.toUnfoldable props :: Array (String /\ v)) + \(kString /\ v) -> do + k <- decodeAeson (encodeAeson kString) + pure $ k /\ v + decodeAsArray = do + Map.fromFoldable <$> (decodeAeson aeson :: Either _ (Array (k /\ v))) + +decodeTaggedNewtype + :: ∀ (a :: Type) (b :: Type) + . DecodeAeson a + => String + -> (a -> b) + -> Aeson + -> Either JsonDecodeError b +decodeTaggedNewtype constrName constr = caseAesonObject + (Left $ TypeMismatch "Expected object") + (flip getField constrName >=> decodeAeson >>> map constr) -- | Args: tag value encoder -- | Encodes `value` using `encoder` as `{ "tag": *encoded tag*, "contents": *encoded value* }` encodeTagged :: forall a. String -> a -> (a -> Aeson) -> Aeson encodeTagged tag a encoder = encodeAeson $ Obj.fromFoldable - [ tagProp /\ encodeAeson tag - , contentsProp /\ encoder a + [ "tag" /\ encodeAeson tag + , "contents" /\ encoder a ] -- | A wrapper around `encodeTagged` function that uses @@ -301,3 +347,40 @@ fromMaybeFlipped :: forall (a :: Type). Maybe a -> a -> a fromMaybeFlipped = flip fromMaybe infixl 5 fromMaybeFlipped as ?? + +eqOrd :: forall a. Ord a => a -> a -> Boolean +eqOrd a b = compare a b == EQ + +compareViaCslBytes + :: forall a b + . IsCsl a + => IsBytes a + => IsCsl b + => IsBytes b + => a + -> b + -> Ordering +compareViaCslBytes a b = + compare (byteArrayToHex $ toBytes a) (byteArrayToHex $ toBytes b) + +showFromBytes :: forall a. IsCsl a => IsBytes a => String -> a -> String +showFromBytes typeName a = "(" <> typeName + <> " $ unsafePartial $ fromJust $ fromBytes " + <> show (toBytes a) + <> ")" + +showFromCbor :: forall a. IsCsl a => IsBytes a => String -> a -> String +showFromCbor typeName a = "(" <> typeName + <> " $ unsafePartial $ fromJust $ decodeCbor $ CborBytes $ " + <> show (toBytes a) + <> ")" + +unsafeFromJust :: forall a. String -> Maybe a -> a +unsafeFromJust e a = case a of + Nothing -> + unsafePerformEffect $ throw $ "unsafeFromJust: impossible happened: " + <> e + <> " (please report as bug at " + <> bugTrackerLink + <> " )" + Just v -> v diff --git a/src/Internal/IsData.purs b/src/Internal/IsData.purs index 06c5552cd1..95551efb8e 100644 --- a/src/Internal/IsData.purs +++ b/src/Internal/IsData.purs @@ -1,7 +1,7 @@ module Ctl.Internal.IsData (class IsData) where -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.ToData (class ToData) +import Cardano.FromData (class FromData) +import Cardano.ToData (class ToData) class IsData :: Type -> Constraint class (FromData a, ToData a) <= IsData a diff --git a/src/Internal/JsWebSocket.js b/src/Internal/JsWebSocket.js index f48f4465c3..e05ce2748c 100644 --- a/src/Internal/JsWebSocket.js +++ b/src/Internal/JsWebSocket.js @@ -1,16 +1,7 @@ -/* global BROWSER_RUNTIME */ - import ReconnectingWebSocket from "reconnecting-websocket"; +import WebSocket from "isomorphic-ws"; -let OurWebSocket; -if (typeof BROWSER_RUNTIME == "undefined" || !BROWSER_RUNTIME) { - const { default: WebSocket } = await import("ws"); - OurWebSocket = WebSocket; -} else { - OurWebSocket = WebSocket; -} - -class NoPerMessageDeflateWebSocket extends OurWebSocket { +class NoPerMessageDeflateWebSocket extends WebSocket { constructor(url, protocols, options) { options = options || {}; options.perMessageDeflate = false; @@ -21,14 +12,9 @@ class NoPerMessageDeflateWebSocket extends OurWebSocket { export function _mkWebSocket(logger) { return url => () => { try { - let ws; - if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - ws = new ReconnectingWebSocket(url); - } else { - ws = new ReconnectingWebSocket(url, [], { - WebSocket: NoPerMessageDeflateWebSocket - }); - } + const ws = new ReconnectingWebSocket(url, [], { + WebSocket: NoPerMessageDeflateWebSocket + }); ws.finalizers = []; logger("Created a new WebSocket")(); return ws; diff --git a/src/Internal/Metadata/Cip25/Cip25String.purs b/src/Internal/Metadata/Cip25/Cip25String.purs deleted file mode 100644 index f2cde33c4c..0000000000 --- a/src/Internal/Metadata/Cip25/Cip25String.purs +++ /dev/null @@ -1,141 +0,0 @@ --- | This module includes a string type that is used in CIP-25 standard. -module Ctl.Internal.Metadata.Cip25.Cip25String - ( Cip25String - , mkCip25String - , unCip25String - , fromMetadataString - , toMetadataString - , toCip25Strings - , fromCip25Strings - , fromDataString - , toDataString - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , decodeAeson - ) -import Control.Alt ((<|>)) -import Ctl.Internal.FromData (class FromData, fromData) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata, fromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata, toMetadata) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.ByteArray (byteLength) -import Ctl.Internal.Types.PlutusData (PlutusData) -import Ctl.Internal.Types.TransactionMetadata (TransactionMetadatum) -import Data.Array ((:)) -import Data.Array as Array -import Data.Either (note) -import Data.Foldable (foldMap) -import Data.Maybe (Maybe(Nothing, Just), isJust) -import Data.Newtype (wrap) -import Data.String.CodePoints as String -import Data.TextEncoder (encodeUtf8) -import Data.Tuple.Nested (type (/\), (/\)) - --- | A string type that is used in CIP-25 standard. --- | String length in bytes (in UTF-8) is limited by 64, because PlutusData --- | bytes have this length limit. -newtype Cip25String = Cip25String String - -derive newtype instance Eq Cip25String -derive newtype instance Ord Cip25String -derive newtype instance ToMetadata Cip25String -derive newtype instance FromMetadata Cip25String -derive newtype instance ToData Cip25String -derive newtype instance FromData Cip25String -derive newtype instance EncodeAeson Cip25String - -instance Show Cip25String where - show (Cip25String str) = "(unsafePartial (fromJust (mkCip25String " - <> show str - <> ")))" - -instance DecodeAeson Cip25String where - decodeAeson = decodeAeson >=> mkCip25String >>> note - (TypeMismatch "Cip25String") - -unCip25String :: Cip25String -> String -unCip25String (Cip25String str) = str - --- | A smart constructor for `Cip25String` -mkCip25String :: String -> Maybe Cip25String -mkCip25String str - | byteLength (wrap (encodeUtf8 str)) <= 64 = Just $ Cip25String str - | otherwise = Nothing - -takeCip25String :: String -> Maybe { init :: Cip25String, rest :: Maybe String } -takeCip25String str = - -- > https://www.rfc-editor.org/rfc/rfc3629 - -- - -- In UTF-8, characters from the U+0000..U+10FFFF range (the UTF-16 - -- accessible range) are encoded using sequences of 1 to 4 octets - -- - -- Hence we start at 64/4 = 16 (worst case, all code points take 4 bytes), - -- with a step equal to (64 - 16) / 2 = 24. - case - forwardSearch - { minBound: 16 - , maxBound: 64 - , step: 24 - , takeN: \ix -> mkCip25String (String.take ix str) - } - of - Nothing /\ _ -> Nothing - Just cip25String /\ ix -> Just - { init: cip25String - , rest: - let - rest = String.drop ix str - in - if rest == "" then Nothing else Just rest - } - -forwardSearch - :: forall (a :: Type) - . { step :: Int, minBound :: Int, maxBound :: Int, takeN :: Int -> Maybe a } - -> Maybe a /\ Int -forwardSearch { minBound, maxBound, takeN, step } - | isJust (takeN $ minBound + step) = - if minBound + step <= maxBound then forwardSearch - { minBound: minBound + step, maxBound, takeN, step } - else takeN maxBound /\ maxBound - | otherwise = - if step == 1 then - takeN minBound /\ minBound - else - forwardSearch - { minBound: minBound, maxBound, takeN, step: step `div` 2 } - -toCip25Strings :: String -> Array Cip25String -toCip25Strings str = case takeCip25String str of - Nothing -> [] - Just { init: cip25String, rest } -> - case rest of - Just restString -> cip25String : toCip25Strings restString - Nothing -> [ cip25String ] - -fromCip25Strings :: Array Cip25String -> String -fromCip25Strings = foldMap unCip25String - -toDataString :: String -> PlutusData -toDataString str = case toCip25Strings str of - [ singleStr ] -> toData singleStr - strings -> toData $ toData <$> strings - -fromDataString :: PlutusData -> Maybe String -fromDataString datum = fromCip25Strings <$> - ((Array.singleton <$> fromData datum) <|> fromData datum) - -toMetadataString :: String -> TransactionMetadatum -toMetadataString str = case toCip25Strings str of - [ singleStr ] -> toMetadata singleStr - strings -> toMetadata $ toMetadata <$> strings - -fromMetadataString :: TransactionMetadatum -> Maybe String -fromMetadataString datum = fromCip25Strings <$> - ((Array.singleton <$> fromMetadata datum) <|> fromMetadata datum) diff --git a/src/Internal/Metadata/Cip25/Common.purs b/src/Internal/Metadata/Cip25/Common.purs deleted file mode 100644 index 09b1c5eebc..0000000000 --- a/src/Internal/Metadata/Cip25/Common.purs +++ /dev/null @@ -1,137 +0,0 @@ --- | This module contains definitions common for CIP-25 V1 and V2 standards --- | (and probably future versions). --- | https://cips.cardano.org/cips/cip25/ -module Ctl.Internal.Metadata.Cip25.Common - ( nftMetadataLabel - , Cip25TokenName(Cip25TokenName) - , Cip25MetadataFile(Cip25MetadataFile) - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , caseAesonObject - , decodeAeson - , encodeAeson - , (.:) - ) -import Ctl.Internal.FromData (class FromData, fromData) -import Ctl.Internal.Metadata.Cip25.Cip25String - ( Cip25String - , fromDataString - , fromMetadataString - , toDataString - , toMetadataString - ) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata, fromMetadata) -import Ctl.Internal.Metadata.Helpers - ( errExpectedObject - , lookupKey - , lookupMetadata - ) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata, toMetadata) -import Ctl.Internal.Plutus.Types.AssocMap as AssocMap -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.TokenName (TokenName, getTokenName, mkTokenName) -import Data.Either (note) -import Data.Generic.Rep (class Generic) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Show.Generic (genericShow) -import Data.Tuple.Nested ((/\)) -import JS.BigInt (BigInt) -import JS.BigInt as BigInt - -nftMetadataLabel :: BigInt -nftMetadataLabel = BigInt.fromInt 721 - --- | A newtype over `TokenName` that uses correct Json encoding (without `0x` prefix) -newtype Cip25TokenName = Cip25TokenName TokenName - -derive newtype instance Eq Cip25TokenName -derive newtype instance Ord Cip25TokenName -derive newtype instance ToData Cip25TokenName -derive newtype instance FromData Cip25TokenName -derive newtype instance ToMetadata Cip25TokenName -derive newtype instance FromMetadata Cip25TokenName -derive instance Newtype Cip25TokenName _ - -instance Show Cip25TokenName where - show (Cip25TokenName tn) = "(Cip25TokenName " <> show tn <> ")" - -instance DecodeAeson Cip25TokenName where - decodeAeson = (note (TypeMismatch "TokenName") <<< map wrap <<< mkTokenName) - <=< decodeAeson - -instance EncodeAeson Cip25TokenName where - encodeAeson = encodeAeson <<< getTokenName <<< unwrap - --- | `files_details` in CDDL --- | --- | Same for V1 and V2. --- | --- | ``` --- | files_details = --- | { --- | name : string, --- | mediaType : string, --- | src : string / [* string] --- | } --- | ``` -newtype Cip25MetadataFile = Cip25MetadataFile - { name :: Cip25String - , mediaType :: Cip25String - , src :: String - } - -derive instance Generic Cip25MetadataFile _ -derive instance Newtype Cip25MetadataFile _ -derive instance Eq Cip25MetadataFile - -instance Show Cip25MetadataFile where - show = genericShow - -instance ToMetadata Cip25MetadataFile where - toMetadata (Cip25MetadataFile file) = toMetadata - [ "name" /\ toMetadata file.name - , "mediaType" /\ toMetadata file.mediaType - , "src" /\ toMetadataString file.src - ] - -instance FromMetadata Cip25MetadataFile where - fromMetadata contents = do - name <- lookupMetadata "name" contents >>= fromMetadata - mediaType <- lookupMetadata "mediaType" contents >>= fromMetadata - src <- lookupMetadata "src" contents >>= fromMetadataString - pure $ wrap { name, mediaType, src } - -instance ToData Cip25MetadataFile where - toData (Cip25MetadataFile file) = toData $ AssocMap.Map $ - [ "name" /\ toData file.name - , "mediaType" /\ toData file.mediaType - , "src" /\ toDataString file.src - ] - -instance FromData Cip25MetadataFile where - fromData contents = do - name <- lookupKey "name" contents >>= fromData - mediaType <- lookupKey "mediaType" contents >>= fromData - src <- lookupKey "src" contents >>= fromDataString - pure $ wrap { name, mediaType, src } - -instance DecodeAeson Cip25MetadataFile where - decodeAeson = - caseAesonObject errExpectedObject \obj -> do - name <- obj .: "name" - mediaType <- obj .: "mediaType" - src <- obj .: "src" - pure $ wrap { name, mediaType, src } - -instance EncodeAeson Cip25MetadataFile where - encodeAeson (Cip25MetadataFile { name, mediaType, src }) = encodeAeson - { name - , mediaType - , src - } diff --git a/src/Internal/Metadata/Cip25/V2.purs b/src/Internal/Metadata/Cip25/V2.purs deleted file mode 100644 index 7cdeefbbd0..0000000000 --- a/src/Internal/Metadata/Cip25/V2.purs +++ /dev/null @@ -1,383 +0,0 @@ --- Implementation of CIP 25 - NFT Metadata Standard V2. --- https://cips.cardano.org/cips/cip25/ --- https://cips.cardano.org/cips/cip25/cddl/version_2.cddl --- --- Differences from the spec: --- - We do not split strings in pieces when encoding to JSON --- - We require a "version": 2 tag. --- - `policy_id` is 28 bytes --- - `asset_name` is up to 32 bytes. --- --- Motivation: https://github.com/cardano-foundation/CIPs/issues/303 -module Ctl.Internal.Metadata.Cip25.V2 - ( Cip25Metadata(Cip25Metadata) - , Cip25MetadataEntry(Cip25MetadataEntry) - , module Ctl.Internal.Metadata.Cip25.Common - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , Aeson - , JsonDecodeError(TypeMismatch) - , caseAesonObject - , decodeAeson - , (.:) - , (.:?) - ) -import Aeson as Aeson -import Control.Alt ((<|>)) -import Ctl.Internal.FromData (class FromData, fromData) -import Ctl.Internal.Metadata.Cip25.Cip25String - ( Cip25String - , fromDataString - , fromMetadataString - , toDataString - , toMetadataString - ) -import Ctl.Internal.Metadata.Cip25.Common - ( Cip25MetadataFile(Cip25MetadataFile) - , Cip25TokenName(Cip25TokenName) - , nftMetadataLabel - ) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata, fromMetadata) -import Ctl.Internal.Metadata.Helpers - ( errExpectedObject - , lookupKey - , lookupMetadata - ) -import Ctl.Internal.Metadata.MetadataType (class MetadataType) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata, toMetadata) -import Ctl.Internal.Plutus.Types.AssocMap (Map(Map), singleton) as AssocMap -import Ctl.Internal.Serialization.Hash (scriptHashFromBytes, scriptHashToBytes) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.ByteArray (byteArrayToHex, hexToByteArray) -import Ctl.Internal.Types.Int as Int -import Ctl.Internal.Types.PlutusData (PlutusData(Map, Integer)) -import Ctl.Internal.Types.RawBytes (rawBytesToHex) -import Ctl.Internal.Types.Scripts (MintingPolicyHash) -import Ctl.Internal.Types.TokenName (getTokenName, mkTokenName) -import Ctl.Internal.Types.TransactionMetadata - ( TransactionMetadatum(Int, MetadataMap) - ) -import Data.Array (catMaybes, concat, groupBy) -import Data.Array.NonEmpty (NonEmptyArray, toArray) -import Data.Array.NonEmpty (head) as NonEmpty -import Data.Either (Either(Left), note) -import Data.Function (on) -import Data.Generic.Rep (class Generic) -import Data.Map (toUnfoldable) as Map -import Data.Maybe (Maybe(Just, Nothing), fromJust, fromMaybe) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Show.Generic (genericShow) -import Data.TextEncoder (encodeUtf8) -import Data.Traversable (fold, for, sequence, traverse) -import Data.Tuple (Tuple) -import Data.Tuple.Nested ((/\)) -import Foreign.Object (Object, toUnfoldable) as FO -import JS.BigInt (fromInt, toString) as BigInt -import Partial.Unsafe (unsafePartial) - --- | ``` --- | metadata_details = --- | { --- | name : string, --- | image : string / [* string], --- | ? mediaType : string, --- | ? description : string / [* string], --- | ? files : [* files_details] --- | } --- | ``` -newtype Cip25MetadataEntry = Cip25MetadataEntry - { policyId :: MintingPolicyHash - , assetName :: Cip25TokenName - -- metadata_details: - , name :: Cip25String - , image :: String - , mediaType :: Maybe Cip25String - , description :: Maybe String - , files :: Array Cip25MetadataFile - } - -derive instance Generic Cip25MetadataEntry _ -derive instance Newtype Cip25MetadataEntry _ -derive instance Eq Cip25MetadataEntry - -instance Show Cip25MetadataEntry where - show = genericShow - --- | A version tag (not exported, internal) -data Cip25V2 = Cip25V2 - -derive instance Eq Cip25V2 -derive instance Ord Cip25V2 -derive instance Generic Cip25V2 _ - -instance Show Cip25V2 where - show = genericShow - -instance FromData Cip25V2 where - fromData (Integer int) - | int == BigInt.fromInt 2 = pure Cip25V2 - fromData _ = Nothing - -instance ToData Cip25V2 where - toData _ = Integer $ BigInt.fromInt 2 - -instance FromMetadata Cip25V2 where - fromMetadata (Int int) - | Int.toBigInt int == BigInt.fromInt 2 = pure Cip25V2 - fromMetadata _ = Nothing - -instance ToMetadata Cip25V2 where - toMetadata _ = Int $ unsafePartial $ fromJust $ Int.fromBigInt $ - BigInt.fromInt 2 - -instance DecodeAeson Cip25V2 where - decodeAeson aeson = do - n :: Int <- decodeAeson aeson - case n of - 2 -> pure Cip25V2 - _ -> Left $ TypeMismatch "Cip25V2" - --- Note: this is not an instance of `ToMetadata` to prevent confusion --- between `Cip25Metadata` and `Cip25MetadataEntry` (the users do not --- need to deal with data-representations of a single entry, because --- the standard only specifies the encoding for Cip25Metadata). -metadataEntryToMetadata :: Cip25MetadataEntry -> TransactionMetadatum -metadataEntryToMetadata (Cip25MetadataEntry entry) = toMetadata $ - [ "name" /\ toMetadata entry.name - , "image" /\ toMetadataString entry.image - ] - <> mbMediaType - <> mbDescription - <> mbFiles - where - mbFiles = case entry.files of - [] -> [] - files -> [ "files" /\ toMetadata files ] - mbMediaType = fold $ entry.mediaType <#> \mediaType -> - [ "mediaType" /\ toMetadata mediaType ] - mbDescription = fold $ entry.description <#> \description -> - [ "description" /\ toMetadataString description ] - -metadataEntryFromMetadata - :: MintingPolicyHash - -> Cip25TokenName - -> TransactionMetadatum - -> Maybe Cip25MetadataEntry -metadataEntryFromMetadata policyId assetName contents = do - name <- lookupMetadata "name" contents >>= fromMetadata - image <- lookupMetadata "image" contents >>= fromMetadataString - mediaType <- for (lookupMetadata "mediaType" contents) fromMetadata - description <- for (lookupMetadata "description" contents) fromMetadataString - files <- for (lookupMetadata "files" contents) fromMetadata <#> fromMaybe [] - pure $ - wrap { policyId, assetName, name, image, mediaType, description, files } - -metadataEntryToData :: Cip25MetadataEntry -> PlutusData -metadataEntryToData (Cip25MetadataEntry entry) = toData $ AssocMap.Map $ - [ "name" /\ toData entry.name - , "image" /\ toDataString entry.image - ] - <> mbMediaType - <> mbDescription - <> mbFiles - where - mbFiles = case entry.files of - [] -> [] - files -> [ "files" /\ toData files ] - mbMediaType = fold $ entry.mediaType <#> \mediaType -> - [ "mediaType" /\ toData mediaType ] - mbDescription = fold $ entry.description <#> \description -> - [ "description" /\ toDataString description ] - -metadataEntryFromData - :: MintingPolicyHash - -> Cip25TokenName - -> PlutusData - -> Maybe Cip25MetadataEntry -metadataEntryFromData policyId assetName contents = do - name <- lookupKey "name" contents >>= fromData - image <- lookupKey "image" contents >>= fromDataString - mediaType <- for (lookupKey "mediaType" contents) fromData - description <- for (lookupKey "description" contents) fromDataString - files <- for (lookupKey "files" contents) fromData <#> fromMaybe [] - pure $ - wrap { policyId, assetName, name, image, mediaType, description, files } - -metadataEntryDecodeAeson - :: MintingPolicyHash - -> Cip25TokenName - -> Aeson - -> Either JsonDecodeError Cip25MetadataEntry -metadataEntryDecodeAeson policyId assetName = - caseAesonObject errExpectedObject \obj -> do - name <- obj .: "name" - image <- obj .: "image" - mediaType <- obj .:? "mediaType" - description <- obj .:? "description" <#> fromMaybe mempty - files <- obj .:? "files" >>= \mbFiles -> - fromMaybe [] <$> for mbFiles \files -> - traverse decodeAeson =<< note (TypeMismatch "files") - (Aeson.toArray files) - pure $ - wrap { policyId, assetName, name, image, mediaType, description, files } - --- | Encode the entry's policy id to the string used as the metadata --- | key -encodePolicyIdKey :: Cip25MetadataEntry -> String -encodePolicyIdKey (Cip25MetadataEntry { policyId }) = - rawBytesToHex $ scriptHashToBytes $ unwrap policyId - --- | Decode the CIP25 policy id key -decodePolicyIdKey :: String -> Maybe MintingPolicyHash -decodePolicyIdKey = map wrap <<< scriptHashFromBytes <=< hexToByteArray - --- | Encode the entry's asset name to the string used as the metadata --- | key -encodeAssetNameKey :: Cip25MetadataEntry -> String -encodeAssetNameKey (Cip25MetadataEntry { assetName }) = - byteArrayToHex $ getTokenName $ unwrap assetName - --- | Decode the CIP25 asset name key -decodeAssetNameKey :: String -> Maybe Cip25TokenName -decodeAssetNameKey = map wrap <<< mkTokenName <=< hexToByteArray - -newtype Cip25Metadata = Cip25Metadata (Array Cip25MetadataEntry) - -derive instance Generic Cip25Metadata _ -derive instance Newtype Cip25Metadata _ -derive instance Eq Cip25Metadata - -instance Show Cip25Metadata where - show = genericShow - -instance MetadataType Cip25Metadata where - metadataLabel _ = wrap nftMetadataLabel - -groupEntries - :: Array Cip25MetadataEntry -> Array (NonEmptyArray Cip25MetadataEntry) -groupEntries = groupBy (eq `on` (unwrap >>> _.policyId)) - -instance ToMetadata Cip25Metadata where - toMetadata (Cip25Metadata entries) = toMetadata $ - let - dataEntries = - groupEntries entries <#> - \group -> - ( toMetadata $ encodePolicyIdKey $ NonEmpty.head group - ) /\ - (toMetadata <<< toArray <<< flip map group) \entry -> - (encodeAssetNameKey entry) /\ metadataEntryToMetadata entry - versionEntry = [ toMetadata "version" /\ toMetadata Cip25V2 ] - in - dataEntries <> versionEntry - -instance FromMetadata Cip25Metadata where - fromMetadata (MetadataMap mp1) = do - entries <- map concat - $ map catMaybes - $ for (Map.toUnfoldable mp1) - \(key /\ assets) -> - if key == toMetadata "version" then - -- top-level version tag - ( if assets == toMetadata Cip25V2 then pure Nothing - else Nothing -- fail if version does not match - ) - else - -- key is policyId - Just case assets of - MetadataMap mp2 -> - for (Map.toUnfoldable mp2) \(assetName /\ contents) -> - metadataEntryFromMetadata - <$> (decodePolicyIdKey =<< fromMetadata key) - <*> (decodeAssetNameKey =<< fromMetadata assetName) - <*> pure contents - _ -> Nothing - wrap <$> sequence entries - fromMetadata _ = Nothing - -instance ToData Cip25Metadata where - toData (Cip25Metadata entries) = toData - $ AssocMap.singleton (toData $ BigInt.toString nftMetadataLabel) - $ AssocMap.Map - let - dataEntries = - groupEntries entries <#> - \group -> - toData (encodePolicyIdKey $ NonEmpty.head group) /\ toData - ( (AssocMap.Map <<< toArray <<< flip map group) \entry -> - toData (encodeAssetNameKey entry) /\ metadataEntryToData - entry - ) - versionEntry = [ toData "version" /\ toData Cip25V2 ] - in - dataEntries <> versionEntry - -instance FromData Cip25Metadata where - fromData meta = do - entries <- lookupKey (BigInt.toString nftMetadataLabel) meta >>= case _ of - Map mp1 -> map concat - $ for mp1 - \(policyId /\ assets) -> - let - fromDataAssets = - case assets of - Map mp2 -> - for mp2 \(assetName /\ contents) -> - metadataEntryFromData - <$> (decodePolicyIdKey =<< fromData policyId) - <*> (decodeAssetNameKey =<< fromData assetName) - <*> pure contents - _ -> Nothing - fromDataVersion = - if - policyId == toData "version" - && assets == toData Cip25V2 then - pure [] - else - Nothing - in - fromDataAssets <|> fromDataVersion - _ -> Nothing - wrap <$> sequence entries - -instance DecodeAeson Cip25Metadata where - decodeAeson = - caseAesonObject errExpectedObject \obj -> do - policies <- obj .: BigInt.toString nftMetadataLabel - withJsonObject policies \objPolicies -> - map (wrap <<< concat) - $ for (objToArray objPolicies) - \(policyId /\ assets) -> - withJsonObject assets \objAssets -> - for (objToArray objAssets) \(assetName /\ contents) -> do - policyId_ <- decodePolicyId policyId - assetName_ <- decodeAssetName assetName - metadataEntryDecodeAeson policyId_ assetName_ contents - where - objToArray :: forall (a :: Type). FO.Object a -> Array (Tuple String a) - objToArray = FO.toUnfoldable - - withJsonObject - :: forall (a :: Type) - . Aeson - -> (FO.Object Aeson -> Either JsonDecodeError a) - -> Either JsonDecodeError a - withJsonObject = flip (caseAesonObject errExpectedObject) - - decodePolicyId :: String -> Either JsonDecodeError MintingPolicyHash - decodePolicyId = - note (TypeMismatch "Expected hex-encoded policy id") - <<< map wrap - <<< (scriptHashFromBytes <=< hexToByteArray) - - decodeAssetName :: String -> Either JsonDecodeError Cip25TokenName - decodeAssetName = - note (TypeMismatch "Expected UTF-8 encoded asset name") - <<< map wrap - <<< mkTokenName - <<< wrap - <<< encodeUtf8 diff --git a/src/Internal/Metadata/FromMetadata.purs b/src/Internal/Metadata/FromMetadata.purs deleted file mode 100644 index 6f115b1e8c..0000000000 --- a/src/Internal/Metadata/FromMetadata.purs +++ /dev/null @@ -1,63 +0,0 @@ -module Ctl.Internal.Metadata.FromMetadata where - -import Prelude - -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.Int (Int, toBigInt) as Int -import Ctl.Internal.Types.TransactionMetadata - ( TransactionMetadatum(MetadataList, Int, Bytes, Text) - ) -import Data.Array (toUnfoldable, uncons) as Array -import Data.Maybe (Maybe(Just, Nothing)) -import Data.NonEmpty (NonEmpty, (:|)) -import Data.Traversable (traverse) -import Data.Unfoldable (class Unfoldable) -import JS.BigInt (BigInt) - --------------------------------------------------------------------------------- --- FromMetadata --------------------------------------------------------------------------------- - -class FromMetadata (a :: Type) where - fromMetadata :: TransactionMetadatum -> Maybe a - -instance FromMetadata TransactionMetadatum where - fromMetadata = Just - -instance FromMetadata a => FromMetadata (Array a) where - fromMetadata = fromMetadataUnfoldable - -instance FromMetadata a => FromMetadata (NonEmpty Array a) where - fromMetadata md = do - { head, tail } <- Array.uncons =<< fromMetadata md - pure (head :| tail) - -instance FromMetadata Int.Int where - fromMetadata (Int n) = Just n - fromMetadata _ = Nothing - -instance FromMetadata BigInt where - fromMetadata (Int n) = pure $ Int.toBigInt n - fromMetadata _ = Nothing - -instance FromMetadata ByteArray where - fromMetadata (Bytes byteArr) = Just byteArr - fromMetadata _ = Nothing - -instance FromMetadata String where - fromMetadata (Text str) = Just str - fromMetadata _ = Nothing - --------------------------------------------------------------------------------- --- Internal --------------------------------------------------------------------------------- - -fromMetadataUnfoldable - :: forall (a :: Type) (f :: Type -> Type) - . Unfoldable f - => FromMetadata a - => TransactionMetadatum - -> Maybe (f a) -fromMetadataUnfoldable (MetadataList entries) = - Array.toUnfoldable <$> traverse fromMetadata entries -fromMetadataUnfoldable _ = Nothing diff --git a/src/Internal/Metadata/Helpers.purs b/src/Internal/Metadata/Helpers.purs deleted file mode 100644 index ec4ae266ec..0000000000 --- a/src/Internal/Metadata/Helpers.purs +++ /dev/null @@ -1,38 +0,0 @@ -module Ctl.Internal.Metadata.Helpers - ( mkKey - , unsafeMkKey - , lookupKey - , lookupMetadata - , errExpectedObject - ) where - -import Prelude - -import Aeson (JsonDecodeError(TypeMismatch)) -import Ctl.Internal.Types.ByteArray (byteArrayFromAscii) -import Ctl.Internal.Types.PlutusData (PlutusData(Map, Bytes)) -import Ctl.Internal.Types.TransactionMetadata - ( TransactionMetadatum(MetadataMap, Text) - ) -import Data.Either (Either(Left)) -import Data.Foldable (lookup) -import Data.Map (lookup) as Map -import Data.Maybe (Maybe(Nothing), fromJust) - -mkKey :: String -> Maybe PlutusData -mkKey str = Bytes <$> byteArrayFromAscii str - -unsafeMkKey :: Partial => String -> PlutusData -unsafeMkKey = fromJust <<< mkKey - -lookupKey :: String -> PlutusData -> Maybe PlutusData -lookupKey keyStr (Map array) = mkKey keyStr >>= flip lookup array -lookupKey _ _ = Nothing - -lookupMetadata :: String -> TransactionMetadatum -> Maybe TransactionMetadatum -lookupMetadata keyStr (MetadataMap mp) = Map.lookup (Text keyStr) mp -lookupMetadata _ _ = Nothing - -errExpectedObject :: forall (a :: Type). Either JsonDecodeError a -errExpectedObject = - Left (TypeMismatch "Expected object") diff --git a/src/Internal/Metadata/MetadataType.purs b/src/Internal/Metadata/MetadataType.purs index fb742499ad..3168158e40 100644 --- a/src/Internal/Metadata/MetadataType.purs +++ b/src/Internal/Metadata/MetadataType.purs @@ -7,26 +7,27 @@ module Ctl.Internal.Metadata.MetadataType import Prelude -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata, fromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata, toMetadata) -import Ctl.Internal.Types.TransactionMetadata - ( GeneralTransactionMetadata - , TransactionMetadatumLabel - ) +import Cardano.FromMetadata (class FromMetadata, fromMetadata) +import Cardano.ToMetadata (class ToMetadata, toMetadata) +import Cardano.Types (GeneralTransactionMetadata) +import Ctl.Internal.Types.MetadataLabel (MetadataLabel) import Data.Map (lookup, singleton) as Map import Data.Maybe (Maybe) import Data.Newtype (unwrap, wrap) import Type.Proxy (Proxy(Proxy)) +-- | Associates a metadata label with a type. E.g. a CIP-25 metadata type could be associated with label `721`. class (FromMetadata a, ToMetadata a) <= MetadataType (a :: Type) where - metadataLabel :: Proxy a -> TransactionMetadatumLabel + metadataLabel :: Proxy a -> MetadataLabel fromGeneralTxMetadata :: forall (a :: Type). MetadataType a => GeneralTransactionMetadata -> Maybe a fromGeneralTxMetadata = - fromMetadata <=< Map.lookup (metadataLabel (Proxy :: Proxy a)) <<< unwrap + fromMetadata <=< Map.lookup (unwrap $ metadataLabel (Proxy :: Proxy a)) <<< + unwrap toGeneralTxMetadata :: forall (a :: Type). MetadataType a => a -> GeneralTransactionMetadata toGeneralTxMetadata = - wrap <<< Map.singleton (metadataLabel (Proxy :: Proxy a)) <<< toMetadata + wrap <<< Map.singleton (unwrap $ metadataLabel (Proxy :: Proxy a)) <<< + toMetadata diff --git a/src/Internal/Metadata/ToMetadata.purs b/src/Internal/Metadata/ToMetadata.purs deleted file mode 100644 index b8dd0bf333..0000000000 --- a/src/Internal/Metadata/ToMetadata.purs +++ /dev/null @@ -1,61 +0,0 @@ -module Ctl.Internal.Metadata.ToMetadata - ( class ToMetadata - , toMetadata - ) where - -import Prelude - -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.Int (Int, fromBigInt) as Int -import Ctl.Internal.Types.TransactionMetadata - ( TransactionMetadatum(MetadataMap, MetadataList, Int, Bytes, Text) - ) -import Data.Map (Map) -import Data.Map (fromFoldable, toUnfoldable) as Map -import Data.Maybe (fromJust) -import Data.Profunctor.Strong ((***)) -import Data.Tuple (Tuple) -import JS.BigInt (BigInt) -import Partial.Unsafe (unsafePartial) - --------------------------------------------------------------------------------- --- ToMetadata --------------------------------------------------------------------------------- - -class ToMetadata (a :: Type) where - toMetadata :: a -> TransactionMetadatum - -instance ToMetadata TransactionMetadatum where - toMetadata = identity - -instance (ToMetadata k, ToMetadata v) => ToMetadata (Map k v) where - toMetadata mp = - let - entries = Map.toUnfoldable mp :: Array (Tuple k v) - in - MetadataMap <<< Map.fromFoldable $ - map (toMetadata *** toMetadata) entries - -instance - ( Ord k - , ToMetadata k - , ToMetadata v - ) => - ToMetadata (Array (Tuple k v)) where - toMetadata = toMetadata <<< Map.fromFoldable -else instance ToMetadata a => ToMetadata (Array a) where - toMetadata = MetadataList <<< map toMetadata - -instance ToMetadata Int.Int where - toMetadata = Int - --- FIXME: Come up with a type-safe error handling approach. -instance ToMetadata BigInt where - toMetadata bi = - unsafePartial $ Int $ fromJust $ Int.fromBigInt bi - -instance ToMetadata ByteArray where - toMetadata = Bytes - -instance ToMetadata String where - toMetadata = Text diff --git a/src/Internal/NativeScripts.purs b/src/Internal/NativeScripts.purs index e692cffd0b..9c1d8549f6 100644 --- a/src/Internal/NativeScripts.purs +++ b/src/Internal/NativeScripts.purs @@ -6,7 +6,9 @@ module Ctl.Internal.NativeScripts import Prelude -import Ctl.Internal.Cardano.Types.NativeScript +import Cardano.Serialization.Lib (nativeScript_hash) +import Cardano.Types (Ed25519KeyHash, ScriptHash) +import Cardano.Types.NativeScript ( NativeScript ( ScriptPubkey , ScriptAll @@ -16,9 +18,7 @@ import Ctl.Internal.Cardano.Types.NativeScript , TimelockExpiry ) ) -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash, ScriptHash) -import Ctl.Internal.Serialization.Hash as Hashing -import Ctl.Internal.Serialization.NativeScript (convertNativeScript) +import Cardano.Types.NativeScript as NativeScript import Data.Array as Array import Data.Foldable (foldr, maximumBy) import Data.Function (on) @@ -39,7 +39,7 @@ instance Show NativeScriptHash where show (NativeScriptHash sh) = "(NativeScriptHash " <> show sh <> ")" nativeScriptHash :: NativeScript -> NativeScriptHash -nativeScriptHash = wrap <<< Hashing.nativeScriptHash <<< convertNativeScript +nativeScriptHash = wrap <<< wrap <<< nativeScript_hash <<< NativeScript.toCsl -- | `SetChoice` is an internal type representing internal state of -- | `getMaximumSigners` algorithm. @@ -68,9 +68,9 @@ sublists n xs = List.take (List.length xs - n + 1) $ sublists' n xs -- | Used for fee calculation. -- | We try to calculate maximum number of signers from the script itself, -- | following its logic. --- | But we must not count `requiredSigners` as signers from native scripts --- | twice, because that would lead to excessive fees. Hence we accept a set --- | of already known signers to be ignored in this function. +-- | But we must not count `requiredSigners` and `selfSigners` as signers from +-- | native scripts twice, because that would lead to excessive fees. Hence we +-- | accept a set of already known signers to be ignored in this function. getMaximumSigners :: Set Ed25519KeyHash -> NativeScript -> Int getMaximumSigners alreadyCounted = sizes >>> maximumBy (compare `on` Set.size) >>> map Set.size >>> fromMaybe 0 diff --git a/src/Internal/Partition.purs b/src/Internal/Partition.purs index 16c4ad80e5..2c121a560d 100644 --- a/src/Internal/Partition.purs +++ b/src/Internal/Partition.purs @@ -3,10 +3,20 @@ module Ctl.Internal.Partition , class Partition , equipartition , partition + , equipartitionValueWithTokenQuantityUpperBound ) where import Prelude +import Cardano.Types.AssetName (AssetName) +import Cardano.Types.BigInt (divCeil) +import Cardano.Types.BigNum (BigNum) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.MultiAsset (MultiAsset) +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.ScriptHash (ScriptHash) +import Cardano.Types.Value (Value(Value)) +import Ctl.Internal.Helpers (unsafeFromJust) import Data.Array (replicate) import Data.Array.NonEmpty (NonEmptyArray) import Data.Array.NonEmpty @@ -19,20 +29,27 @@ import Data.Array.NonEmpty , zip , zipWith ) as NEArray -import Data.Foldable (any, length, sum) +import Data.Foldable (any, foldl, length, sum) import Data.Function (on) -import Data.Maybe (Maybe(Just, Nothing), fromJust) -import Data.Newtype (class Newtype, unwrap) +import Data.Maybe (Maybe(Just, Nothing)) +import Data.Newtype (class Newtype, unwrap, wrap) import Data.Ordering (invert) as Ordering import Data.Tuple (fst, snd) import Data.Tuple.Nested (type (/\), (/\)) import JS.BigInt (BigInt) import JS.BigInt (fromInt, toInt) as BigInt import Partial.Unsafe (unsafePartial) +import Prelude as Prelude class Partition (a :: Type) where partition :: a -> NonEmptyArray a -> Maybe (NonEmptyArray a) +instance Partition BigNum where + partition bigNum = unsafePartial $ map BigNum.toBigInt + >>> partition (BigNum.toBigInt bigNum) + >>> map + (map $ unsafeFromJust "instance Partition BigNum" <<< BigNum.fromBigInt) + -- | Partitions a `BigInt` into a number of parts, where the size of each part -- | is proportional to the size of its corresponding element in the given -- | list of weights, and the number of parts is equal to the number of weights. @@ -76,13 +93,14 @@ instance Partition BigInt where round portions = NEArray.zipWith (+) (map (fst <<< unwrap) <$> portions) - ( fromArrayUnsafe $ + ( unsafeFromJust "instance Partition BigInt" <<< NEArray.fromArray $ replicate shortfall one <> replicate (length portions - shortfall) zero ) shortfall :: Int - shortfall = toIntUnsafe $ target - sum (map fst portionsUnrounded) + shortfall = unsafeFromJust "instance Partition BigInt" <<< BigInt.toInt + $ target - sum (map fst portionsUnrounded) portionsUnrounded :: NonEmptyArray (BigInt /\ BigInt) portionsUnrounded = weights <#> \w -> (target * w) `quotRem` sumWeights @@ -105,16 +123,34 @@ instance Equipartition BigInt where NEArray.singleton bi | otherwise = let - quot /\ rem = toIntUnsafe <$> (bi `quotRem` BigInt.fromInt numParts) + quot /\ rem = + unsafeFromJust "instance Equipartition BigInt" <<< BigInt.toInt <$> + (bi `quotRem` BigInt.fromInt numParts) in NEArray.replicate (numParts - rem) quot `NEArray.appendArray` replicate rem (quot + one) -toIntUnsafe :: BigInt -> Int -toIntUnsafe = unsafePartial fromJust <<< BigInt.toInt - -fromArrayUnsafe :: forall (a :: Type). Array a -> NonEmptyArray a -fromArrayUnsafe = unsafePartial fromJust <<< NEArray.fromArray +instance Equipartition BigNum where + equipartition bn = unsafePartial + $ map (unsafeFromJust "instance Equipartition BigNum" <<< BigNum.fromBigInt) + <<< equipartition (BigNum.toBigInt bn) + +instance Equipartition MultiAsset where + equipartition nonAdaAssets numParts = + foldl accumulate (NEArray.replicate numParts MultiAsset.empty) + (MultiAsset.flatten nonAdaAssets) + where + append' a b = unsafeFromJust "instance Equipartition MultiAsset" $ + MultiAsset.add a b + + accumulate + :: NonEmptyArray MultiAsset + -> (ScriptHash /\ AssetName /\ BigNum) + -> NonEmptyArray MultiAsset + accumulate xs (cs /\ tn /\ tokenQuantity) = + NEArray.zipWith append' xs $ + map (MultiAsset.singleton cs tn) + (equipartition tokenQuantity numParts) quotRem :: forall (a :: Type). EuclideanRing a => a -> a -> (a /\ a) quotRem a b = (a `div` b) /\ (a `mod` b) @@ -129,3 +165,51 @@ instance Ord a => Ord (QuotRem a) where case compare rem0 rem1 of EQ -> compare quot0 quot1 ordering -> ordering + +-- | Partitions a `Value` into smaller `Value`s, where the Ada amount and the +-- | quantity of each token is equipartitioned across the resultant `Value`s, +-- | with the goal that no token quantity in any of the resultant `Value`s +-- | exceeds the given upper bound. +-- | Taken from cardano-wallet: +-- | https://github.com/input-output-hk/cardano-wallet/blob/d4b30de073f2b5eddb25bf12c2453abb42e8b352/lib/wallet/src/Cardano/Wallet/Primitive/Types/TokenBundle.hs#L381 +equipartitionValueWithTokenQuantityUpperBound + :: BigInt -> Value -> NonEmptyArray Value +equipartitionValueWithTokenQuantityUpperBound maxTokenQuantity value = + let + Value coin nonAdaAssets = value + ms /\ numParts = + equipartitionAssetsWithTokenQuantityUpperBound nonAdaAssets + maxTokenQuantity + in + NEArray.zipWith Value (map wrap $ equipartition (unwrap coin) numParts) ms + +-- | Partitions a `MultiAsset` into smaller `MultiAsset`s, where the +-- | quantity of each token is equipartitioned across the resultant +-- | `MultiAsset`s, with the goal that no token quantity in any of the +-- | resultant `MultiAsset`s exceeds the given upper bound. +-- | Taken from cardano-wallet: +-- | https://github.com/input-output-hk/cardano-wallet/blob/d4b30de073f2b5eddb25bf12c2453abb42e8b352/lib/wallet/src/Cardano/Wallet/Primitive/Types/TokenMap.hs#L780 +equipartitionAssetsWithTokenQuantityUpperBound + :: MultiAsset -> BigInt -> NonEmptyArray MultiAsset /\ Int +equipartitionAssetsWithTokenQuantityUpperBound nonAdaAssets maxTokenQuantity = + case + maxTokenQuantity <= Prelude.zero || BigNum.toBigInt currentMaxTokenQuantity + <= maxTokenQuantity + of + true -> + NEArray.singleton nonAdaAssets /\ one + false -> + equipartition nonAdaAssets numParts /\ numParts + where + numParts :: Int + numParts = unsafeFromJust "equipartitionAssetsWithTokenQuantityUpperBound" + $ BigInt.toInt + $ divCeil (BigNum.toBigInt currentMaxTokenQuantity) maxTokenQuantity + + tokenQuantity :: (ScriptHash /\ AssetName /\ BigNum) -> BigNum + tokenQuantity (_ /\ _ /\ quantity) = quantity + + currentMaxTokenQuantity :: BigNum + currentMaxTokenQuantity = + foldl (\quantity tn -> quantity `max` tokenQuantity tn) BigNum.zero + (MultiAsset.flatten nonAdaAssets) diff --git a/src/Internal/Plutip/PortCheck.purs b/src/Internal/Plutip/PortCheck.purs deleted file mode 100644 index ca4343128f..0000000000 --- a/src/Internal/Plutip/PortCheck.purs +++ /dev/null @@ -1,15 +0,0 @@ -module Ctl.Internal.Plutip.PortCheck - ( isPortAvailable - ) where - -import Prelude - -import Control.Promise (Promise, toAffE) -import Data.UInt (UInt, toInt) -import Effect (Effect) -import Effect.Aff (Aff) - -foreign import _isPortAvailable :: Int -> Effect (Promise Boolean) - -isPortAvailable :: UInt -> Aff Boolean -isPortAvailable = toAffE <<< _isPortAvailable <<< toInt diff --git a/src/Internal/Plutip/Server.purs b/src/Internal/Plutip/Server.purs deleted file mode 100644 index b31118b3ff..0000000000 --- a/src/Internal/Plutip/Server.purs +++ /dev/null @@ -1,660 +0,0 @@ -module Ctl.Internal.Plutip.Server - ( runPlutipContract - , withPlutipContractEnv - , startPlutipCluster - , stopPlutipCluster - , startPlutipServer - , checkPlutipServer - , stopChildProcessWithPort - , testPlutipContracts - ) where - -import Prelude - -import Aeson (decodeAeson, encodeAeson, parseJsonStringToAeson, stringifyAeson) -import Affjax (defaultRequest) as Affjax -import Affjax.RequestBody as RequestBody -import Affjax.RequestHeader as Header -import Affjax.ResponseFormat as Affjax.ResponseFormat -import Contract.Address (NetworkId(MainnetId)) -import Contract.Chain (waitNSlots) -import Contract.Config (defaultSynchronizationParams, defaultTimeParams) -import Contract.Monad (Contract, ContractEnv, liftContractM, runContractInEnv) -import Control.Monad.Error.Class (liftEither, throwError) -import Control.Monad.State (State, execState, modify_) -import Control.Monad.Trans.Class (lift) -import Control.Monad.Writer (censor, execWriterT, tell) -import Ctl.Internal.Affjax (request) as Affjax -import Ctl.Internal.Contract.Hooks (emptyHooks) -import Ctl.Internal.Contract.Monad - ( buildBackend - , getLedgerConstants - , mkQueryHandle - , stopContractEnv - ) -import Ctl.Internal.Contract.QueryBackend (mkCtlBackendParams) -import Ctl.Internal.Helpers ((<>)) -import Ctl.Internal.Logging (Logger, mkLogger, setupLogs) -import Ctl.Internal.Plutip.PortCheck (isPortAvailable) -import Ctl.Internal.Plutip.Spawn - ( ManagedProcess - , NewOutputAction(Success, NoOp) - , OnSignalRef - , cleanupOnSigint - , cleanupTmpDir - , removeOnSignal - , spawn - , stop - ) -import Ctl.Internal.Plutip.Types - ( ClusterStartupParameters - , ClusterStartupRequest(ClusterStartupRequest) - , PlutipConfig - , PrivateKeyResponse(PrivateKeyResponse) - , StartClusterResponse(ClusterStartupSuccess, ClusterStartupFailure) - , StopClusterRequest(StopClusterRequest) - , StopClusterResponse - ) -import Ctl.Internal.Plutip.Utils (tmpdir) -import Ctl.Internal.Service.Error - ( ClientError(ClientDecodeJsonError, ClientHttpError) - , pprintClientError - ) -import Ctl.Internal.Test.ContractTest - ( ContractTest(ContractTest) - , ContractTestPlan(ContractTestPlan) - , ContractTestPlanHandler - ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Test.UtxoDistribution - ( class UtxoDistribution - , InitialUTxODistribution - , InitialUTxOs - , decodeWallets - , encodeDistribution - , keyWallets - , transferFundsFromEnterpriseToBase - ) -import Ctl.Internal.Types.UsedTxOuts (newUsedTxOuts) -import Ctl.Internal.Wallet.Key (PrivatePaymentKey(PrivatePaymentKey)) -import Data.Array as Array -import Data.Bifunctor (lmap) -import Data.Either (Either(Left, Right), either, isLeft) -import Data.Foldable (sum) -import Data.HTTP.Method as Method -import Data.Log.Level (LogLevel) -import Data.Log.Message (Message) -import Data.Maybe (Maybe(Nothing, Just), fromMaybe, maybe) -import Data.Newtype (over, unwrap, wrap) -import Data.Set as Set -import Data.String.CodeUnits (indexOf) as String -import Data.String.Pattern (Pattern(Pattern)) -import Data.Traversable (foldMap, for, for_, sequence_, traverse_) -import Data.Tuple (fst, snd) -import Data.Tuple.Nested (type (/\), (/\)) -import Data.UInt (UInt) -import Data.UInt as UInt -import Effect.Aff (Aff, Milliseconds(Milliseconds), try) -import Effect.Aff (bracket) as Aff -import Effect.Aff.Class (liftAff) -import Effect.Aff.Retry - ( RetryPolicy - , constantDelay - , limitRetriesByCumulativeDelay - , recovering - ) -import Effect.Class (liftEffect) -import Effect.Exception (error, message, throw) -import Effect.Ref (Ref) -import Effect.Ref as Ref -import JS.BigInt as BigInt -import Mote (bracket) as Mote -import Mote.Description (Description(Group, Test)) -import Mote.Monad (MoteT(MoteT), mapTest) -import Node.ChildProcess (defaultSpawnOptions) -import Node.FS.Sync (exists, mkdir) as FSSync -import Node.Path (FilePath, dirname) -import Type.Prelude (Proxy(Proxy)) - --- | Run a single `Contract` in Plutip environment. -runPlutipContract - :: forall (distr :: Type) (wallets :: Type) (a :: Type) - . UtxoDistribution distr wallets - => PlutipConfig - -> distr - -> (wallets -> Contract a) - -> Aff a -runPlutipContract cfg distr cont = withPlutipContractEnv cfg distr - \env wallets -> - runContractInEnv env (cont wallets) - --- | Provide a `ContractEnv` connected to Plutip. --- | can be used to run multiple `Contract`s using `runContractInEnv`. -withPlutipContractEnv - :: forall (distr :: Type) (wallets :: Type) (a :: Type) - . UtxoDistribution distr wallets - => PlutipConfig - -> distr - -> (ContractEnv -> wallets -> Aff a) - -> Aff a -withPlutipContractEnv plutipCfg distr cont = do - cleanupRef <- liftEffect $ Ref.new mempty - Aff.bracket - (try $ startPlutipContractEnv plutipCfg distr cleanupRef) - (const $ runCleanup cleanupRef) - $ liftEither >=> \{ env, wallets, printLogs } -> - whenError printLogs (cont env wallets) - --- | Run several `Contract`s in tests in a (single) Plutip environment (plutip-server and cluster, kupo, etc.). --- | NOTE: This uses `MoteT`s bracketing, and thus has the same caveats. --- | Namely, brackets are run for each of the top-level groups and tests --- | inside the bracket. --- | If you wish to only set up Plutip once, ensure all tests that are passed --- | to `testPlutipContracts` are wrapped in a single group. --- | https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/doc/plutip-testing.md#testing-with-mote -testPlutipContracts - :: PlutipConfig - -> TestPlanM ContractTest Unit - -> TestPlanM (Aff Unit) Unit -testPlutipContracts plutipCfg tp = do - -- Modify tests to pluck out parts of a single combined distribution - ContractTestPlan runContractTestPlan <- lift $ execDistribution tp - runContractTestPlan \distr tests -> do - cleanupRef <- liftEffect $ Ref.new mempty - -- Sets a single Mote bracket at the top level, it will be run for all - -- immediate tests and groups - bracket (startPlutipContractEnv plutipCfg distr cleanupRef) - (runCleanup cleanupRef) - $ flip mapTest tests \test { env, wallets, printLogs, clearLogs } -> do - whenError printLogs (runContractInEnv env (test wallets)) - clearLogs - where - -- `MoteT`'s bracket doesn't support supplying the constructed resource into - -- the main action, so we use a `Ref` to store and read the result. - bracket - :: forall (a :: Type) (b :: Type) - . Aff a - -> Aff Unit - -> TestPlanM (a -> Aff b) Unit - -> TestPlanM (Aff b) Unit - bracket before' after' act = do - resultRef <- liftEffect $ Ref.new (Left $ error "Plutip not initialized") - let - before = do - res <- try $ before' - liftEffect $ Ref.write res resultRef - pure res - after = const $ after' - Mote.bracket { before, after } $ flip mapTest act \t -> do - result <- liftEffect $ Ref.read resultRef >>= liftEither - t result - -runCleanup :: Ref (Array (Aff Unit)) -> Aff Unit -runCleanup cleanupRef = do - cleanups <- liftEffect $ Ref.read cleanupRef - sequence_ (try <$> cleanups) - --- Similar to `catchError` but preserves the error -whenError :: forall (a :: Type). Aff Unit -> Aff a -> Aff a -whenError whenErrorAction action = do - res <- try action - when (isLeft res) whenErrorAction - liftEither res - --- | Lifts the UTxO distributions of each test out of Mote, into a combined --- | distribution. Adapts the tests to pick their distribution out of the --- | combined distribution. --- | NOTE: Skipped tests still have their distribution generated. --- | This is the current method of constructing all the wallets with required distributions --- | in one go during Plutip startup. -execDistribution :: TestPlanM ContractTest Unit -> Aff ContractTestPlan -execDistribution (MoteT mote) = execWriterT mote <#> go - where - -- Recursively go over the tree of test `Description`s and construct a `ContractTestPlan` callback. - -- When run the `ContractTestPlan` will reconstruct the whole `MoteT` value passed to `execDistribution` - -- via similar writer effects (plus combining distributions) which append test descriptions - -- or wrap them in a group. - go :: Array (Description Aff ContractTest) -> ContractTestPlan - go = flip execState emptyContractTestPlan <<< traverse_ case _ of - Test rm { bracket, label, value: ContractTest runTest } -> - runTest \distr test -> do - addTests distr $ MoteT - (tell [ Test rm { bracket, label, value: test } ]) - Group rm { bracket, label, value } -> do - let ContractTestPlan runGroupPlan = go value - runGroupPlan \distr tests -> - addTests distr $ over MoteT - (censor (pure <<< Group rm <<< { bracket, label, value: _ })) - tests - - -- This function is used by `go` for iteratively adding Mote tests (internally Writer monad actions) - -- to the `ContractTestPlan` in the State monad _and_ for combining UTxO distributions used by tests. - -- Given a distribution and tests (a MoteT value) this runs a `ContractTestPlan`, i.e. passes its - -- stored distribution and tests to our handler, and then makes a new `ContractTestPlan`, but this time - -- storing a tuple of stored and passed distributions and also storing a pair of Mote tests, modifying - -- the previously stored tests to use the first distribution, and the passed tests the second distribution - -- - -- `go` starts at the top of the test tree and step-by-step constructs a big `ContractTestPlan` which - -- stores distributions of all inner tests tupled together and tests from the original test tree, which - -- know how to get their distribution out of the big tuple. - addTests - :: forall (distr :: Type) (wallets :: Type) - . ContractTestPlanHandler distr wallets (State ContractTestPlan Unit) - addTests distr tests = do - modify_ \(ContractTestPlan runContractTestPlan) -> runContractTestPlan - \distr' tests' -> ContractTestPlan \h -> h (distr' /\ distr) do - mapTest (_ <<< fst) tests' - mapTest (_ <<< snd) tests - - -- Start with an empty plan, which passes an empty distribution - -- and an empty array of test `Description`s to the function that - -- will run tests. - emptyContractTestPlan :: ContractTestPlan - emptyContractTestPlan = ContractTestPlan \h -> h unit (pure unit) - --- | Provide a `ContractEnv` connected to Plutip. --- | Can be used to run multiple `Contract`s using `runContractInEnv`. --- | Resources which are allocated in the `Aff` computation must be de-allocated --- | via the `Ref (Array (Aff Unit))` parameter, even if the computation did not --- | succesfully complete. --- Startup is implemented sequentially, rather than with nested `Aff.bracket`, --- to allow non-`Aff` computations to occur between setup and cleanup. -startPlutipContractEnv - :: forall (distr :: Type) (wallets :: Type) - . UtxoDistribution distr wallets - => PlutipConfig - -> distr - -> Ref (Array (Aff Unit)) - -> Aff - { env :: ContractEnv - , wallets :: wallets - , printLogs :: Aff Unit - , clearLogs :: Aff Unit - } -startPlutipContractEnv plutipCfg distr cleanupRef = do - configCheck plutipCfg - tryWithReport startPlutipServer' "Could not start Plutip server" - (ourKey /\ response) <- tryWithReport startPlutipCluster' - "Could not start Plutip cluster" - tryWithReport (startOgmios' response) "Could not start Ogmios" - tryWithReport (startKupo' response) "Could not start Kupo" - { env, printLogs, clearLogs } <- mkContractEnv' - wallets <- mkWallets' env ourKey response - pure - { env - , wallets - , printLogs - , clearLogs - } - where - tryWithReport - :: forall (a :: Type) - . Aff a - -> String - -> Aff a - tryWithReport what prefix = do - result <- try what - case result of - Left err -> throwError $ error $ prefix <> ": " <> message err - Right result' -> pure result' - - -- Similar to `Aff.bracket`, except cleanup is pushed onto a stack to be run - -- later. - bracket - :: forall (a :: Type) (b :: Type) - . Aff a - -> (a -> Aff Unit) - -> (a -> Aff b) - -> Aff b - bracket before after action = do - Aff.bracket - before - (\res -> liftEffect $ Ref.modify_ ([ after res ] <> _) cleanupRef) - action - - startPlutipServer' :: Aff Unit - startPlutipServer' = - bracket (startPlutipServer plutipCfg) - (stopChildProcessWithPort plutipCfg.port) - (const $ checkPlutipServer plutipCfg) - - startPlutipCluster' - :: Aff (PrivatePaymentKey /\ ClusterStartupParameters) - startPlutipCluster' = do - let - distrArray = - encodeDistribution $ - ourInitialUtxos (encodeDistribution distr) /\ - distr - for_ distrArray $ traverse_ \n -> when (n < BigInt.fromInt 1_000_000) do - liftEffect $ throw $ "UTxO is too low: " <> BigInt.toString n <> - ", must be at least 1_000_000 Lovelace" - bracket - (startPlutipCluster plutipCfg distrArray) - (const $ void $ stopPlutipCluster plutipCfg) - pure - - startOgmios' :: ClusterStartupParameters -> Aff Unit - startOgmios' response = - bracket (startOgmios plutipCfg response) - (stopChildProcessWithPort plutipCfg.ogmiosConfig.port) - (const $ pure unit) - - startKupo' :: ClusterStartupParameters -> Aff Unit - startKupo' response = - bracket (startKupo plutipCfg response) - (stopChildProcessWithPortAndRemoveOnSignal plutipCfg.kupoConfig.port) - \(process /\ workdir /\ _) -> do - liftEffect $ cleanupTmpDir process workdir - pure unit - - mkWallets' - :: ContractEnv - -> PrivatePaymentKey - -> ClusterStartupParameters - -> Aff wallets - mkWallets' env ourKey response = do - runContractInEnv - env { customLogger = Just (\_ _ -> pure unit) } - do - wallets <- - liftContractM - "Impossible happened: could not decode wallets. Please report as bug" - $ decodeWallets distr (unwrap <$> response.privateKeys) - let walletsArray = keyWallets (Proxy :: Proxy distr) wallets - void $ waitNSlots one - transferFundsFromEnterpriseToBase ourKey walletsArray - pure wallets - - mkContractEnv' - :: Aff - { env :: ContractEnv - , printLogs :: Aff Unit - , clearLogs :: Aff Unit - } - mkContractEnv' | plutipCfg.suppressLogs = do - -- if logs should be suppressed, setup the machinery and continue with - -- the bracket - { addLogEntry, suppressedLogger, printLogs, clearLogs } <- - liftEffect $ setupLogs plutipCfg.logLevel plutipCfg.customLogger - let - configLogger = Just $ map liftEffect <<< addLogEntry - - bracket - ( mkClusterContractEnv - plutipCfg { customLogger = configLogger } - suppressedLogger - configLogger - ) - stopContractEnv - \env -> pure - { env - , printLogs: liftEffect printLogs - , clearLogs: liftEffect clearLogs - } - mkContractEnv' = - -- otherwise, proceed with the env setup and provide a normal logger - bracket - ( mkClusterContractEnv plutipCfg - (mkLogger plutipCfg.logLevel plutipCfg.customLogger) - plutipCfg.customLogger - ) - stopContractEnv - \env -> pure - { env - , printLogs: pure unit - , clearLogs: pure unit - } - --- | Throw an exception if `PlutipConfig` contains ports that are occupied. -configCheck :: PlutipConfig -> Aff Unit -configCheck cfg = do - let - services :: Array (UInt /\ String) - services = - [ cfg.port /\ "plutip-server" - , cfg.ogmiosConfig.port /\ "ogmios" - , cfg.kupoConfig.port /\ "kupo" - ] - occupiedServices <- Array.catMaybes <$> for services \(port /\ service) -> do - isPortAvailable port <#> if _ then Nothing else Just (port /\ service) - unless (Array.null occupiedServices) do - liftEffect $ throw $ - "Unable to run the following services, because the ports are occupied:\ - \\n" <> foldMap printServiceEntry occupiedServices - where - printServiceEntry :: UInt /\ String -> String - printServiceEntry (port /\ service) = - "- " <> service <> " (port: " <> show (UInt.toInt port) <> ")\n" - --- | Start the plutip cluster, initializing the state with the given --- | UTxO distribution. Also initializes an extra payment key (aka --- | `ourKey`) with some UTxOs for use with further plutip --- | setup. `ourKey` has funds proportional to the total amount of the --- | UTxOs in the passed distribution, so it can be used to handle --- | transaction fees. -startPlutipCluster - :: PlutipConfig - -> InitialUTxODistribution - -> Aff (PrivatePaymentKey /\ ClusterStartupParameters) -startPlutipCluster cfg keysToGenerate = do - let - url = mkServerEndpointUrl cfg "start" - -- TODO: Non-default values for `slotLength` and `epochSize` break staking - -- rewards, see https://github.com/mlabs-haskell/plutip/issues/149 - epochSize = fromMaybe (UInt.fromInt 80) cfg.clusterConfig.epochSize - res <- do - response <- liftAff - ( Affjax.request - Affjax.defaultRequest - { content = Just - $ RequestBody.String - $ stringifyAeson - $ encodeAeson - $ ClusterStartupRequest - { keysToGenerate - , epochSize - , slotLength: cfg.clusterConfig.slotLength - , maxTxSize: cfg.clusterConfig.maxTxSize - , raiseExUnitsToMax: cfg.clusterConfig.raiseExUnitsToMax - } - , responseFormat = Affjax.ResponseFormat.string - , headers = [ Header.ContentType (wrap "application/json") ] - , url = url - , method = Left Method.POST - } - ) - pure $ response # either - (Left <<< ClientHttpError) - \{ body } -> lmap (ClientDecodeJsonError body) - $ (decodeAeson <=< parseJsonStringToAeson) body - either (liftEffect <<< throw <<< pprintClientError) pure res >>= - case _ of - ClusterStartupFailure reason -> do - liftEffect $ throw $ - "Failed to start up cluster. Reason: " <> show reason - ClusterStartupSuccess response@{ privateKeys } -> - case Array.uncons privateKeys of - Nothing -> - liftEffect $ throw $ - "Impossible happened: insufficient private keys provided by plutip. Please report as bug." - Just { head: PrivateKeyResponse ourKey, tail } -> - pure $ PrivatePaymentKey ourKey /\ response { privateKeys = tail } - --- | Calculate the initial UTxOs needed for `ourKey` to cover --- | transaction costs for the given initial distribution -ourInitialUtxos :: InitialUTxODistribution -> InitialUTxOs -ourInitialUtxos utxoDistribution = - let - total = Array.foldr (sum >>> add) zero utxoDistribution - in - [ -- Take the total value of the UTxOs and add some extra on top - -- of it to cover the possible transaction fees. Also make sure - -- we don't request a 0 ada UTxO - total + BigInt.fromInt 1_000_000_000 - ] - -stopPlutipCluster :: PlutipConfig -> Aff StopClusterResponse -stopPlutipCluster cfg = do - let url = mkServerEndpointUrl cfg "stop" - res <- do - response <- liftAff - ( Affjax.request - Affjax.defaultRequest - { content = Just - $ RequestBody.String - $ stringifyAeson - $ encodeAeson - $ StopClusterRequest - , responseFormat = Affjax.ResponseFormat.string - , headers = [ Header.ContentType (wrap "application/json") ] - , url = url - , method = Left Method.POST - } - ) - pure $ response # either - (Left <<< ClientHttpError) - \{ body } -> lmap (ClientDecodeJsonError body) - $ (decodeAeson <=< parseJsonStringToAeson) - body - either (liftEffect <<< throw <<< show) pure res - -startOgmios :: PlutipConfig -> ClusterStartupParameters -> Aff ManagedProcess -startOgmios cfg params = do - spawn "ogmios" ogmiosArgs defaultSpawnOptions - $ Just - $ String.indexOf (Pattern "networkParameters") - >>> maybe NoOp (const Success) - where - ogmiosArgs :: Array String - ogmiosArgs = - [ "--host" - , cfg.ogmiosConfig.host - , "--port" - , UInt.toString cfg.ogmiosConfig.port - , "--node-socket" - , params.nodeSocketPath - , "--node-config" - , params.nodeConfigPath - , "--include-transaction-cbor" - ] - -startKupo - :: PlutipConfig - -> ClusterStartupParameters - -> Aff (ManagedProcess /\ String /\ OnSignalRef) -startKupo cfg params = do - tmpDir <- liftEffect tmpdir - let - workdir = tmpDir <> "kupo-db" - testClusterDir = (dirname <<< dirname) params.nodeConfigPath - liftEffect do - workdirExists <- FSSync.exists workdir - unless workdirExists (FSSync.mkdir workdir) - childProcess <- spawnKupoProcess workdir - -- here we also set the SIGINT handler for the whole process - sig <- liftEffect $ cleanupOnSigint workdir testClusterDir - pure (childProcess /\ workdir /\ sig) - where - spawnKupoProcess :: FilePath -> Aff ManagedProcess - spawnKupoProcess workdir = - spawn "kupo" (kupoArgs workdir) defaultSpawnOptions $ - Just (String.indexOf outputString >>> maybe NoOp (const Success)) - where - outputString :: Pattern - outputString = Pattern "ConfigurationCheckpointsForIntersection" - - kupoArgs :: FilePath -> Array String - kupoArgs workdir = - [ "--match" - , "*/*" - , "--since" - , "origin" - , "--workdir" - , workdir - , "--host" - , cfg.kupoConfig.host - , "--port" - , UInt.toString cfg.kupoConfig.port - , "--node-socket" - , params.nodeSocketPath - , "--node-config" - , params.nodeConfigPath - ] - -startPlutipServer :: PlutipConfig -> Aff ManagedProcess -startPlutipServer cfg = do - spawn "plutip-server" [ "-p", UInt.toString cfg.port ] - defaultSpawnOptions - Nothing - -checkPlutipServer :: PlutipConfig -> Aff Unit -checkPlutipServer cfg = do - -- We are trying to call stopPlutipCluster endpoint to ensure that - -- `plutip-server` has started. - void - $ recovering defaultRetryPolicy - ([ \_ _ -> pure true ]) - $ const - $ stopPlutipCluster cfg - --- | Kill a process and wait for it to stop listening on a specific port. -stopChildProcessWithPort :: UInt -> ManagedProcess -> Aff Unit -stopChildProcessWithPort port childProcess = do - stop childProcess - void $ recovering defaultRetryPolicy ([ \_ _ -> pure true ]) - \_ -> do - isAvailable <- isPortAvailable port - unless isAvailable do - liftEffect $ throw "retry" - -stopChildProcessWithPortAndRemoveOnSignal - :: UInt -> (ManagedProcess /\ String /\ OnSignalRef) -> Aff Unit -stopChildProcessWithPortAndRemoveOnSignal port (childProcess /\ _ /\ sig) = do - stop $ childProcess - void $ recovering defaultRetryPolicy ([ \_ _ -> pure true ]) - \_ -> do - isAvailable <- isPortAvailable port - unless isAvailable do - liftEffect $ throw "retry" - liftEffect $ removeOnSignal sig - -mkClusterContractEnv - :: PlutipConfig - -> Logger - -> Maybe (LogLevel -> Message -> Aff Unit) - -> Aff ContractEnv -mkClusterContractEnv plutipCfg logger customLogger = do - usedTxOuts <- newUsedTxOuts - backend <- buildBackend logger $ mkCtlBackendParams - { ogmiosConfig: plutipCfg.ogmiosConfig - , kupoConfig: plutipCfg.kupoConfig - } - ledgerConstants <- getLedgerConstants - plutipCfg { customLogger = customLogger } - backend - backendKnownTxs <- liftEffect $ Ref.new Set.empty - pure - { backend - , handle: mkQueryHandle plutipCfg backend - , networkId: MainnetId - , logLevel: plutipCfg.logLevel - , customLogger: customLogger - , suppressLogs: plutipCfg.suppressLogs - , hooks: emptyHooks - , wallet: Nothing - , usedTxOuts - , ledgerConstants - -- timeParams have no effect when KeyWallet is used - , timeParams: defaultTimeParams - , synchronizationParams: defaultSynchronizationParams - , knownTxs: { backend: backendKnownTxs } - } - -defaultRetryPolicy :: RetryPolicy -defaultRetryPolicy = limitRetriesByCumulativeDelay (Milliseconds 3000.00) $ - constantDelay (Milliseconds 100.0) - -mkServerEndpointUrl :: PlutipConfig -> String -> String -mkServerEndpointUrl cfg path = do - "http://" <> cfg.host <> ":" <> UInt.toString cfg.port <> path diff --git a/src/Internal/Plutip/Spawn.js b/src/Internal/Plutip/Spawn.js deleted file mode 100644 index 93cba32e6c..0000000000 --- a/src/Internal/Plutip/Spawn.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; - -export function clearLineHandler(readline) { - return () => { - readline.removeAllListeners("line"); - }; -} - -import fs from "fs"; - -export function _rmdirSync(path) { - return () => fs.rmSync(path, { recursive: true }); -} - -export function removeOnSignal({ signal, callback }) { - return () => { - process.removeListener(signal, callback); - }; -} - -export function onSignalImpl(signal) { - return callback => () => { - process.on(signal, callback); - return { signal, callback }; - }; -} diff --git a/src/Internal/Plutip/Types.purs b/src/Internal/Plutip/Types.purs deleted file mode 100644 index d2f7ba78c6..0000000000 --- a/src/Internal/Plutip/Types.purs +++ /dev/null @@ -1,194 +0,0 @@ -module Ctl.Internal.Plutip.Types - ( ClusterStartupParameters - , ErrorMessage - , FilePath - , PlutipConfig - , ClusterStartupRequest(ClusterStartupRequest) - , PrivateKeyResponse(PrivateKeyResponse) - , ClusterStartupFailureReason - ( ClusterIsRunningAlready - , NegativeLovelaces - , NodeConfigNotFound - ) - , StartClusterResponse - ( ClusterStartupFailure - , ClusterStartupSuccess - ) - , StopClusterRequest(StopClusterRequest) - , StopClusterResponse(StopClusterSuccess, StopClusterFailure) - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch, UnexpectedValue) - , decodeAeson - , encodeAeson - , finiteNumber - , toStringifiedNumbersJson - , (.:) - ) -import Ctl.Internal.Contract.Hooks (Hooks) -import Ctl.Internal.Deserialization.Keys (privateKeyFromBytes) -import Ctl.Internal.Serialization.Types (PrivateKey) -import Ctl.Internal.ServerConfig (ServerConfig) -import Ctl.Internal.Test.UtxoDistribution (InitialUTxODistribution) -import Ctl.Internal.Types.ByteArray (hexToByteArray) -import Ctl.Internal.Types.RawBytes (RawBytes(RawBytes)) -import Data.Either (Either(Left), note) -import Data.Generic.Rep (class Generic) -import Data.Log.Level (LogLevel) -import Data.Log.Message (Message) -import Data.Maybe (Maybe, fromJust) -import Data.Newtype (class Newtype) -import Data.Show.Generic (genericShow) -import Data.Time.Duration (Seconds(Seconds)) -import Data.UInt (UInt) -import Effect.Aff (Aff) -import Partial.Unsafe (unsafePartial) - --- | A config that is used to run tests on Plutip clusters. --- | Note that the test suite starts the services on the specified ports. --- | It does not expect them to be running. -type PlutipConfig = - { host :: String - , port :: UInt - , logLevel :: LogLevel - -- Server configs are used to deploy the corresponding services: - , ogmiosConfig :: ServerConfig - , kupoConfig :: ServerConfig - , customLogger :: Maybe (LogLevel -> Message -> Aff Unit) - , suppressLogs :: Boolean - , hooks :: Hooks - , clusterConfig :: - { slotLength :: Seconds - , epochSize :: Maybe UInt - , maxTxSize :: Maybe UInt - , raiseExUnitsToMax :: Boolean - } - } - -type FilePath = String - -type ErrorMessage = String - -newtype ClusterStartupRequest = ClusterStartupRequest - { keysToGenerate :: InitialUTxODistribution - , epochSize :: UInt - , slotLength :: Seconds - , maxTxSize :: Maybe UInt - , raiseExUnitsToMax :: Boolean - } - -instance EncodeAeson ClusterStartupRequest where - encodeAeson - ( ClusterStartupRequest - { keysToGenerate - , epochSize - , slotLength: Seconds slotLength - , maxTxSize - , raiseExUnitsToMax - } - ) = encodeAeson - { keysToGenerate - , epochSize - , slotLength: unsafePartial $ fromJust $ finiteNumber slotLength - , maxTxSize - , raiseExUnitsToMax - } - -newtype PrivateKeyResponse = PrivateKeyResponse PrivateKey - -derive instance Newtype PrivateKeyResponse _ -derive instance Generic PrivateKeyResponse _ - -instance Show PrivateKeyResponse where - show _ = "(PrivateKeyResponse \"\")" - -instance DecodeAeson PrivateKeyResponse where - decodeAeson json = do - cborStr <- decodeAeson json - cborBytes <- note err $ hexToByteArray cborStr - PrivateKeyResponse <$> note err (privateKeyFromBytes (RawBytes cborBytes)) - where - err :: JsonDecodeError - err = TypeMismatch "PrivateKey" - -type ClusterStartupParameters = - { privateKeys :: Array PrivateKeyResponse - , nodeSocketPath :: FilePath - , nodeConfigPath :: FilePath - , keysDirectory :: FilePath - } - -data ClusterStartupFailureReason - = ClusterIsRunningAlready - | NegativeLovelaces - | NodeConfigNotFound - -derive instance Generic ClusterStartupFailureReason _ - -instance Show ClusterStartupFailureReason where - show = genericShow - -instance DecodeAeson ClusterStartupFailureReason where - decodeAeson aeson = do - decodeAeson aeson >>= case _ of - "ClusterIsRunningAlready" -> do - pure ClusterIsRunningAlready - "NegativeLovelaces" -> pure NegativeLovelaces - "NodeConfigNotFound" -> pure NodeConfigNotFound - _ -> do - Left (UnexpectedValue (toStringifiedNumbersJson aeson)) - -data StartClusterResponse - = ClusterStartupFailure ClusterStartupFailureReason - | ClusterStartupSuccess ClusterStartupParameters - -derive instance Generic StartClusterResponse _ - -instance Show StartClusterResponse where - show = genericShow - -instance DecodeAeson StartClusterResponse where - decodeAeson aeson = do - obj <- decodeAeson aeson - obj .: "tag" >>= case _ of - "ClusterStartupSuccess" -> do - contents <- obj .: "contents" - ClusterStartupSuccess <$> decodeAeson contents - "ClusterStartupFailure" -> do - failure <- obj .: "contents" - ClusterStartupFailure <$> decodeAeson failure - _ -> do - Left (UnexpectedValue (toStringifiedNumbersJson aeson)) - -data StopClusterRequest = StopClusterRequest - -derive instance Generic StopClusterRequest _ - -instance Show StopClusterRequest where - show = genericShow - -instance EncodeAeson StopClusterRequest where - encodeAeson _ = encodeAeson ([] :: Array Int) - -data StopClusterResponse = StopClusterSuccess | StopClusterFailure ErrorMessage - -derive instance Generic StopClusterResponse _ - -instance Show StopClusterResponse where - show = genericShow - -instance DecodeAeson StopClusterResponse where - decodeAeson aeson = do - obj <- decodeAeson aeson - obj .: "tag" >>= case _ of - "StopClusterSuccess" -> pure StopClusterSuccess - "StopClusterFailure" -> do - failure <- obj .: "contents" - StopClusterFailure <$> decodeAeson failure - _ -> do - Left (UnexpectedValue (toStringifiedNumbersJson aeson)) diff --git a/src/Internal/Plutip/Utils.js b/src/Internal/Plutip/Utils.js deleted file mode 100644 index ab594520c6..0000000000 --- a/src/Internal/Plutip/Utils.js +++ /dev/null @@ -1,5 +0,0 @@ -import os from "os"; - -export function tmpdir() { - return os.tmpdir(); -} diff --git a/src/Internal/Plutip/Utils.purs b/src/Internal/Plutip/Utils.purs deleted file mode 100644 index 610390fabf..0000000000 --- a/src/Internal/Plutip/Utils.purs +++ /dev/null @@ -1,9 +0,0 @@ -module Ctl.Internal.Plutip.Utils - ( tmpdir - ) where - -import Effect (Effect) - --- TODO: remove this function when PS bindings for os.tmpdir are available. --- https://github.com/Plutonomicon/cardano-transaction-lib/issues/726 -foreign import tmpdir :: Effect String diff --git a/src/Internal/Plutus/Conversion.purs b/src/Internal/Plutus/Conversion.purs deleted file mode 100644 index 993ae9f8d6..0000000000 --- a/src/Internal/Plutus/Conversion.purs +++ /dev/null @@ -1,166 +0,0 @@ --- | A module for performing conversions between various types and --- | their Plutus representations. --- | --- | Conversion functions come in pairs and must be named as follows: --- | `fromPlutusType` and `toPlutusType`, where `Type` is to --- | be replaced by the name of the actual type. -module Ctl.Internal.Plutus.Conversion - ( - -- Plutus Address <-> CSL Address - module Conversion.Address - - -- Plutus Value <-> Types.Value - , module Conversion.Value - - -- Plutus Coin <-> Cardano Coin - , fromPlutusCoin - , toPlutusCoin - - -- Plutus TransactionOutput <-> Cardano TransactionOutput - , fromPlutusTxOutput - , toPlutusTxOutput - - -- Plutus TransactionOutputWithRefScript <-> Cardano TransactionOutput - , fromPlutusTxOutputWithRefScript - , toPlutusTxOutputWithRefScript - - -- Plutus TransactionUnspentOutput <-> Cardano TransactionUnspentOutput - , fromPlutusTxUnspentOutput - , toPlutusTxUnspentOutput - - -- Plutus UtxoMap <-> Cardano UtxoMap - , fromPlutusUtxoMap - , toPlutusUtxoMap - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.ScriptRef (ScriptRef) -import Ctl.Internal.Cardano.Types.Transaction (TransactionOutput, UtxoMap) as Cardano -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput - ) as Cardano -import Ctl.Internal.Cardano.Types.Value (Coin) as Cardano -import Ctl.Internal.Hashing (scriptRefHash) -import Ctl.Internal.Plutus.Conversion.Address - ( fromPlutusAddress - , fromPlutusAddressWithNetworkTag - , toPlutusAddress - , toPlutusAddressWithNetworkTag - ) as Conversion.Address -import Ctl.Internal.Plutus.Conversion.Address - ( fromPlutusAddress - , toPlutusAddress - ) -import Ctl.Internal.Plutus.Conversion.Value (fromPlutusValue, toPlutusValue) -import Ctl.Internal.Plutus.Conversion.Value (fromPlutusValue, toPlutusValue) as Conversion.Value -import Ctl.Internal.Plutus.Types.Transaction - ( TransactionOutput - , TransactionOutputWithRefScript(TransactionOutputWithRefScript) - , UtxoMap - ) as Plutus -import Ctl.Internal.Plutus.Types.TransactionUnspentOutput - ( TransactionUnspentOutput - ) as Plutus -import Ctl.Internal.Plutus.Types.Value (Coin) as Plutus -import Ctl.Internal.Serialization.Address (NetworkId) -import Data.Maybe (Maybe) -import Data.Newtype (unwrap, wrap) -import Data.Traversable (traverse) - --------------------------------------------------------------------------------- --- Plutus Coin <-> Cardano Coin --------------------------------------------------------------------------------- - -fromPlutusCoin :: Plutus.Coin -> Cardano.Coin -fromPlutusCoin = wrap <<< unwrap - -toPlutusCoin :: Cardano.Coin -> Plutus.Coin -toPlutusCoin = wrap <<< unwrap - --------------------------------------------------------------------------------- --- Plutus TransactionOutput <-> Cardano TransactionOutput --------------------------------------------------------------------------------- - -fromPlutusTxOutput - :: NetworkId - -> Maybe ScriptRef - -> Plutus.TransactionOutput - -> Cardano.TransactionOutput -fromPlutusTxOutput networkId scriptRef plutusTxOut = - let - rec = unwrap plutusTxOut - in - wrap - { address: fromPlutusAddress networkId rec.address - , amount: fromPlutusValue rec.amount - , datum: rec.datum - , scriptRef - } - -toPlutusTxOutput - :: Cardano.TransactionOutput -> Maybe Plutus.TransactionOutput -toPlutusTxOutput cardanoTxOut = do - let rec = unwrap cardanoTxOut - address <- toPlutusAddress rec.address - let - amount = toPlutusValue rec.amount - referenceScript = scriptRefHash <$> rec.scriptRef - pure $ wrap - { address, amount, datum: rec.datum, referenceScript } - --------------------------------------------------------------------------------- --- Plutus TransactionOutputWithRefScript <-> Cardano TransactionOutput --------------------------------------------------------------------------------- - -fromPlutusTxOutputWithRefScript - :: NetworkId - -> Plutus.TransactionOutputWithRefScript - -> Cardano.TransactionOutput -fromPlutusTxOutputWithRefScript - networkId - (Plutus.TransactionOutputWithRefScript { output, scriptRef }) = - fromPlutusTxOutput networkId scriptRef output - -toPlutusTxOutputWithRefScript - :: Cardano.TransactionOutput -> Maybe Plutus.TransactionOutputWithRefScript -toPlutusTxOutputWithRefScript cTxOutput = - toPlutusTxOutput cTxOutput - <#> wrap <<< { output: _, scriptRef: (unwrap cTxOutput).scriptRef } - --------------------------------------------------------------------------------- --- Plutus TransactionUnspentOutput <-> Cardano TransactionUnspentOutput --------------------------------------------------------------------------------- - -fromPlutusTxUnspentOutput - :: NetworkId - -> Plutus.TransactionUnspentOutput - -> Cardano.TransactionUnspentOutput -fromPlutusTxUnspentOutput networkId txUnspentOutput = - let - rec = unwrap txUnspentOutput - in - wrap - { input: rec.input - , output: fromPlutusTxOutputWithRefScript networkId rec.output - } - -toPlutusTxUnspentOutput - :: Cardano.TransactionUnspentOutput - -> Maybe Plutus.TransactionUnspentOutput -toPlutusTxUnspentOutput txUnspentOutput = do - let rec = unwrap txUnspentOutput - output <- toPlutusTxOutputWithRefScript rec.output - pure $ wrap { input: rec.input, output } - --------------------------------------------------------------------------------- --- Plutus UtxoMap <-> Cardano UtxoMap --------------------------------------------------------------------------------- - -fromPlutusUtxoMap :: NetworkId -> Plutus.UtxoMap -> Cardano.UtxoMap -fromPlutusUtxoMap networkId = - map (fromPlutusTxOutputWithRefScript networkId) - -toPlutusUtxoMap :: Cardano.UtxoMap -> Maybe Plutus.UtxoMap -toPlutusUtxoMap = - traverse toPlutusTxOutputWithRefScript diff --git a/src/Internal/Plutus/Conversion/Address.purs b/src/Internal/Plutus/Conversion/Address.purs deleted file mode 100644 index a2cc5e18b8..0000000000 --- a/src/Internal/Plutus/Conversion/Address.purs +++ /dev/null @@ -1,203 +0,0 @@ -module Ctl.Internal.Plutus.Conversion.Address - ( fromPlutusAddress - , fromPlutusAddressWithNetworkTag - , toPlutusAddress - , toPlutusAddressWithNetworkTag - ) where - -import Prelude - -import Control.Alt ((<|>)) -import Ctl.Internal.Plutus.Types.Address - ( Address(Address) - , AddressWithNetworkTag(AddressWithNetworkTag) - ) as Plutus -import Ctl.Internal.Plutus.Types.Credential - ( Credential(PubKeyCredential, ScriptCredential) - , StakingCredential(StakingHash, StakingPtr) - ) -import Ctl.Internal.Serialization.Address - ( Address - , NetworkId - , Pointer - , StakeCredential - , addressNetworkId - , baseAddressDelegationCred - , baseAddressFromAddress - , baseAddressPaymentCred - , baseAddressToAddress - , enterpriseAddressFromAddress - , enterpriseAddressPaymentCred - , enterpriseAddressToAddress - , paymentKeyHashEnterpriseAddress - , paymentKeyHashPointerAddress - , paymentKeyHashScriptHashAddress - , paymentKeyHashStakeKeyHashAddress - , pointerAddressFromAddress - , pointerAddressPaymentCred - , pointerAddressStakePointer - , pointerAddressToAddress - , scriptHashEnterpriseAddress - , scriptHashPointerAddress - , scriptHashScriptHashAddress - , scriptHashStakeKeyHashAddress - , withStakeCredential - ) as Csl -import Ctl.Internal.Types.PubKeyHash (PubKeyHash(PubKeyHash)) -import Ctl.Internal.Types.Scripts (ValidatorHash(ValidatorHash)) -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (unwrap, wrap) - --------------------------------------------------------------------------------- --- Plutus Address -> CSL Address --------------------------------------------------------------------------------- - -fromPlutusAddressWithNetworkTag - :: Plutus.AddressWithNetworkTag -> Csl.Address -fromPlutusAddressWithNetworkTag (Plutus.AddressWithNetworkTag rec) = - fromPlutusAddress rec.networkId rec.address - --- | Builds a CSL-level address from a Plutus address. --- | CIP-0019: https://cips.cardano.org/cips/cip19/ -fromPlutusAddress - :: Csl.NetworkId -> Plutus.Address -> Csl.Address -fromPlutusAddress - networkId - (Plutus.Address { addressCredential, addressStakingCredential }) = - case addressCredential, addressStakingCredential of - -- %b0000 | network tag | key hash | key hash - PubKeyCredential (PubKeyHash pkh), - Just (StakingHash (PubKeyCredential (PubKeyHash skh))) -> - Csl.baseAddressToAddress $ - Csl.paymentKeyHashStakeKeyHashAddress networkId pkh skh - - -- %b0001 | network tag | script hash | key hash - ScriptCredential (ValidatorHash sh), - Just (StakingHash (PubKeyCredential (PubKeyHash skh))) -> - Csl.baseAddressToAddress $ - Csl.scriptHashStakeKeyHashAddress networkId sh skh - - -- %b0010 | network tag | key hash | script hash - PubKeyCredential (PubKeyHash pkh), - Just (StakingHash (ScriptCredential (ValidatorHash sh))) -> - Csl.baseAddressToAddress $ - Csl.paymentKeyHashScriptHashAddress networkId pkh sh - - -- %b0011 | network tag | script hash | script hash - ScriptCredential (ValidatorHash sh), - Just (StakingHash (ScriptCredential (ValidatorHash sh'))) -> - Csl.baseAddressToAddress $ - Csl.scriptHashScriptHashAddress networkId sh sh' - - -- %b0100 | network tag | key hash | pointer - PubKeyCredential (PubKeyHash pkh), Just (StakingPtr ptr) -> - Csl.pointerAddressToAddress $ - Csl.paymentKeyHashPointerAddress networkId pkh ptr - - -- %b0101 | network tag | script hash | pointer - ScriptCredential (ValidatorHash sh), Just (StakingPtr ptr) -> - Csl.pointerAddressToAddress $ - Csl.scriptHashPointerAddress networkId sh ptr - - -- %b0110 | network tag | key hash - PubKeyCredential (PubKeyHash pkh), Nothing -> - Csl.enterpriseAddressToAddress $ - Csl.paymentKeyHashEnterpriseAddress networkId pkh - - -- %b0111 | network tag | script hash - ScriptCredential (ValidatorHash sh), Nothing -> - Csl.enterpriseAddressToAddress $ - Csl.scriptHashEnterpriseAddress networkId sh - --------------------------------------------------------------------------------- --- CSL Address -> Plutus Address --------------------------------------------------------------------------------- - --- | Attempts to build a Plutus address from a CSL-level address --- | discarding the network tag. --- | CIP-0019: https://cips.cardano.org/cips/cip19/ -toPlutusAddress - :: Csl.Address -> Maybe Plutus.Address -toPlutusAddress = - map (_.address <<< unwrap) <<< toPlutusAddressWithNetworkTag - --- | Attempts to build a Plutus address from a CSL-level address. --- | CIP-0019: https://cips.cardano.org/cips/cip19/ -toPlutusAddressWithNetworkTag - :: Csl.Address -> Maybe Plutus.AddressWithNetworkTag -toPlutusAddressWithNetworkTag addressCsl = do - let networkId = Csl.addressNetworkId addressCsl - Plutus.AddressWithNetworkTag <<< { address: _, networkId } <$> - ( toPlutusBaseAddress addressCsl - <|> toPlutusPointerAddress addressCsl - <|> toPlutusEnterpriseAddress addressCsl - ) - where - toPlutusBaseAddress - :: Csl.Address -> Maybe Plutus.Address - toPlutusBaseAddress addr = do - baseAddress <- Csl.baseAddressFromAddress addr - let - paymentCred :: Csl.StakeCredential - paymentCred = Csl.baseAddressPaymentCred baseAddress - - delegationCred :: Csl.StakeCredential - delegationCred = Csl.baseAddressDelegationCred baseAddress - - flip Csl.withStakeCredential paymentCred - { onKeyHash: \pkh -> - worker (PubKeyCredential (wrap pkh)) delegationCred - , onScriptHash: \sh -> - worker (ScriptCredential (wrap sh)) delegationCred - } - where - worker - :: Credential -> Csl.StakeCredential -> Maybe Plutus.Address - worker addressCredential delegationCred = - Just $ wrap - { addressCredential - , addressStakingCredential: - flip Csl.withStakeCredential delegationCred - { onKeyHash: \skh -> - Just (StakingHash (PubKeyCredential (wrap skh))) - , onScriptHash: \sh -> - Just (StakingHash (ScriptCredential (wrap sh))) - } - } - - toPlutusPointerAddress - :: Csl.Address -> Maybe Plutus.Address - toPlutusPointerAddress addr = do - pointerAddress <- Csl.pointerAddressFromAddress addr - let - paymentCred :: Csl.StakeCredential - paymentCred = Csl.pointerAddressPaymentCred pointerAddress - - stakePointer :: Csl.Pointer - stakePointer = Csl.pointerAddressStakePointer pointerAddress - - Just $ wrap - { addressCredential: mkAddressCredential paymentCred - , addressStakingCredential: Just (StakingPtr stakePointer) - } - - toPlutusEnterpriseAddress - :: Csl.Address -> Maybe Plutus.Address - toPlutusEnterpriseAddress addr = do - enterpriseAddress <- Csl.enterpriseAddressFromAddress addr - let - paymentCred :: Csl.StakeCredential - paymentCred = Csl.enterpriseAddressPaymentCred enterpriseAddress - - Just $ wrap - { addressCredential: mkAddressCredential paymentCred - , addressStakingCredential: Nothing - } - - mkAddressCredential - :: Csl.StakeCredential -> Credential - mkAddressCredential = - Csl.withStakeCredential - { onKeyHash: PubKeyCredential <<< wrap - , onScriptHash: ScriptCredential <<< wrap - } diff --git a/src/Internal/Plutus/Conversion/Value.purs b/src/Internal/Plutus/Conversion/Value.purs deleted file mode 100644 index d5c7f8ef35..0000000000 --- a/src/Internal/Plutus/Conversion/Value.purs +++ /dev/null @@ -1,81 +0,0 @@ -module Ctl.Internal.Plutus.Conversion.Value - ( fromPlutusValue - , toPlutusValue - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.Value (Coin(Coin), Value(Value)) as Types -import Ctl.Internal.Cardano.Types.Value - ( NonAdaAsset - , flattenNonAdaValue - , getCurrencySymbol - , mkNonAdaAssetsFromTokenMap - , mkValue - ) -import Ctl.Internal.Plutus.Types.AssocMap (lookup) as Plutus.AssocMap -import Ctl.Internal.Plutus.Types.CurrencySymbol (adaSymbol, getCurrencySymbol) as Plutus -import Ctl.Internal.Plutus.Types.Value (Value) as Plutus -import Ctl.Internal.Plutus.Types.Value - ( getValue - , lovelaceValueOf - , singleton' - ) as Plutus.Value -import Ctl.Internal.Types.TokenName (adaToken, getTokenName) -import Data.Array (head, partition) -import Data.Foldable (fold) -import Data.List (List) -import Data.Map (fromFoldable) as Map -import Data.Maybe (fromJust, fromMaybe) -import Data.Newtype (unwrap, wrap) -import Data.Tuple (snd) -import Data.Tuple.Nested ((/\)) -import Partial.Unsafe (unsafePartial) - --- The underlying `Plutus.Types.AssocMap` of `Plutus.Types.Value` doesn't --- have the `Ord` constraint on the keys. Therefore, one should be careful when --- performing conversions between `Value`s, since the ordering of components --- can't be guaranteed. - --------------------------------------------------------------------------------- --- Plutus Value -> Types.Value --------------------------------------------------------------------------------- - -fromPlutusValue :: Plutus.Value -> Types.Value -fromPlutusValue plutusValue = - adaValue <> mkValue mempty nonAdaAssets - where - { adaTokenMap, nonAdaTokenMap } = - (\x -> { adaTokenMap: x.yes, nonAdaTokenMap: x.no }) <<< - partition (\(cs /\ _) -> cs == Plutus.adaSymbol) $ - (unwrap $ Plutus.Value.getValue plutusValue) - - adaValue :: Types.Value - adaValue = flip mkValue mempty <<< wrap <<< fromMaybe zero $ do - adaTokens <- snd <$> head adaTokenMap - Plutus.AssocMap.lookup adaToken adaTokens - - nonAdaAssets :: NonAdaAsset - nonAdaAssets = unsafePartial $ fromJust - $ mkNonAdaAssetsFromTokenMap - $ nonAdaTokenMap <#> \(cs /\ tokens) -> - Plutus.getCurrencySymbol cs /\ Map.fromFoldable (unwrap tokens) - --------------------------------------------------------------------------------- --- Types.Value -> Plutus Value --------------------------------------------------------------------------------- - -toPlutusValue :: Types.Value -> Plutus.Value -toPlutusValue (Types.Value (Types.Coin adaAmount) nonAdaAssets) = - adaValue <> fold nonAdaValues - where - adaValue :: Plutus.Value - adaValue - | adaAmount == zero = mempty - | otherwise = Plutus.Value.lovelaceValueOf adaAmount - - nonAdaValues :: List Plutus.Value - nonAdaValues = - flattenNonAdaValue nonAdaAssets <#> \(cs /\ tn /\ val) -> - unsafePartial fromJust $ - Plutus.Value.singleton' (getCurrencySymbol cs) (getTokenName tn) val diff --git a/src/Internal/Plutus/Types/Address.purs b/src/Internal/Plutus/Types/Address.purs deleted file mode 100644 index 989b1be032..0000000000 --- a/src/Internal/Plutus/Types/Address.purs +++ /dev/null @@ -1,157 +0,0 @@ -module Ctl.Internal.Plutus.Types.Address - ( Address(Address) - , AddressWithNetworkTag(AddressWithNetworkTag) - , class PlutusAddress - , getAddress - , pubKeyHashAddress - , scriptHashAddress - , toPubKeyHash - , toValidatorHash - , toStakingCredential - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , caseAesonObject - , encodeAeson - , (.:) - ) -import Ctl.Internal.FromData (class FromData, genericFromData) -import Ctl.Internal.Plutus.Types.Credential - ( Credential(PubKeyCredential, ScriptCredential) - , StakingCredential(StakingHash) - ) -import Ctl.Internal.Plutus.Types.DataSchema - ( class HasPlutusSchema - , type (:+) - , type (:=) - , type (@@) - , I - , PNil - ) -import Ctl.Internal.Serialization.Address (NetworkId) -import Ctl.Internal.ToData (class ToData, genericToData) -import Ctl.Internal.TypeLevel.Nat (Z) -import Ctl.Internal.Types.PubKeyHash - ( PaymentPubKeyHash(PaymentPubKeyHash) - , PubKeyHash - ) -import Ctl.Internal.Types.Scripts (ValidatorHash) -import Data.Either (Either(Left)) -import Data.Generic.Rep (class Generic) -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Show.Generic (genericShow) - --------------------------------------------------------------------------------- --- Address --------------------------------------------------------------------------------- - -class PlutusAddress (t :: Type) where - getAddress :: t -> Address - -newtype AddressWithNetworkTag = AddressWithNetworkTag - { address :: Address - , networkId :: NetworkId - } - -instance PlutusAddress Address where - getAddress = identity - -instance PlutusAddress AddressWithNetworkTag where - getAddress = _.address <<< unwrap - -derive instance Eq AddressWithNetworkTag -derive instance Newtype AddressWithNetworkTag _ -derive instance Generic AddressWithNetworkTag _ - -instance Show AddressWithNetworkTag where - show = genericShow - --- Taken from https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/Plutus-V1-Ledger-Tx.html#t:Address --- Plutus rev: dbefda30be6490c758aa88b600f5874f12712b3a --- | Address with two kinds of credentials, normal and staking. -newtype Address = Address - { addressCredential :: Credential - , addressStakingCredential :: Maybe StakingCredential - } - -derive instance Eq Address -derive instance Ord Address -derive instance Newtype Address _ -derive instance Generic Address _ - -instance Show Address where - show = genericShow - -instance - HasPlutusSchema - Address - ( "Address" - := - ( "addressCredential" := I Credential :+ "addressStakingCredential" - := I (Maybe StakingCredential) - :+ PNil - ) - @@ Z - :+ PNil - ) - -instance ToData Address where - toData = genericToData - -instance FromData Address where - fromData = genericFromData - -instance DecodeAeson Address where - decodeAeson = caseAesonObject (Left $ TypeMismatch "Expected object") $ - \obj -> do - addressCredential <- obj .: "addressCredential" - addressStakingCredential <- obj .: "addressStakingCredential" - pure $ Address { addressCredential, addressStakingCredential } - -instance EncodeAeson Address where - encodeAeson (Address addr) = encodeAeson addr - --------------------------------------------------------------------------------- --- Useful functions --------------------------------------------------------------------------------- - --- | The address that should be targeted by a transaction output locked --- | by the public key with the given hash. -pubKeyHashAddress :: PaymentPubKeyHash -> Maybe Credential -> Address -pubKeyHashAddress (PaymentPubKeyHash pkh) mbStakeCredential = wrap - { addressCredential: PubKeyCredential pkh - , addressStakingCredential: - map StakingHash mbStakeCredential - } - --- | The address that should be used by a transaction output locked --- | by the given validator script hash. -scriptHashAddress :: ValidatorHash -> Maybe Credential -> Address -scriptHashAddress vh mbStakeCredential = wrap - { addressCredential: ScriptCredential vh - , addressStakingCredential: map StakingHash mbStakeCredential - } - --- | The PubKeyHash of the address (if any). -toPubKeyHash :: Address -> Maybe PubKeyHash -toPubKeyHash addr = - case (unwrap addr).addressCredential of - PubKeyCredential k -> Just k - _ -> Nothing - --- | The validator hash of the address (if any). -toValidatorHash :: Address -> Maybe ValidatorHash -toValidatorHash addr = - case (unwrap addr).addressCredential of - ScriptCredential k -> Just k - _ -> Nothing - --- | The staking credential of an address (if any). -toStakingCredential :: Address -> Maybe StakingCredential -toStakingCredential = _.addressStakingCredential <<< unwrap diff --git a/src/Internal/Plutus/Types/AssocMap.purs b/src/Internal/Plutus/Types/AssocMap.purs deleted file mode 100644 index cb773d6398..0000000000 --- a/src/Internal/Plutus/Types/AssocMap.purs +++ /dev/null @@ -1,250 +0,0 @@ -module Ctl.Internal.Plutus.Types.AssocMap - ( Map(Map) - , delete - , elems - , empty - , filter - , insert - , keys - , lookup - , mapMaybe - , mapMaybeWithKey - , mapThese - , member - , null - , singleton - , union - , unionWith - , values - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , Aeson - , decodeAeson - , encodeAeson - ) -import Ctl.Internal.FromData (class FromData, fromData) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.PlutusData (PlutusData(Map)) as PD -import Data.Array (any, deleteAt, filter, findIndex, mapMaybe, null, singleton) as Array -import Data.Array ((:)) -import Data.Bifunctor (bimap, rmap) -import Data.Bitraversable (rtraverse) -import Data.Foldable - ( class Foldable - , foldMap - , foldlDefault - , foldr - , foldrDefault - ) -import Data.Foldable (lookup) as Foldable -import Data.FoldableWithIndex - ( class FoldableWithIndex - , foldlWithIndexDefault - , foldrWithIndexDefault - ) -import Data.FunctorWithIndex (class FunctorWithIndex) -import Data.Generic.Rep (class Generic) -import Data.Maybe (Maybe(Just, Nothing), isJust) -import Data.Newtype (class Newtype, unwrap) -import Data.Show.Generic (genericShow) -import Data.These (These(Both, That, This), these) -import Data.Traversable (class Traversable, for, sequence, traverse) -import Data.TraversableWithIndex (class TraversableWithIndex) -import Data.Tuple (Tuple(Tuple), fst, snd, uncurry) -import Data.Tuple.Nested (type (/\), (/\)) - --- Taken from local Hoogle server for the Haskell server which uses --- `plutus` rev: 1efbb276ef1a10ca6961d0fd32e6141e9798bd11 --- It looks like Plutus doesn't provide any safety on their `Map`, notice the --- existence of functions like `fromList :: [(k, v)] -> Map k v` and --- toList :: Map k v -> [(k, v)]. Therefore, I will derive Generic and Newtype --- instance and export the constructor. We could potentially provide this by --- having a `fromList` in `Maybe` although we should probably try to replicate --- behaviour so that our CTL and on-chain behaviours match. There doesn't even --- seem to be an `Ord` constraint on the keys. --- | A Plutus-style associated list `Map` of key-value pairs. -newtype Map (k :: Type) (v :: Type) = Map (Array (Tuple k v)) - -derive instance Generic (Map k v) _ -derive instance Newtype (Map k v) _ -derive newtype instance (Eq k, Eq v) => Eq (Map k v) -derive newtype instance (Ord k, Ord v) => Ord (Map k v) - -instance (EncodeAeson k, EncodeAeson v) => EncodeAeson (Map k v) where - encodeAeson = encodeAeson <<< map (rmap encodeAeson) <<< unwrap - -instance (DecodeAeson k, DecodeAeson v) => DecodeAeson (Map k v) where - decodeAeson x = Map <$> - ( traverse (rtraverse decodeAeson) - =<< (decodeAeson x :: _ (Array (Tuple k Aeson))) - ) - -instance (Show k, Show v) => Show (Map k v) where - show = genericShow - -instance (ToData k, ToData v) => ToData (Map k v) where - toData (Map xs) = PD.Map (bimap toData toData <$> xs) - -instance (FromData k, FromData v) => FromData (Map k v) where - fromData (PD.Map mp) = do - Map <$> - ( for mp \(k /\ v) -> - Tuple <$> fromData k <*> fromData v - ) - fromData _ = Nothing - -instance Functor (Map k) where - map f (Map xs) = Map $ map (map f) xs - -instance FunctorWithIndex k (Map k) where - mapWithIndex f (Map xs) = Map $ map (\(Tuple k v) -> Tuple k (f k v)) xs - -instance Foldable (Map k) where - foldMap f (Map xs) = foldMap (foldMap f) xs - foldr f = foldrDefault f - foldl f = foldlDefault f - -instance FoldableWithIndex k (Map k) where - foldMapWithIndex f (Map xs) = foldMap (uncurry f) xs - foldrWithIndex f = foldrWithIndexDefault f - foldlWithIndex f = foldlWithIndexDefault f - -instance Traversable (Map k) where - traverse f (Map xs) = Map <$> traverse (traverse f) xs - sequence (Map xs) = Map <$> sequence (map sequence xs) - -instance TraversableWithIndex k (Map k) where - traverseWithIndex f (Map xs) = Map <$> traverse - (\(Tuple k v) -> Tuple k <$> f k v) - xs - -instance (Eq k, Semigroup v) => Semigroup (Map k v) where - append = unionWith (<>) - -instance (Eq k, Semigroup v) => Monoid (Map k v) where - mempty = empty - --- | Find an entry in a `Map`. -lookup :: forall (k :: Type) (v :: Type). Eq k => k -> Map k v -> Maybe v -lookup k (Map xs) = Foldable.lookup k xs - --- | Whether given key is a member of a `Map` -member :: forall (k :: Type) (v :: Type). Eq k => k -> Map k v -> Boolean -member k = isJust <<< lookup k - --- Insert a key-value pair into a `Map` -insert :: forall k v. (Eq k) => k -> v -> Map k v -> Map k v -insert k v m = unionWith (\_ b -> b) m $ singleton k v - --- | Delete a key in a `Map` -delete :: forall (k :: Type) (v :: Type). Eq k => k -> Map k v -> Map k v -delete k (Map xs) = - case Array.findIndex (fst >>> (==) k) xs >>= flip Array.deleteAt xs of - Nothing -> Map xs - Just newMap -> Map newMap - --- | The keys of a `Map` -keys :: forall (k :: Type) (v :: Type). Map k v -> Array k -keys (Map xs) = fst <$> xs - --- | The values of a `Map` -values :: forall (k :: Type) (v :: Type). Map k v -> Array v -values (Map xs) = snd <$> xs - --- | Combine two `Map`s -union - :: forall (k :: Type) (v :: Type) (r :: Type) - . Eq k - => Map k v - -> Map k r - -> Map k (These v r) -union (Map ls) (Map rs) = - let - f :: v -> Maybe r -> These v r - f a = case _ of - Nothing -> This a - Just b -> Both a b - - ls' :: Array (k /\ These v r) - ls' = map (\(c /\ i) -> (c /\ f i (lookup c (Map rs)))) ls - - rs' :: Array (k /\ r) - rs' = - Array.filter (\(c /\ _) -> not (Array.any (\(c' /\ _) -> c' == c) ls)) rs - - rs'' :: Array (k /\ These v r) - rs'' = map (map That) rs' - in - Map (ls' <> rs'') - --- | Combine two `Map`s with the given combination function -unionWith - :: forall (k :: Type) (a :: Type) - . Eq k - => (a -> a -> a) - -> Map k a - -> Map k a - -> Map k a -unionWith merge ls rs = these identity identity merge <$> union ls rs - --- | A version of Haskell's `Data.Map.Lazy.mapEither` that works with `These` -mapThese - :: forall (k :: Type) (v :: Type) (a :: Type) (b :: Type) - . (v -> These a b) - -> Map k v - -> (Map k a /\ Map k b) -mapThese f mps = Map (fst mappedThese) /\ Map (snd mappedThese) - where - f' - :: k /\ These a b - -> Array (k /\ a) /\ Array (k /\ b) - -> Array (k /\ a) /\ Array (k /\ b) - f' (k /\ v) (as /\ bs) = case v of - This a -> Tuple ((k /\ a) : as) bs - That b -> Tuple as ((k /\ b) : bs) - Both a b -> Tuple ((k /\ a) : as) ((k /\ b) : bs) - - mappedThese :: Array (k /\ a) /\ Array (k /\ b) - mappedThese = foldr f' ([] /\ []) (unwrap $ map f mps) - --- | A singleton `Map` -singleton :: forall (k :: Type) (v :: Type). k -> v -> Map k v -singleton k v = Map $ Array.singleton (k /\ v) - --- | An empty `Map` -empty :: forall (k :: Type) (v :: Type). Map k v -empty = Map [] - --- | Checks whether a `Map` is empty -null :: forall (k :: Type) (v :: Type). Map k v -> Boolean -null (Map xs) = Array.null xs - --- | Filter all values that satisfy the predicate. -filter :: forall (k :: Type) (v :: Type). (v -> Boolean) -> Map k v -> Map k v -filter f (Map xs) = Map $ Array.filter (f <<< snd) xs - --- | Return all elements of the map in the ascending order of their keys. -elems :: forall (k :: Type) (v :: Type). Map k v -> Array v -elems (Map xs) = snd <$> xs - --- | Map values and collect the `Just` results. -mapMaybe - :: forall (k :: Type) (a :: Type) (b :: Type) - . (a -> Maybe b) - -> Map k a - -> Map k b -mapMaybe f (Map xs) = Map $ Array.mapMaybe (\(k /\ v) -> (k /\ _) <$> f v) xs - --- | Map keys, values and collect the `Just` results. -mapMaybeWithKey - :: forall (k :: Type) (a :: Type) (b :: Type) - . (k -> a -> Maybe b) - -> Map k a - -> Map k b -mapMaybeWithKey f (Map xs) = - Map $ Array.mapMaybe (\(k /\ v) -> (k /\ _) <$> f k v) xs diff --git a/src/Internal/Plutus/Types/Credential.purs b/src/Internal/Plutus/Types/Credential.purs deleted file mode 100644 index 33ebe51043..0000000000 --- a/src/Internal/Plutus/Types/Credential.purs +++ /dev/null @@ -1,153 +0,0 @@ -module Ctl.Internal.Plutus.Types.Credential - ( Credential(PubKeyCredential, ScriptCredential) - , StakingCredential(StakingHash, StakingPtr) - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(AtKey, Named, UnexpectedValue) - , decodeAeson - , (.:) - ) -import Contract.Prelude (type (/\)) -import Ctl.Internal.FromData (class FromData, genericFromData) -import Ctl.Internal.Helpers (contentsProp, encodeTagged', tagProp) -import Ctl.Internal.Plutus.Types.DataSchema - ( class HasPlutusSchema - , type (:+) - , type (:=) - , type (@@) - , I - , PNil - ) -import Ctl.Internal.Serialization.Address - ( CertificateIndex - , Slot - , TransactionIndex - ) -import Ctl.Internal.ToData (class ToData, genericToData) -import Ctl.Internal.TypeLevel.Nat (S, Z) -import Ctl.Internal.Types.PubKeyHash (PubKeyHash) -import Ctl.Internal.Types.Scripts (ValidatorHash) -import Data.Argonaut.Encode.Encoders (encodeString) -import Data.Bifunctor (lmap) -import Data.Either (Either(Left)) -import Data.Generic.Rep (class Generic) -import Data.Show.Generic (genericShow) -import Data.Tuple.Nested ((/\)) - --------------------------------------------------------------------------------- --- Credential --------------------------------------------------------------------------------- - --- Taken from https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/Plutus-V1-Ledger-Api.html#t:Credential --- Plutus rev: dbefda30be6490c758aa88b600f5874f12712b3a --- | Credential required to unlock a transaction output. -data Credential - -- | The transaction that spends this output must be signed by - -- | the private key. - = PubKeyCredential PubKeyHash - -- | The transaction that spends this output must include the validator - -- | script and be accepted by the validator. - | ScriptCredential ValidatorHash - -derive instance Eq Credential -derive instance Ord Credential -derive instance Generic Credential _ - -instance Show Credential where - show = genericShow - -instance - HasPlutusSchema - Credential - ( "PubKeyCredential" := PNil @@ Z - :+ "ScriptCredential" - := PNil - @@ (S Z) - :+ PNil - ) - -instance EncodeAeson Credential where - encodeAeson = case _ of - PubKeyCredential a -> encodeTagged' "PubKeyCredential" a - ScriptCredential a -> encodeTagged' "ScriptCredential" a - -instance DecodeAeson Credential where - decodeAeson a = lmap (Named "Credential") do - obj <- decodeAeson a - tag <- obj .: tagProp - case tag of - "PubKeyCredential" -> PubKeyCredential <$> obj .: contentsProp - "ScriptCredential" -> ScriptCredential <$> obj .: contentsProp - _ -> Left $ AtKey tagProp $ UnexpectedValue $ encodeString tag - -instance ToData Credential where - toData = genericToData - -instance FromData Credential where - fromData = genericFromData - --------------------------------------------------------------------------------- --- StakingCredential --------------------------------------------------------------------------------- - --- Taken from https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/Plutus-V1-Ledger-Api.html#t:StakingCredential --- Plutus rev: dbefda30be6490c758aa88b600f5874f12712b3a --- | Staking credential used to assign rewards. -data StakingCredential - = StakingHash Credential - | StakingPtr - { slot :: Slot - , txIx :: TransactionIndex - , certIx :: CertificateIndex - } - -derive instance Eq StakingCredential -derive instance Ord StakingCredential -derive instance Generic StakingCredential _ - -instance Show StakingCredential where - show = genericShow - -instance - HasPlutusSchema - StakingCredential - ( "StakingHash" := PNil @@ Z - :+ "StakingPtr" - := - ( "slot" := I Slot :+ "txIx" := I TransactionIndex :+ "certIx" - := I CertificateIndex - :+ PNil - ) - @@ (S Z) - :+ PNil - ) - -instance ToData StakingCredential where - toData = genericToData - -instance FromData StakingCredential where - fromData = genericFromData - -instance EncodeAeson StakingCredential where - encodeAeson = case _ of - StakingHash a -> encodeTagged' "StakingHash" a - StakingPtr ptr -> encodeTagged' "StakingPtr" - (ptr.slot /\ ptr.txIx /\ ptr.certIx) - -instance DecodeAeson StakingCredential where - decodeAeson a = lmap (Named "StakingCredential") do - obj <- decodeAeson a - tag <- obj .: tagProp - case tag of - "StakingHash" -> StakingHash <$> obj .: contentsProp - "StakingPtr" -> toStakingPtr <$> obj .: contentsProp - _ -> Left $ AtKey tagProp $ UnexpectedValue $ encodeString tag - where - toStakingPtr - :: (Slot /\ TransactionIndex /\ CertificateIndex) -> StakingCredential - toStakingPtr (slot /\ txIx /\ certIx) = StakingPtr { slot, txIx, certIx } diff --git a/src/Internal/Plutus/Types/CurrencySymbol.purs b/src/Internal/Plutus/Types/CurrencySymbol.purs deleted file mode 100644 index 3bc9af231d..0000000000 --- a/src/Internal/Plutus/Types/CurrencySymbol.purs +++ /dev/null @@ -1,109 +0,0 @@ -module Ctl.Internal.Plutus.Types.CurrencySymbol - ( CurrencySymbol(CurrencySymbol) - , adaSymbol - , currencyMPSHash - , getCurrencySymbol - , mkCurrencySymbol - , mpsSymbol - , scriptHashAsCurrencySymbol - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , caseAesonObject - , decodeAeson - , encodeAeson - , getField - ) -import Control.Monad.Gen as Gen -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata) -import Ctl.Internal.Serialization.Hash - ( ScriptHash - , scriptHashFromBytes - , scriptHashToBytes - ) -import Ctl.Internal.ToData (class ToData) -import Ctl.Internal.Types.ByteArray (ByteArray, hexToByteArrayUnsafe) -import Ctl.Internal.Types.Scripts (MintingPolicyHash(MintingPolicyHash)) -import Data.Array.NonEmpty (fromArray) -import Data.Either (Either(Left)) -import Data.Maybe (Maybe, fromJust) -import Data.Newtype (unwrap) -import Partial.Unsafe (unsafePartial) -import Test.QuickCheck.Arbitrary (class Arbitrary) - -newtype CurrencySymbol = CurrencySymbol ByteArray - -derive newtype instance Eq CurrencySymbol -derive newtype instance Ord CurrencySymbol -derive newtype instance FromData CurrencySymbol -derive newtype instance FromMetadata CurrencySymbol -derive newtype instance ToData CurrencySymbol -derive newtype instance ToMetadata CurrencySymbol - -instance DecodeAeson CurrencySymbol where - decodeAeson = caseAesonObject - (Left $ TypeMismatch "Expected object") - (flip getField "unCurrencySymbol" >=> decodeAeson >>> map CurrencySymbol) - -instance EncodeAeson CurrencySymbol where - encodeAeson (CurrencySymbol mph) = encodeAeson { "unCurrencySymbol": mph } - -instance Show CurrencySymbol where - show (CurrencySymbol cs) = "(CurrencySymbol " <> show cs <> ")" - -instance Arbitrary CurrencySymbol where - arbitrary = Gen.elements $ map translate $ unsafeNonEmpty - [ "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" - , "92c4f22371bd453aec9fe19ccebfbc88211ae854b5eab424bcd4c26d" - , "c9e9c15d4f16a7948d3736c93aa79034621d51dccc4df5d31c7d34aa" - ] - where - unsafeNonEmpty x = unsafePartial $ fromJust $ fromArray x - - translate :: String -> CurrencySymbol - translate x = - scriptHashAsCurrencySymbol $ unsafePartial $ fromJust - $ scriptHashFromBytes - $ hexToByteArrayUnsafe x - -adaSymbol :: CurrencySymbol -adaSymbol = CurrencySymbol mempty - -scriptHashAsCurrencySymbol :: ScriptHash -> CurrencySymbol -scriptHashAsCurrencySymbol = CurrencySymbol <<< unwrap <<< scriptHashToBytes - --- | The minting policy hash of a currency symbol. -currencyMPSHash :: CurrencySymbol -> MintingPolicyHash -currencyMPSHash = MintingPolicyHash <<< currencyScriptHash - --- | The currency symbol of a monetary policy hash. -mpsSymbol :: MintingPolicyHash -> Maybe CurrencySymbol -mpsSymbol (MintingPolicyHash h) = mkCurrencySymbol $ unwrap $ scriptHashToBytes - h - -getCurrencySymbol :: CurrencySymbol -> ByteArray -getCurrencySymbol (CurrencySymbol curSymbol) = curSymbol - -mkCurrencySymbol :: ByteArray -> Maybe CurrencySymbol -mkCurrencySymbol byteArr - | byteArr == mempty = - pure adaSymbol - | otherwise = - scriptHashFromBytes byteArr $> CurrencySymbol byteArr - --------------------------------------------------------------------------------- --- Internal --------------------------------------------------------------------------------- - --- This must be safe to use as long as we always construct a --- `CurrencySymbol` with the smart-constructors. -currencyScriptHash :: CurrencySymbol -> ScriptHash -currencyScriptHash = unsafePartial $ fromJust <<< scriptHashFromBytes - <<< getCurrencySymbol diff --git a/src/Internal/Plutus/Types/DataSchema.purs b/src/Internal/Plutus/Types/DataSchema.purs deleted file mode 100644 index 7d69a41f78..0000000000 --- a/src/Internal/Plutus/Types/DataSchema.purs +++ /dev/null @@ -1,261 +0,0 @@ -module Ctl.Internal.Plutus.Types.DataSchema - ( PSchema - , class HasPlutusSchema - , PNil - , PCons - , ApPCons - , Id - , I - , type (:+) - , IxK - , MkIxK - , MkIxK_ - , type (@@) - , Field - , MkField - , MkField_ - , type (:=) - , class SchemaToRowList - , class PlutusSchemaToRowListI - , class AllUnique2 - , class ValidPlutusSchema - ) where - -import Ctl.Internal.TypeLevel.Nat (Nat) -import Ctl.Internal.TypeLevel.RowList (class AllUniqueLabels) -import Ctl.Internal.TypeLevel.RowList.Unordered.Indexed - ( class AllUniqueLabelsI - , class UniqueIndices - , ConsI - , NilI - , RowListI - ) -import Type.RowList (Cons, Nil, RowList) - -{- This modules defines various data types (kinds) which are used to encode enough the *structure* of the Plutus Data that corresponds to a - given data type at the type level. - - There are three reason why this is needed: - - 1) The previous implementation of ToData/FromData does not encode the order of record entries. Because RowLists are lexicographically sorted - and Plutus Data is not, this rendered the library incompatible with PureScript record types generated by purescript-bridge. This provides a way to - encode that order. - - 2) The previous implementation of ToData/FromData relied upon a HasConstrIndices class which encoded the index corresponding to a - Symbol representation of a constructor's name at the *term level*. This is not in itself bad. However, it is possible (in both Haskell and PureScript) - to define sum types such as: - - ``` - data Foo = FooA {foo :: String, fooo :: Int} - | FooB {fooo :: Bool, foo :: Bool} - ``` - - In cases like this, where multiple constructors of the sum type accept records as arguments and where those records share labels - with each other, the Plutus Data index of a record entry cannot be determined solely by the type (Foo) and the label ("foo","fooo") and must be - represented in a dependent manner with respect to the constructor name. (I.e. you need to know which constructor a given record belongs to in order - to determine its index). - - I do not believe that it is possible to make FromData work without a type level representation of the indices of each record entry, and it would be difficult - (if not strictly impossible) to combine the term-level HasConstrIndices approach with a type level IndexedRecField approach, and the schema implented here unifies all - of the required information in a single place. - - 3) Ergonomics/Safety. By encoding everything at the type level, we can express sophisticated constraints on the schema to ensure that patently invalid schemata are - rejected at compile time. This reduces the burden and complexity of tests, and allows us to detect subtle mistakes in generated or handwritten instances that might - otherwise only be determinable from emulator trace errors (which are, to put it mildly, not ideal). By defining Schema types here, we are also able to provide a syntax - for the schema which is visually close to a data declaration and easy to generate. - --} - -{- <<< Plutus Data Schema + Associated types/kinds/data >>> -} - --- | A type level Identity "functor kind". This is mainly used to overload the ':=' type operator. -data Id :: forall (k :: Type). k -> Type -data Id k - -foreign import data I :: forall (k :: Type). k -> Id k - --- | A kind (never exists as a term). This is the kind of @PCons@ and @PNil@. -data PSchema :: forall (k :: Type). k -> Type -data PSchema k - -{- A concrete Plutus Data schema. Morally equivalent to: Row (Row Type). This is superfluous - in the sense that we could simply do everything here with (RowListI (RowList Type)), which - @PlutusSchema@s are all translated to, but this facilitates a more comprehensible syntax. - (Conversely we could rewrite all of the RowList/RowListI machinery in terms of this, but it - would be much more difficult to read/debug/reason about). - - Here's an example: - - data FType - = F0 - { f0A :: BigInt - } - | F1 - { f1A :: Boolean - , f1B :: Boolean - , f1C :: Boolean - } - | F2 - { f2A :: BigInt - , f2B :: FType - } - - instance - HasPlutusSchema FType - ( "F0" := - ( "f0A" := I BigInt - :+ PNil) - @@ Z - - :+ "F1" := - ( "f1A" := I Boolean - :+ "f1B" := I Boolean - :+ "f1C" := I Boolean - :+ PNil - ) - @@ (S Z) - - :+ "F2" := - ( "f2A" := I BigInt - :+ "f2B" := I FType - :+ PNil - ) - @@ (S (S Z)) - - :+ PNil - ) - -Note that a PSchema encodes two pieces of information: - -1) The index of each *constructor* of a data type. This information is encoded in the "outer" RowListI. - In the above example, these are "F0" (Z), "F1" (S Z), and "F2" (S (S Z)) - -2) The correct on-chain ordering of each record field. This is encoded implicitly by the ordering of the fields in each inner list (i.e. we do not provide a specific index for record fields). - If a constructor does not have a Record argument, we do not need to encode any information about that argument. For example, the type: - - data GType - = G0 BigInt - | G1 Boolean Boolean Boolean - | G2 BigInt GType - - would have a much simpler Schema: - - instance - HasPlutusSchema GType - ( "G0" := PNil @@ Z - :+ "G1" := PNil @@ (S Z) - :+ "G2" := PNil @@ (S (S Z)) - :+ PNil) - - The sole purpose of the inner list is to ensure correct translation to and from Plutus Data for record types - when using the generic functions in ToData/FromData. Since GType's constructors do not have record arguments, - no additional information is needed in the inner lists. --} - -type PlutusSchema = PSchema (PSchema Type) - --- | A class used to associate types with a Plutus Data Schema. The fundeps *should* guarantee --- | that only one schema can exist for each type. This allows us to make the compiler select the --- | schema associated with a particular type. -class HasPlutusSchema - :: Type -> PlutusSchema -> Constraint -class HasPlutusSchema t schema | t -> schema - --- | Listlike constructors for the PSchema kind. -foreign import data PNil :: forall (k :: Type). PSchema k -foreign import data PCons - :: forall (k :: Type). Field k -> PSchema k -> PSchema k - --- | Type synonym which is used to provide syntatic sugar to PCons. You can think of :+ as a type level version of : for PSchema -type ApPCons :: forall (k :: Type). Field k -> PSchema k -> PSchema k -type ApPCons x xs = PCons x xs - -infixr 0 type ApPCons as :+ - --- | Indexed kind. A kind representing a type @k@ indexed by a type level natural number @n@. -data IxK :: forall (k :: Type). k -> Type -data IxK k - --- | A data type of Kind (IxK k n) for some k and n -foreign import data MkIxK :: forall (k :: Type). Nat -> k -> IxK k - --- | Syntactic sugar which allows us to represent MkIxK as a type operator -type MkIxK_ - :: forall k1. k1 -> Nat -> IxK k1 -- FIXME(@gnumonik): s/k1/k it complains -type MkIxK_ k n = MkIxK n k - -infixr 9 type MkIxK_ as @@ - --- | A kind which is used to represent pairs of Symbols and IxKs. A fancy type level tuple, more or less. -data Field :: forall (k :: Type). k -> Type -data Field k - --- | A data type of Kind (Field k) -foreign import data MkField - :: forall (k :: Type) (f :: Type -> Type). Symbol -> f k -> Field k - --- | Type synonym used to represent MkField as a type operator. -type MkField_ - :: forall (f :: Type -> Type) (k :: Type). Symbol -> f k -> Field k -type MkField_ lbl ixty = MkField lbl ixty - -infixr 8 type MkField_ as := - -{- <<< Constraints used to provide compile-time validation of a PSchema >>> -} - --- TODO: See if we can optimize this. Slows down compilation considerably for complex types. --- GH Issue: https://github.com/Plutonomicon/cardano-transaction-lib/issues/433 --- | A class which ensures that the Nat indices of the RowListI are unique & that the Symbol --- | labels of both the RowListI and RowList in a RowListI (RowList k) all contain unique labels --- | (relative to their "level", i.e., two record arguments of *different* constructors can --- | have overlapping labels, but constructor names cannot overlap, nor can two labels or indices --- | of the *same* record) -class AllUnique2 :: forall (k :: Type). RowListI (RowList k) -> Constraint -class AllUnique2 rList - -instance AllUnique2 NilI -else instance - ( AllUniqueLabels a - , AllUniqueLabelsI (ConsI l a n xs) - , UniqueIndices (ConsI l a n xs) - , AllUnique2 xs - ) => - AllUnique2 (ConsI l a n xs) - --- | The class which validates a Plutus Schema. To make use of genericFromData / genericToData, --- | a type must have an associated Plutus Data schema which satisfies this constraint. -class ValidPlutusSchema :: PlutusSchema -> RowListI (RowList Type) -> Constraint -class - ( PlutusSchemaToRowListI schema list - , AllUnique2 list - ) <= - ValidPlutusSchema schema list - | schema -> list - -instance - ( PlutusSchemaToRowListI schema list - , AllUnique2 list - ) => - ValidPlutusSchema schema list - --- | Helper type classes used to convert a PlutusSchema to a RowListI (RowList k). Should not need to be used outside of this module. -class SchemaToRowList - :: forall (k :: Type). PSchema k -> RowList k -> Constraint -class SchemaToRowList schema list | schema -> list - -instance SchemaToRowList PNil Nil -else instance - ( SchemaToRowList xs xs' - ) => - SchemaToRowList (PCons (MkField l (I k)) xs) (Cons l k xs') - -class PlutusSchemaToRowListI - :: PlutusSchema -> RowListI (RowList Type) -> Constraint -class PlutusSchemaToRowListI schema list | schema -> list - -instance PlutusSchemaToRowListI PNil NilI -else instance - ( PlutusSchemaToRowListI xs xs' - , SchemaToRowList a a' - ) => - PlutusSchemaToRowListI (PCons (MkField l (MkIxK n a)) xs) (ConsI l a' n xs') diff --git a/src/Internal/Plutus/Types/Transaction.purs b/src/Internal/Plutus/Types/Transaction.purs deleted file mode 100644 index 66c4d57ff3..0000000000 --- a/src/Internal/Plutus/Types/Transaction.purs +++ /dev/null @@ -1,121 +0,0 @@ -module Ctl.Internal.Plutus.Types.Transaction - ( TransactionOutput(TransactionOutput) - , UtxoMap - , TransactionOutputWithRefScript(TransactionOutputWithRefScript) - , _amount - , _datum - , _output - , _scriptRef - , pprintTransactionOutput - ) where - -import Prelude - -import Aeson (class DecodeAeson, class EncodeAeson) -import Ctl.Internal.Cardano.Types.ScriptRef (ScriptRef) -import Ctl.Internal.Cardano.Types.Value (pprintValue) -import Ctl.Internal.FromData (class FromData, fromData) -import Ctl.Internal.Plutus.Conversion.Value (fromPlutusValue) -import Ctl.Internal.Plutus.Types.Address (Address) -import Ctl.Internal.Plutus.Types.Value (Value) -import Ctl.Internal.Serialization.Hash (ScriptHash, scriptHashToBytes) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.BigNum as BigNum -import Ctl.Internal.Types.OutputDatum (OutputDatum, pprintOutputDatum) -import Ctl.Internal.Types.PlutusData (PlutusData(Constr)) -import Ctl.Internal.Types.RawBytes (rawBytesToHex) -import Ctl.Internal.Types.Transaction (TransactionInput) -import Data.Generic.Rep (class Generic) -import Data.Lens (Lens') -import Data.Lens.Iso.Newtype (_Newtype) -import Data.Lens.Record (prop) -import Data.Log.Tag (TagSet, tag, tagSetTag) -import Data.Log.Tag as TagSet -import Data.Map (Map) -import Data.Maybe (Maybe(Nothing), maybe) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Show.Generic (genericShow) -import Type.Proxy (Proxy(Proxy)) - --- https://github.com/input-output-hk/plutus/blob/c8d4364d0e639fef4d5b93f7d6c0912d992b54f9/plutus-ledger-api/src/PlutusLedgerApi/V2/Tx.hs#L80 -newtype TransactionOutput = TransactionOutput - { address :: Address - , amount :: Value - , datum :: OutputDatum - , referenceScript :: Maybe ScriptHash - } - -_amount :: Lens' TransactionOutput Value -_amount = _Newtype <<< prop (Proxy :: Proxy "amount") - -_datum :: Lens' TransactionOutput OutputDatum -_datum = _Newtype <<< prop (Proxy :: Proxy "datum") - -derive instance Generic TransactionOutput _ -derive instance Newtype TransactionOutput _ -derive newtype instance Eq TransactionOutput - -instance Show TransactionOutput where - show = genericShow - -derive newtype instance DecodeAeson TransactionOutput -derive newtype instance EncodeAeson TransactionOutput - -instance FromData TransactionOutput where - fromData (Constr n [ addr, amt, datum, referenceScript ]) - | n == BigNum.zero = - TransactionOutput <$> - ( { address: _, amount: _, datum: _, referenceScript: _ } - <$> fromData addr - <*> fromData amt - <*> fromData datum - <*> fromData referenceScript - ) - fromData _ = Nothing - -instance ToData TransactionOutput where - toData (TransactionOutput { address, amount, datum, referenceScript }) = - Constr BigNum.zero - [ toData address, toData amount, toData datum, toData referenceScript ] - -pprintTransactionOutput :: TransactionOutput -> TagSet -pprintTransactionOutput - (TransactionOutput { address, amount, datum, referenceScript }) = - TagSet.fromArray $ - [ "address" `tag` show address - , "amount" `tagSetTag` pprintValue (fromPlutusValue amount) - , pprintOutputDatum datum - ] <> referenceScriptTagSet - where - referenceScriptTagSet = maybe [] - (pure <<< tag "referenceScript" <<< rawBytesToHex <<< scriptHashToBytes) - referenceScript - -newtype TransactionOutputWithRefScript = TransactionOutputWithRefScript - { output :: TransactionOutput - , scriptRef :: Maybe ScriptRef - } - -_output :: Lens' TransactionOutputWithRefScript TransactionOutput -_output = _Newtype <<< prop (Proxy :: Proxy "output") - -_scriptRef :: Lens' TransactionOutputWithRefScript (Maybe ScriptRef) -_scriptRef = _Newtype <<< prop (Proxy :: Proxy "scriptRef") - -derive instance Generic TransactionOutputWithRefScript _ -derive instance Newtype TransactionOutputWithRefScript _ -derive newtype instance Eq TransactionOutputWithRefScript - -instance Show TransactionOutputWithRefScript where - show = genericShow - -derive newtype instance DecodeAeson TransactionOutputWithRefScript -derive newtype instance EncodeAeson TransactionOutputWithRefScript - -instance FromData TransactionOutputWithRefScript where - fromData = map (wrap <<< { output: _, scriptRef: Nothing }) <<< fromData - -instance ToData TransactionOutputWithRefScript where - toData = toData <<< _.output <<< unwrap - -type UtxoMap = Map TransactionInput TransactionOutputWithRefScript diff --git a/src/Internal/Plutus/Types/TransactionUnspentOutput.purs b/src/Internal/Plutus/Types/TransactionUnspentOutput.purs deleted file mode 100644 index 68853c349c..0000000000 --- a/src/Internal/Plutus/Types/TransactionUnspentOutput.purs +++ /dev/null @@ -1,65 +0,0 @@ -module Ctl.Internal.Plutus.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - , lookupTxHash - , _input - , _output - , mkTxUnspentOut - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - ) -import Ctl.Internal.Plutus.Types.Transaction - ( TransactionOutputWithRefScript - , UtxoMap - ) -import Ctl.Internal.Types.Transaction (TransactionHash, TransactionInput) -import Data.Array (filter) -import Data.Generic.Rep (class Generic) -import Data.Lens (Lens') -import Data.Lens.Iso.Newtype (_Newtype) -import Data.Lens.Record (prop) -import Data.Map as Map -import Data.Newtype (class Newtype, unwrap) -import Data.Show.Generic (genericShow) -import Data.Tuple (fst) -import Data.Tuple.Nested ((/\)) -import Type.Proxy (Proxy(Proxy)) - -newtype TransactionUnspentOutput = TransactionUnspentOutput - { input :: TransactionInput - , output :: TransactionOutputWithRefScript - } - -_input :: Lens' TransactionUnspentOutput TransactionInput -_input = _Newtype <<< prop (Proxy :: Proxy "input") - -_output :: Lens' TransactionUnspentOutput TransactionOutputWithRefScript -_output = _Newtype <<< prop (Proxy :: Proxy "output") - -derive instance Generic TransactionUnspentOutput _ -derive instance Newtype TransactionUnspentOutput _ -derive newtype instance Eq TransactionUnspentOutput - -instance Show TransactionUnspentOutput where - show = genericShow - -derive newtype instance DecodeAeson TransactionUnspentOutput -derive newtype instance EncodeAeson TransactionUnspentOutput - -lookupTxHash - :: TransactionHash -> UtxoMap -> Array TransactionUnspentOutput -lookupTxHash txHash utxos = - map (\(input /\ output) -> TransactionUnspentOutput { input, output }) - $ filter (fst >>> unwrap >>> _.transactionId >>> eq txHash) - $ - Map.toUnfoldable utxos - -mkTxUnspentOut - :: TransactionInput - -> TransactionOutputWithRefScript - -> TransactionUnspentOutput -mkTxUnspentOut input output = TransactionUnspentOutput { input, output } diff --git a/src/Internal/Plutus/Types/Value.purs b/src/Internal/Plutus/Types/Value.purs deleted file mode 100644 index 3e3c31a00f..0000000000 --- a/src/Internal/Plutus/Types/Value.purs +++ /dev/null @@ -1,298 +0,0 @@ -module Ctl.Internal.Plutus.Types.Value - ( Coin(Coin) - , Value - , coinToValue - , flattenNonAdaAssets - , flattenValue - , geq - , getLovelace - , getValue - , gt - , isCoinZero - , isZero - , leq - , lovelaceValueOf - , lt - , negation - , scale - , singleton - , singleton' - , split - , symbols - , unionWith - , valueOf - , valueToCoin - , valueToCoin' - ) where - -import Prelude hiding (eq) - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , caseAesonObject - , decodeAeson - , encodeAeson - , getField - ) -import Control.Apply (lift3) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Helpers (showWithParens) -import Ctl.Internal.Plutus.Types.AssocMap (Map(Map)) as Plutus -import Ctl.Internal.Plutus.Types.AssocMap - ( keys - , lookup - , mapThese - , singleton - , union - ) as Plutus.Map -import Ctl.Internal.Plutus.Types.CurrencySymbol - ( CurrencySymbol - , adaSymbol - , mkCurrencySymbol - ) -import Ctl.Internal.QuickCheck (genPositive, unMaybeGen) -import Ctl.Internal.ToData (class ToData) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.TokenName (TokenName, adaToken, mkTokenName) -import Data.Array (concatMap, filter, replicate) -import Data.Either (Either(Left)) -import Data.Foldable (all, fold) -import Data.Generic.Rep (class Generic) -import Data.Lattice (class JoinSemilattice, class MeetSemilattice) -import Data.Maybe (Maybe(Nothing), fromMaybe) -import Data.Newtype (class Newtype) -import Data.These (These(Both, That, This), these) -import Data.Traversable (sequence) -import Data.Tuple (fst) -import Data.Tuple.Nested (type (/\), (/\)) -import JS.BigInt (BigInt) -import JS.BigInt as BigInt -import Test.QuickCheck.Arbitrary (class Arbitrary, arbitrary) -import Test.QuickCheck.Gen (Gen, chooseInt) - -newtype Value = Value (Plutus.Map CurrencySymbol (Plutus.Map TokenName BigInt)) - -derive newtype instance ToData Value -derive newtype instance FromData Value - -instance DecodeAeson Value where - decodeAeson = caseAesonObject - (Left $ TypeMismatch "Expected object") - (flip getField "getValue" >=> decodeAeson >>> map Value) - -instance EncodeAeson Value where - encodeAeson (Value mph) = encodeAeson $ encodeAeson - { "getValue": encodeAeson mph } - -arbitrarySingletonValue :: Gen Value -arbitrarySingletonValue = do - currencySymbol <- arbitrary - tokenName <- unMaybeGen $ mkTokenName <$> arbitrary - num <- BigInt.fromInt <$> genPositive - pure $ singleton currencySymbol tokenName num - -instance Arbitrary Value where - arbitrary = do - tokenNum <- chooseInt 0 10 - fold <$> (sequence $ replicate tokenNum arbitrarySingletonValue) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#eq -instance Eq Value where - eq = checkBinRel (==) - -instance Show Value where - show (Value mp) = "(PlutusValue " <> show mp <> ")" - -instance Semigroup Value where - append = unionWith add - -instance Monoid Value where - mempty = Value (Plutus.Map []) - -instance JoinSemilattice Value where - join = unionWith max - -instance MeetSemilattice Value where - meet = unionWith min - --------------------------------------------------------------------------------- --- Coin (Ada Lovelaces) --------------------------------------------------------------------------------- -newtype Coin = Coin BigInt - -derive instance Generic Coin _ -derive instance Newtype Coin _ -derive newtype instance Eq Coin - -instance Show Coin where - show (Coin c) = showWithParens "Coin" c - -instance Semigroup Coin where - append (Coin c1) (Coin c2) = Coin (c1 + c2) - -instance Monoid Coin where - mempty = Coin zero - -instance JoinSemilattice Coin where - join (Coin c1) (Coin c2) = Coin (max c1 c2) - -instance MeetSemilattice Coin where - meet (Coin c1) (Coin c2) = Coin (min c1 c2) - --- | Get the amount of lovelaces in Ada `Coin`. -getLovelace :: Coin -> BigInt -getLovelace (Coin l) = l - --- | Create a `Value` containing only the given `Coin`. -coinToValue :: Coin -> Value -coinToValue (Coin i) = lovelaceValueOf i - --- | Get the `Coin` in the given `Value`. -valueToCoin :: Value -> Coin -valueToCoin v = Coin $ valueOf v adaSymbol adaToken - --- | Get the `Coin` in the given `Value` as a `BigInt`. -valueToCoin' :: Value -> BigInt -valueToCoin' = getLovelace <<< valueToCoin - --- | Check whether an 'Ada' value is zero. -isCoinZero :: Coin -> Boolean -isCoinZero (Coin i) = i == zero - --------------------------------------------------------------------------------- --- Public --------------------------------------------------------------------------------- - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#Value --- | Gets the underlying `Plutus.Types.AssocMap.Map`. -getValue :: Value -> Plutus.Map CurrencySymbol (Plutus.Map TokenName BigInt) -getValue (Value mp) = mp - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#singleton --- | Makes a `Value` containing only the given quantity of the given currency. -singleton :: CurrencySymbol -> TokenName -> BigInt -> Value -singleton cs tn = Value <<< Plutus.Map.singleton cs <<< Plutus.Map.singleton tn - --- | Creates a singleton value given two byte arrays for currency symbol and --- | token name respectively. Returns `Nothing` when trying to create a `Value` --- | with the Ada currency symbol and a non-empty token name. -singleton' :: ByteArray -> ByteArray -> BigInt -> Maybe Value -singleton' cs tn amount - | cs == mempty && tn /= mempty = Nothing - | otherwise = - lift3 singleton (mkCurrencySymbol cs) (mkTokenName tn) - (pure amount) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#valueOf --- | Gets the quantity of the given currency in the `Value`. -valueOf :: Value -> CurrencySymbol -> TokenName -> BigInt -valueOf (Value mp) cs tn = fromMaybe zero $ - Plutus.Map.lookup cs mp >>= Plutus.Map.lookup tn - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Ada.html#lovelaceValueOf --- | A Value with the given amount of Lovelace (the currency unit). -lovelaceValueOf :: BigInt -> Value -lovelaceValueOf = singleton adaSymbol adaToken - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#local-6989586621679887124 --- | Returns a new `Value` with all amounts multiplied by `s`. -scale :: BigInt -> Value -> Value -scale s (Value mp) = Value (map (map (mul s)) mp) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#symbols --- | The list of `CurrencySymbol`s of a `Value`. -symbols :: Value -> Array CurrencySymbol -symbols (Value mp) = Plutus.Map.keys mp - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#isZero --- | Checks whether a `Value` is zero. -isZero :: Value -> Boolean -isZero = all (all ((==) zero)) <<< getValue - -negation :: Value -> Value -negation (Value mp) = Value (map (map negate) mp) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#split --- | Splits a value into its positive and non-positive parts. The first element of --- | the tuple contains the non-positive parts of the value, the second element --- | contains the positive parts. The convention is non-positive parts are --- | negated to make them positive in the output. -split :: Value -> Value /\ Value -split (Value mp) = - let - neg /\ pos = Plutus.Map.mapThese worker mp - in - negation (Value neg) /\ Value pos - where - worker - :: Plutus.Map TokenName BigInt - -> These (Plutus.Map TokenName BigInt) (Plutus.Map TokenName BigInt) - worker mp' = Both l r - where - l /\ r = - Plutus.Map.mapThese (\a -> if a <= zero then This a else That a) mp' - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#unionWith --- | Combines `Value` with a binary function on `BigInt`s. -unionWith :: (BigInt -> BigInt -> BigInt) -> Value -> Value -> Value -unionWith f lhs = - Value <<< map (map (these identity identity f)) <<< unionVal lhs - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#flattenValue --- | Converts a value to a simple list, keeping only the non-zero amounts. -flattenValue :: Value -> Array (CurrencySymbol /\ TokenName /\ BigInt) -flattenValue (Value (Plutus.Map arr)) = - flip concatMap arr \(cs /\ (Plutus.Map tokens)) -> - tokens <#> \(tn /\ value) -> - cs /\ tn /\ value - --- | Converts a value to a simple list, keeping only the non-Ada assets --- | with non-zero amounts. -flattenNonAdaAssets :: Value -> Array (CurrencySymbol /\ TokenName /\ BigInt) -flattenNonAdaAssets = filter (notEq adaSymbol <<< fst) <<< flattenValue - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#geq --- | Checks whether one `Value` is greater than or equal to another. -geq :: Value -> Value -> Boolean -geq = checkBinRel (>=) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#gt --- | Checks whether one `Value` is strictly greater than another. -gt :: Value -> Value -> Boolean -gt l r = not (isZero l && isZero r) && checkBinRel (>) l r - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#leq --- | Checks whether one `Value` is less than or equal to another. -leq :: Value -> Value -> Boolean -leq = checkBinRel (<=) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#lt --- | Checks whether one `Value` is strictly less than another. -lt :: Value -> Value -> Boolean -lt l r = not (isZero l && isZero r) && checkBinRel (<) l r - --------------------------------------------------------------------------------- --- Internal --------------------------------------------------------------------------------- - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#unionVal --- Combines two 'Value' maps. -unionVal - :: Value - -> Value - -> Plutus.Map CurrencySymbol (Plutus.Map TokenName (These BigInt BigInt)) -unionVal (Value lhs') (Value rhs) = - these (map This) (map That) Plutus.Map.union <$> - Plutus.Map.union lhs' rhs - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#checkPred -checkPred :: (These BigInt BigInt -> Boolean) -> Value -> Value -> Boolean -checkPred f l r = all (all f) (unionVal l r) - --- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#checkBinRel --- Check whether a binary relation holds for value pairs of two `Value` maps, --- supplying 0 where a key is only present in one of them. -checkBinRel :: (BigInt -> BigInt -> Boolean) -> Value -> Value -> Boolean -checkBinRel f l r = checkPred (these (flip f zero) (f zero) f) l r diff --git a/src/Internal/ProcessConstraints.purs b/src/Internal/ProcessConstraints.purs index 69ee5cc05c..27d1c79667 100644 --- a/src/Internal/ProcessConstraints.purs +++ b/src/Internal/ProcessConstraints.purs @@ -4,30 +4,34 @@ module Ctl.Internal.ProcessConstraints import Prelude -import Contract.Hashing (plutusScriptStakeValidatorHash) -import Control.Monad.Error.Class (catchError, throwError) -import Control.Monad.Except.Trans (ExceptT(ExceptT), except, runExceptT) -import Control.Monad.Reader.Class (asks) -import Control.Monad.State.Trans (get, gets, put, runStateT) -import Control.Monad.Trans.Class (lift) -import Ctl.Internal.Address (addressPaymentValidatorHash) -import Ctl.Internal.BalanceTx.RedeemerIndex - ( RedeemerPurpose(ForReward, ForCert, ForMint, ForSpend) - , UnindexedRedeemer(UnindexedRedeemer) - , unindexedRedeemerToRedeemer +import Cardano.Transaction.Edit + ( DetachedRedeemer + , RedeemerPurpose(ForSpend, ForMint, ForReward, ForCert) + , attachRedeemers + , mkRedeemersContext ) -import Ctl.Internal.Cardano.Types.ScriptRef (ScriptRef(NativeScriptRef)) -import Ctl.Internal.Cardano.Types.Transaction +import Cardano.Types ( Certificate ( StakeDelegation , PoolRetirement , PoolRegistration , StakeDeregistration , StakeRegistration + , RegDrepCert ) + , DataHash + , NetworkId + , PlutusData + , PlutusScript + , ScriptHash + , ScriptRef(NativeScriptRef, PlutusScriptRef) + , StakeCredential(StakeCredential) , Transaction + , TransactionInput , TransactionOutput(TransactionOutput) - , TransactionWitnessSet(TransactionWitnessSet) + , TransactionUnspentOutput(TransactionUnspentOutput) + , UtxoMap + , Value(Value) , _body , _certs , _inputs @@ -37,33 +41,36 @@ import Ctl.Internal.Cardano.Types.Transaction , _outputs , _referenceInputs , _requiredSigners - , _scriptDataHash , _withdrawals , _witnessSet ) -import Ctl.Internal.Cardano.Types.Value - ( Coin(Coin) - , getNonAdaAsset - , isZero - , mkSingletonValue' - , mpsSymbol +import Cardano.Types as Cardano +import Cardano.Types.Address + ( Address(BaseAddress, EnterpriseAddress) + , getPaymentCredential + ) +import Cardano.Types.Coin as Coin +import Cardano.Types.Credential + ( Credential(PubKeyHashCredential, ScriptHashCredential) + , asScriptHash ) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.DataHash as Datum +import Cardano.Types.Int as Int +import Cardano.Types.Mint as Mint +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.NativeScript as NativeScript +import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash, OutputDatum)) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.Transaction as Transaction +import Control.Monad.Error.Class (catchError, throwError) +import Control.Monad.Except.Trans (ExceptT(ExceptT), except, runExceptT) +import Control.Monad.Reader.Class (asks) +import Control.Monad.State.Trans (get, gets, put, runStateT) +import Control.Monad.Trans.Class (lift) import Ctl.Internal.Contract (getProtocolParameters) import Ctl.Internal.Contract.Monad (Contract, getQueryHandle, wrapQueryM) -import Ctl.Internal.Hashing (datumHash) as Hashing -import Ctl.Internal.Helpers (liftEither, liftM) -import Ctl.Internal.NativeScripts (nativeScriptHash) -import Ctl.Internal.Plutus.Conversion - ( fromPlutusTxOutputWithRefScript - , fromPlutusValue - ) -import Ctl.Internal.Plutus.Types.Credential - ( Credential(ScriptCredential, PubKeyCredential) - ) -import Ctl.Internal.Plutus.Types.Transaction (TransactionOutputWithRefScript) as Plutus -import Ctl.Internal.Plutus.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - ) +import Ctl.Internal.Helpers (liftEither, liftM, unsafeFromJust) import Ctl.Internal.ProcessConstraints.Error ( MkUnbalancedTxError ( CannotSatisfyAny @@ -71,8 +78,6 @@ import Ctl.Internal.ProcessConstraints.Error , CannotWithdrawRewardsPlutusScript , CannotWithdrawRewardsPubKey , DatumWrongHash - , CannotMakeValue - , MintingPolicyHashNotCurrencySymbol , CannotMintZero , ExpectedPlutusScriptGotNativeScript , CannotFindDatum @@ -86,7 +91,9 @@ import Ctl.Internal.ProcessConstraints.Error , DatumNotFound , TxOutRefNotFound , CannotSolveTimeConstraints + , NumericOverflow , OwnPubKeyAndStakeKeyMissing + , CannotAttachRedeemer ) ) import Ctl.Internal.ProcessConstraints.State @@ -106,33 +113,16 @@ import Ctl.Internal.ProcessConstraints.State , requireValue , totalMissingValue ) -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx) import Ctl.Internal.QueryM.Pools ( getPubKeyHashDelegationsAndRewards , getValidatorHashDelegationsAndRewards ) -import Ctl.Internal.Scripts - ( mintingPolicyHash - , nativeScriptStakeValidatorHash - , validatorHash - , validatorHashEnterpriseAddress - ) -import Ctl.Internal.Serialization.Address - ( NetworkId - , StakeCredential - , baseAddress - , baseAddressToAddress - , keyHashCredential - , scriptHashCredential - ) -import Ctl.Internal.Serialization.Hash (ScriptHash) import Ctl.Internal.Transaction ( attachDatum , attachNativeScript , attachPlutusScript , setScriptDataHash ) -import Ctl.Internal.Types.Datum (DataHash, Datum) import Ctl.Internal.Types.Interval ( POSIXTimeRange , always @@ -140,26 +130,7 @@ import Ctl.Internal.Types.Interval , isEmpty , posixTimeRangeToTransactionValidity ) -import Ctl.Internal.Types.OutputDatum - ( OutputDatum(NoOutputDatum, OutputDatumHash, OutputDatum) - ) -import Ctl.Internal.Types.PubKeyHash - ( payPubKeyHashBaseAddress - , payPubKeyHashEnterpriseAddress - , stakePubKeyHashRewardAddress - ) -import Ctl.Internal.Types.RewardAddress - ( stakePubKeyHashRewardAddress - , stakeValidatorHashRewardAddress - ) as RewardAddress import Ctl.Internal.Types.ScriptLookups (ScriptLookups) -import Ctl.Internal.Types.Scripts - ( MintingPolicy(NativeMintingPolicy, PlutusMintingPolicy) - , MintingPolicyHash - , Validator - , ValidatorHash - ) -import Ctl.Internal.Types.Transaction (TransactionInput) import Ctl.Internal.Types.TxConstraints ( DatumPresence(DatumWitness, DatumInline) , InputWithScriptRef(SpendInput, RefInput) @@ -194,30 +165,34 @@ import Ctl.Internal.Types.TxConstraints , MustBeSignedBy , MustValidateIn , MustIncludeDatum + , MustRegisterDrep ) - , TxConstraints(TxConstraints) + , TxConstraints , utxoWithScriptRef ) +import Ctl.Internal.Types.Val as Val import Data.Array (cons, partition, toUnfoldable, zip) import Data.Array (mapMaybe, singleton, (:)) as Array import Data.Bifunctor (lmap) import Data.Either (Either(Left, Right), either, hush, isRight, note) import Data.Foldable (foldM) -import Data.Lens (non, (%=), (%~), (.=), (.~), (<>=)) -import Data.Lens.Getter (to, use) +import Data.Lens ((%=), (.=), (.~), (<>=)) +import Data.Lens.Getter (use) import Data.Lens.Iso.Newtype (_Newtype) import Data.List (List(Nil, Cons)) import Data.Map (Map, empty, fromFoldable, lookup, union) import Data.Map as Map -import Data.Maybe (Maybe(Just, Nothing), fromMaybe, maybe) -import Data.Newtype (class Newtype, over, unwrap, wrap) -import Data.Set (insert) as Set -import Data.Traversable (for, traverse_) +import Data.Maybe (Maybe(Nothing, Just), fromMaybe, maybe) +import Data.Newtype (unwrap, wrap) +import Data.Set as Set +import Data.Traversable (traverse_) +import Data.Tuple (uncurry) import Data.Tuple.Nested (type (/\), (/\)) import Effect (Effect) import Effect.Aff.Class (liftAff) import Effect.Class (liftEffect) import Effect.Exception (throw) +import Partial.Unsafe (unsafePartial) import Prelude (join) as Bind -- The constraints don't precisely match those of Plutus: @@ -234,24 +209,24 @@ import Prelude (join) as Bind processLookupsAndConstraints :: TxConstraints -> ConstraintsM (Either MkUnbalancedTxError Unit) -processLookupsAndConstraints - (TxConstraints { constraints }) = runExceptT do +processLookupsAndConstraints constraints = runExceptT do -- Hash all the MintingPolicys and Scripts beforehand. These maps are lost -- after we `runReaderT`, unlike Plutus that has a `Map` instead of `Array`. lookups <- use _lookups <#> unwrap let - mps = lookups.mps - scripts = lookups.scripts - mpsHashes = map mintingPolicyHash mps - validatorHashes = map validatorHash scripts - mpsMap = fromFoldable $ zip mpsHashes mps - osMap = fromFoldable $ zip validatorHashes scripts + plutusMintingPolicies = + fromFoldable $ + zip (PlutusScript.hash <$> lookups.plutusMintingPolicies) + lookups.plutusMintingPolicies + plutusScripts = + fromFoldable $ + zip (PlutusScript.hash <$> lookups.scripts) lookups.scripts + ctx = { plutusMintingPolicies, plutusScripts } timeConstraintsSolved <- except $ resumeTimeConstraints constraints - ExceptT $ foldConstraints (processConstraint mpsMap osMap) - timeConstraintsSolved + ExceptT $ foldConstraints (processConstraint ctx) timeConstraintsSolved ExceptT addFakeScriptDataHash ExceptT addMissingValueSpent ExceptT updateUsedUtxos @@ -284,7 +259,7 @@ runConstraintsM lookups txConstraints = do let initCps :: ConstraintProcessingState initCps = - { transaction: mempty + { transaction: Transaction.empty , usedUtxos: Map.empty , valueSpentBalancesInputs: ValueSpentBalances { required: mempty, provided: mempty } @@ -314,11 +289,14 @@ addFakeScriptDataHash = runExceptT do dats <- use _datums costModels <- use _costModels -- Use both script and minting redeemers in the order they were appended. - reds <- use (_redeemers <<< to (map unindexedRedeemerToRedeemer)) tx <- use _cpsTransaction + let + ctx = mkRedeemersContext tx + reds <- ExceptT $ use _redeemers <#> attachRedeemers ctx >>> lmap + CannotAttachRedeemer tx' <- ExceptT $ liftEffect $ setScriptDataHash costModels reds dats tx <#> Right - _cpsTransaction .= tx' + _cpsTransaction .= (tx' # _witnessSet <<< Cardano._redeemers .~ reds) -- | Add the remaining balance of the total value that the tx must spend. -- | See note [Balance of value spent] @@ -327,7 +305,7 @@ addMissingValueSpent addMissingValueSpent = do missing <- gets totalMissingValue networkId <- getNetworkId - if isZero missing then pure $ Right unit + if missing == mempty then pure $ Right unit else runExceptT do -- add 'missing' to the transaction's outputs. This ensures that the -- wallet will add a corresponding input when balancing the @@ -335,19 +313,25 @@ addMissingValueSpent = do -- Step 4 of the process described in [Balance of value spent] lookups <- use _lookups <#> unwrap let - pkh' = lookups.ownPaymentPubKeyHash - skh' = lookups.ownStakePubKeyHash + pkh' = map unwrap lookups.ownPaymentPubKeyHash + skh' = map unwrap lookups.ownStakePubKeyHash -- Potential fix me: This logic may be suspect: txOutAddress <- case pkh', skh' of - Nothing, Nothing -> throwError OwnPubKeyAndStakeKeyMissing - Just pkh, Just skh -> pure $ payPubKeyHashBaseAddress networkId pkh skh - Just pkh, Nothing -> pure $ payPubKeyHashEnterpriseAddress networkId pkh - Nothing, Just skh -> pure $ stakePubKeyHashRewardAddress networkId skh + Just pkh, Just skh -> pure $ BaseAddress + { networkId + , paymentCredential: wrap $ PubKeyHashCredential pkh + , stakeCredential: wrap $ PubKeyHashCredential skh + } + Just pkh, Nothing -> pure $ EnterpriseAddress + { networkId, paymentCredential: wrap $ PubKeyHashCredential pkh } + Nothing, _ -> throwError OwnPubKeyAndStakeKeyMissing + missingValue <- maybe (throwError NumericOverflow) pure $ Val.toValue + missing let txOut = TransactionOutput { address: txOutAddress - , amount: missing - , datum: NoOutputDatum + , amount: missingValue + , datum: Nothing , scriptRef: Nothing } _cpsTransaction <<< _body <<< _outputs %= Array.(:) txOut @@ -357,12 +341,10 @@ updateUsedUtxos updateUsedUtxos = runExceptT do txOutputs <- use _lookups <#> unwrap >>> _.txOutputs refScriptsUtxoMap <- use _refScriptsUtxoMap - networkId <- lift getNetworkId let cTxOutputs :: Map TransactionInput TransactionOutput cTxOutputs = (txOutputs `union` refScriptsUtxoMap) - <#> fromPlutusTxOutputWithRefScript networkId -- Left bias towards original map, hence `flip`: _cpsUsedUtxos %= flip union cTxOutputs @@ -406,54 +388,53 @@ lookupTxOutRef lookupTxOutRef oref = case _ of Just inputWithRefScript -> lookup oref (utxoWithScriptRef inputWithRefScript) - # maybe (lookupTxOutRef oref Nothing) (map Right <<< convertTxOutput) + # maybe (lookupTxOutRef oref Nothing) (pure <<< Right) Nothing -> runExceptT do utxos <- use _lookups <#> unwrap >>> _.txOutputs - txOutput <- liftM (TxOutRefNotFound oref) (lookup oref utxos) - lift $ convertTxOutput txOutput - where - convertTxOutput - :: Plutus.TransactionOutputWithRefScript -> ConstraintsM TransactionOutput - convertTxOutput txOutput = - flip fromPlutusTxOutputWithRefScript txOutput <$> getNetworkId + liftM (TxOutRefNotFound oref) (lookup oref utxos) lookupDatum :: DataHash - -> ConstraintsM (Either MkUnbalancedTxError Datum) + -> ConstraintsM (Either MkUnbalancedTxError PlutusData) lookupDatum dh = do otherDt <- use _lookups <#> unwrap >>> _.datums pure $ note (DatumNotFound dh) $ lookup dh otherDt lookupMintingPolicy - :: MintingPolicyHash - -> Map MintingPolicyHash MintingPolicy - -> Either MkUnbalancedTxError MintingPolicy + :: forall a + . ScriptHash + -> Map ScriptHash a + -> Either MkUnbalancedTxError a lookupMintingPolicy mph mpsMap = note (MintingPolicyNotFound mph) $ lookup mph mpsMap lookupValidator - :: ValidatorHash - -> Map ValidatorHash Validator - -> Either MkUnbalancedTxError Validator + :: ScriptHash + -> Map ScriptHash PlutusScript + -> Either MkUnbalancedTxError PlutusScript lookupValidator vh osMap = note (ValidatorHashNotFound vh) $ lookup vh osMap +-- Ensures uniqueness +appendInputs + :: Array TransactionInput -> Array TransactionInput -> Array TransactionInput +appendInputs a b = Set.toUnfoldable (Set.fromFoldable a <> Set.fromFoldable b) + processScriptRefUnspentOut - :: forall (scriptHash :: Type) - . Newtype scriptHash ScriptHash - => scriptHash + :: ScriptHash -> InputWithScriptRef -> ConstraintsM (Either MkUnbalancedTxError Unit) processScriptRefUnspentOut scriptHash inputWithRefScript = do unspentOut <- case inputWithRefScript of SpendInput unspentOut -> do - _cpsTransaction <<< _body <<< _inputs %= Set.insert - (_.input <<< unwrap $ unspentOut) + _cpsTransaction <<< _body <<< _inputs %= + appendInputs [ _.input <<< unwrap $ unspentOut ] pure unspentOut RefInput unspentOut -> do let refInput = (unwrap unspentOut).input - _cpsTransaction <<< _body <<< _referenceInputs %= Set.insert refInput + _cpsTransaction <<< _body <<< _referenceInputs %= + appendInputs [ refInput ] pure unspentOut updateRefScriptsUtxoMap unspentOut @@ -470,13 +451,14 @@ processScriptRefUnspentOut scriptHash inputWithRefScript = do checkScriptRef (TransactionUnspentOutput { output }) = let refScriptHash :: Maybe ScriptHash - refScriptHash = _.referenceScript $ unwrap $ (unwrap output).output + refScriptHash = (unwrap output).scriptRef <#> case _ of + NativeScriptRef ns -> NativeScript.hash ns + PlutusScriptRef ps -> PlutusScript.hash ps err :: ConstraintsM (Either MkUnbalancedTxError Unit) - err = pure $ throwError $ WrongRefScriptHash refScriptHash - (unwrap output).output + err = pure $ throwError $ WrongRefScriptHash refScriptHash output in - if Just (unwrap scriptHash) /= refScriptHash then err + if Just scriptHash /= refScriptHash then err else pure (Right unit) checkRefNative @@ -484,7 +466,7 @@ checkRefNative -> ConstraintsM (Either MkUnbalancedTxError Boolean) checkRefNative scriptRef = let - out = (unwrap ((unwrap uout).output)).output + out = (unwrap uout).output in pure $ note (WrongRefScriptHash Nothing out) $ isNative (unwrap (unwrap uout).output).scriptRef @@ -504,11 +486,14 @@ checkRefNative scriptRef = -- | possible. Fails if a hash is missing from the lookups, or if an output -- | of the wrong type is spent. processConstraint - :: Map MintingPolicyHash MintingPolicy - -> Map ValidatorHash Validator + :: { plutusMintingPolicies :: Map ScriptHash PlutusScript + , plutusScripts :: Map ScriptHash PlutusScript + } -> TxConstraint -> ConstraintsM (Either MkUnbalancedTxError Unit) -processConstraint mpsMap osMap c = do +processConstraint + ctx@{ plutusMintingPolicies, plutusScripts } + c = do queryHandle <- lift $ getQueryHandle case c of MustIncludeDatum dat -> pure <$> addDatum dat @@ -531,42 +516,41 @@ processConstraint mpsMap osMap c = do -- the corresponding `paymentPubKey` lookup. In the next major version, -- we might wish to revise this -- See https://github.com/Plutonomicon/cardano-transaction-lib/issues/569 - _cpsTransaction <<< _body <<< _requiredSigners <>= Just + _cpsTransaction <<< _body <<< _requiredSigners <>= [ wrap $ unwrap $ unwrap pkh ] - MustSpendAtLeast plutusValue -> do - let value = fromPlutusValue plutusValue + MustSpendAtLeast value -> do runExceptT $ _valueSpentBalancesInputs <>= requireValue value - MustProduceAtLeast plutusValue -> do - let value = fromPlutusValue plutusValue + MustProduceAtLeast value -> do runExceptT $ _valueSpentBalancesOutputs <>= requireValue value MustSpendPubKeyOutput txo -> runExceptT do TransactionOutput { amount } <- ExceptT $ lookupTxOutRef txo Nothing -- POTENTIAL FIX ME: Plutus has Tx.TxIn and Tx.PubKeyTxIn -- TxIn -- keeps track TransactionInput and TxInType (the input type, whether -- consuming script, public key or simple script) - _cpsTransaction <<< _body <<< _inputs %= Set.insert txo + _cpsTransaction <<< _body <<< _inputs %= appendInputs [ txo ] _valueSpentBalancesInputs <>= provideValue amount MustSpendScriptOutput txo red scriptRefUnspentOut -> runExceptT do txOut <- ExceptT $ lookupTxOutRef txo scriptRefUnspentOut case txOut of - TransactionOutput { datum: NoOutputDatum } -> + TransactionOutput { datum: Nothing } -> throwError $ TxOutRefWrongType txo TransactionOutput { address, amount, datum: datum' } -> do vHash <- liftM (CannotGetValidatorHashFromAddress address) - (addressPaymentValidatorHash address) + (getPaymentCredential address >>= unwrap >>> asScriptHash) case scriptRefUnspentOut of Nothing -> do plutusScript <- - except $ unwrap <$> lookupValidator vHash osMap - lift $ attachToCps attachPlutusScript plutusScript + except $ lookupValidator vHash plutusScripts + lift $ attachToCps (map pure <<< attachPlutusScript) + plutusScript Just scriptRefUnspentOut' -> ExceptT $ processScriptRefUnspentOut vHash scriptRefUnspentOut' -- Note: Plutus uses `TxIn` to attach a redeemer and datum. -- Use the datum hash inside the lookup case datum' of - OutputDatumHash dHash -> do + Just (OutputDatumHash dHash) -> do dat <- ExceptT do mDatumLookup <- lookupDatum dHash if isRight mDatumLookup then @@ -577,222 +561,215 @@ processConstraint mpsMap osMap c = do >>> note (CannotQueryDatum dHash) lift $ addDatum dat - OutputDatum _ -> pure unit - NoOutputDatum -> throwError CannotFindDatum - _cpsTransaction <<< _body <<< _inputs %= Set.insert txo + Just (OutputDatum _) -> pure unit + Nothing -> throwError CannotFindDatum + _cpsTransaction <<< _body <<< _inputs %= appendInputs [ txo ] let - uiRedeemer = UnindexedRedeemer + dRedeemer :: DetachedRedeemer + dRedeemer = { purpose: ForSpend txo - , datum: unwrap red + , datum: red } - _redeemers <>= [ uiRedeemer ] + _redeemers <>= [ dRedeemer ] _valueSpentBalancesInputs <>= provideValue amount MustSpendNativeScriptOutput txo ns -> runExceptT do - _cpsTransaction <<< _body <<< _inputs %= Set.insert txo + _cpsTransaction <<< _body <<< _inputs %= appendInputs [ txo ] lift $ attachToCps (map pure <<< attachNativeScript) ns MustReferenceOutput refInput -> runExceptT do - _cpsTransaction <<< _body <<< _referenceInputs %= Set.insert refInput - MustMintValue mpsHash red tn i scriptRefUnspentOut -> runExceptT do + _cpsTransaction <<< _body <<< _referenceInputs <>= [ refInput ] + MustMintValue scriptHash red tn i scriptRefUnspentOut -> runExceptT do case scriptRefUnspentOut of Nothing -> do - mp <- except $ lookupMintingPolicy mpsHash mpsMap - ( case mp of - PlutusMintingPolicy p -> - ( lift $ attachToCps - attachPlutusScript - p - ) - NativeMintingPolicy _ -> throwError $ - ExpectedPlutusScriptGotNativeScript mpsHash - ) + mp <- except $ lookupMintingPolicy scriptHash plutusMintingPolicies + lift $ attachToCps (map pure <<< attachPlutusScript) mp Just scriptRefUnspentOut' -> do isNative <- ExceptT $ checkRefNative scriptRefUnspentOut' - when isNative $ throwError $ ExpectedPlutusScriptGotNativeScript - mpsHash - (ExceptT $ processScriptRefUnspentOut mpsHash scriptRefUnspentOut') + when isNative + $ throwError + $ ExpectedPlutusScriptGotNativeScript scriptHash + (ExceptT $ processScriptRefUnspentOut scriptHash scriptRefUnspentOut') - cs <- - liftM (MintingPolicyHashNotCurrencySymbol mpsHash) (mpsSymbol mpsHash) - let value = mkSingletonValue' cs tn + let + mkValue = Value Coin.zero <<< MultiAsset.singleton scriptHash tn + mint = Mint.singleton scriptHash tn i -- If i is negative we are burning tokens. The tokens burned must -- be provided as an input. So we add the value burnt to -- 'valueSpentBalancesInputs'. If i is positive then new tokens are -- created which must be added to 'valueSpentBalancesOutputs'. -- If i is zero we raise error, because of -- https://github.com/Plutonomicon/cardano-transaction-lib/issues/1156 - mintVal <- - if i < zero then do - v <- liftM (CannotMakeValue cs tn i) (value $ negate i) - _valueSpentBalancesInputs <>= provideValue v - pure $ map getNonAdaAsset $ value i - else if i == zero then do - throwError $ CannotMintZero cs tn - else do - v <- liftM (CannotMakeValue cs tn i) (value i) - _valueSpentBalancesOutputs <>= provideValue v - pure $ map getNonAdaAsset $ value i + if Int.toBigInt i < zero then do + let + value = + mkValue $ unsafeFromJust "processConstraints" $ Int.asNegative i + _valueSpentBalancesInputs <>= provideValue value + else if Int.toBigInt i == zero then do + throwError $ CannotMintZero scriptHash tn + else do + let + value = + mkValue $ unsafeFromJust "processConstraints" $ Int.asPositive i + _valueSpentBalancesOutputs <>= provideValue value _redeemers <>= - [ UnindexedRedeemer { purpose: ForMint mpsHash, datum: unwrap red } ] + [ { purpose: ForMint scriptHash, datum: red } ] -- Remove mint redeemers from array before reindexing. - _cpsTransaction <<< _body <<< _mint <>= map wrap mintVal + unsafePartial $ _cpsTransaction <<< _body <<< _mint <>= Just mint MustMintValueUsingNativeScript ns tn i -> runExceptT do - let mpHash = wrap <<< unwrap <<< nativeScriptHash $ ns - + let + cs = NativeScript.hash ns + mkValue = Value Coin.zero <<< MultiAsset.singleton cs tn + mint = Mint.singleton cs tn i lift $ attachToCps (map pure <<< attachNativeScript) ns - - cs <- liftM (MintingPolicyHashNotCurrencySymbol mpHash) (mpsSymbol mpHash) - let value = mkSingletonValue' cs tn -- If i is negative we are burning tokens. The tokens burned must -- be provided as an input. So we add the value burnt to -- 'valueSpentBalancesInputs'. If i is positive then new tokens are -- created which must be added to 'valueSpentBalancesOutputs'. - mintVal <- - if i < zero then do - v <- liftM (CannotMakeValue cs tn i) (value $ negate i) - _valueSpentBalancesInputs <>= provideValue v - pure $ map getNonAdaAsset $ value i - else do - v <- liftM (CannotMakeValue cs tn i) (value i) - _valueSpentBalancesOutputs <>= provideValue v - pure $ map getNonAdaAsset $ value i - - _cpsTransaction <<< _body <<< _mint <>= map wrap mintVal - - MustPayToPubKeyAddress pkh skh mDatum scriptRef plutusValue -> do + if Int.toBigInt i < zero then do + let + value = + mkValue $ unsafeFromJust "processConstraints" $ Int.asNegative i + _valueSpentBalancesInputs <>= provideValue value + else if Int.toBigInt i == zero then do + throwError $ CannotMintZero cs tn + else do + let + value = + mkValue $ unsafeFromJust "processConstraints" $ Int.asPositive i + _valueSpentBalancesOutputs <>= provideValue value + + unsafePartial $ _cpsTransaction <<< _body <<< _mint <>= Just mint + + MustPayToPubKeyAddress pkh skh mDatum scriptRef amount -> do networkId <- getNetworkId - let amount = fromPlutusValue plutusValue runExceptT do - -- If non-inline datum is presented, add it to 'datumWitnesses' and - -- Array of datums. - datum' <- for mDatum \(dat /\ datp) -> do - when (datp == DatumWitness) $ lift $ addDatum dat - pure $ outputDatum dat datp let address = case skh of - Just skh' -> payPubKeyHashBaseAddress networkId pkh skh' - Nothing -> payPubKeyHashEnterpriseAddress networkId pkh + Just skh' -> BaseAddress + { networkId + , paymentCredential: wrap $ PubKeyHashCredential $ unwrap pkh + , stakeCredential: wrap $ PubKeyHashCredential $ unwrap skh' + } + Nothing -> EnterpriseAddress + { networkId + , paymentCredential: wrap $ PubKeyHashCredential $ unwrap pkh + } txOut = TransactionOutput { address , amount - , datum: fromMaybe NoOutputDatum datum' + , datum: uncurry outputDatum <$> mDatum , scriptRef: scriptRef } _cpsTransaction <<< _body <<< _outputs %= Array.(:) txOut _valueSpentBalancesOutputs <>= provideValue amount - MustPayToScript vlh mbCredential dat datp scriptRef plutusValue -> do + MustPayToScript vlh mbCredential dat datp scriptRef amount -> do networkId <- getNetworkId - let amount = fromPlutusValue plutusValue runExceptT do let - datum' = outputDatum dat datp txOut = TransactionOutput { address: case mbCredential of - Nothing -> validatorHashEnterpriseAddress networkId vlh - Just cred -> baseAddressToAddress $ baseAddress - { network: networkId - , paymentCred: scriptHashCredential (unwrap vlh) - , delegationCred: credentialToStakeCredential cred + Nothing -> EnterpriseAddress + { networkId + , paymentCredential: wrap $ ScriptHashCredential vlh + } + Just cred -> BaseAddress + { networkId + , paymentCredential: wrap $ ScriptHashCredential vlh + , stakeCredential: wrap cred } , amount - , datum: datum' + , datum: Just $ outputDatum dat datp , scriptRef: scriptRef } - -- Note we don't `addDatum` as this included as part of `mustPayToScript` - -- constraint already. _cpsTransaction <<< _body <<< _outputs %= Array.(:) txOut _valueSpentBalancesOutputs <>= provideValue amount - MustPayToNativeScript nsh mbCredential plutusValue -> do + MustPayToNativeScript nsh mbCredential amount -> do networkId <- getNetworkId - let amount = fromPlutusValue plutusValue runExceptT do let txOut = TransactionOutput { address: case mbCredential of - Nothing -> validatorHashEnterpriseAddress networkId - (wrap $ unwrap nsh) - Just cred -> baseAddressToAddress $ baseAddress - { network: networkId - , paymentCred: scriptHashCredential (unwrap nsh) - , delegationCred: credentialToStakeCredential cred + Nothing -> EnterpriseAddress + { networkId + , paymentCredential: wrap $ ScriptHashCredential nsh + } + Just cred -> BaseAddress + { networkId + , paymentCredential: wrap $ ScriptHashCredential nsh + , stakeCredential: wrap cred } , amount - , datum: NoOutputDatum + , datum: Nothing , scriptRef: Nothing } _cpsTransaction <<< _body <<< _outputs %= Array.(:) txOut _valueSpentBalancesOutputs <>= provideValue amount MustHashDatum dh dt -> do - let dh' = Hashing.datumHash dt + let dh' = hashPlutusData dt if dh' == dh then pure <$> addDatum dt else pure $ throwError $ DatumWrongHash dh dt MustRegisterStakePubKey skh -> runExceptT do - void $ lift $ addCertificate + lift $ addCertificate $ StakeRegistration - $ keyHashCredential - $ unwrap + $ StakeCredential + $ PubKeyHashCredential $ unwrap skh MustDeregisterStakePubKey pubKey -> runExceptT do - void $ lift $ addCertificate + lift $ addCertificate $ StakeDeregistration - $ keyHashCredential - $ unwrap + $ StakeCredential + $ PubKeyHashCredential $ unwrap pubKey MustRegisterStakeScript scriptHash -> runExceptT do - void $ lift $ addCertificate + lift $ addCertificate $ StakeRegistration - $ scriptHashCredential - $ unwrap scriptHash + $ StakeCredential + $ ScriptHashCredential scriptHash MustDeregisterStakePlutusScript plutusScript redeemerData -> runExceptT do let - cert = StakeDeregistration - ( scriptHashCredential $ unwrap $ plutusScriptStakeValidatorHash - plutusScript + cert = StakeDeregistration $ StakeCredential $ ScriptHashCredential + ( PlutusScript.hash plutusScript ) _redeemers <>= - [ UnindexedRedeemer - { purpose: ForCert cert, datum: unwrap redeemerData } - ] - void $ lift $ addCertificate cert - lift $ attachToCps attachPlutusScript (unwrap plutusScript) + [ { purpose: ForCert cert, datum: redeemerData } ] + lift $ addCertificate cert + lift $ attachToCps (map pure <<< attachPlutusScript) plutusScript MustDeregisterStakeNativeScript stakeValidator -> do - void $ addCertificate $ StakeDeregistration - $ scriptHashCredential - $ unwrap - $ nativeScriptStakeValidatorHash - stakeValidator - pure <$> attachToCps (map pure <<< attachNativeScript) - (unwrap stakeValidator) + addCertificate $ StakeDeregistration + $ wrap + $ ScriptHashCredential + $ NativeScript.hash stakeValidator + pure <$> attachToCps (map pure <<< attachNativeScript) stakeValidator MustRegisterPool poolParams -> runExceptT do - void $ lift $ addCertificate $ PoolRegistration poolParams + lift $ addCertificate $ PoolRegistration poolParams MustRetirePool poolKeyHash epoch -> runExceptT do - void $ lift $ addCertificate $ PoolRetirement { poolKeyHash, epoch } + lift $ addCertificate $ PoolRetirement { poolKeyHash, epoch } MustDelegateStakePubKey stakePubKeyHash poolKeyHash -> runExceptT do - void $ lift $ addCertificate $ - StakeDelegation (keyHashCredential $ unwrap $ unwrap $ stakePubKeyHash) + lift $ addCertificate $ + StakeDelegation + ( StakeCredential $ PubKeyHashCredential $ unwrap $ + stakePubKeyHash + ) poolKeyHash - MustDelegateStakePlutusScript stakeValidator redeemerData poolKeyHash -> + MustDelegateStakePlutusScript stakeValidator redeemerData poolKeyHash -> do runExceptT do let cert = StakeDelegation - ( scriptHashCredential $ unwrap $ plutusScriptStakeValidatorHash - stakeValidator + ( StakeCredential $ ScriptHashCredential + $ PlutusScript.hash stakeValidator ) poolKeyHash lift $ addCertificate cert _redeemers <>= - [ UnindexedRedeemer - { purpose: ForCert cert, datum: unwrap redeemerData } - ] - lift $ attachToCps attachPlutusScript (unwrap stakeValidator) + [ { purpose: ForCert cert, datum: redeemerData } ] + lift $ attachToCps (map pure <<< attachPlutusScript) stakeValidator MustDelegateStakeNativeScript stakeValidator poolKeyHash -> do - void $ addCertificate $ StakeDelegation - ( scriptHashCredential $ unwrap $ nativeScriptStakeValidatorHash + addCertificate $ StakeDelegation + ( StakeCredential $ ScriptHashCredential $ NativeScript.hash stakeValidator ) poolKeyHash - pure <$> attachToCps (map pure <<< attachNativeScript) - (unwrap stakeValidator) + pure <$> attachToCps (map pure <<< attachNativeScript) stakeValidator MustWithdrawStakePubKey spkh -> runExceptT do networkId <- lift getNetworkId mbRewards <- lift $ lift $ wrapQueryM $ getPubKeyHashDelegationsAndRewards @@ -801,42 +778,47 @@ processConstraint mpsMap osMap c = do mbRewards let rewardAddress = - RewardAddress.stakePubKeyHashRewardAddress networkId spkh - _cpsTransaction <<< _body <<< _withdrawals <<< non Map.empty %= - Map.insert rewardAddress (fromMaybe (Coin zero) rewards) + { networkId + , stakeCredential: wrap $ PubKeyHashCredential $ unwrap spkh + } + _cpsTransaction <<< _body <<< _withdrawals %= + Map.insert rewardAddress (fromMaybe Coin.zero rewards) MustWithdrawStakePlutusScript stakeValidator redeemerData -> runExceptT do - let hash = plutusScriptStakeValidatorHash stakeValidator + let hash = PlutusScript.hash stakeValidator networkId <- lift getNetworkId - mbRewards <- lift $ lift $ wrapQueryM $ - getValidatorHashDelegationsAndRewards hash + mbRewards <- lift $ lift $ wrapQueryM + $ getValidatorHashDelegationsAndRewards + $ wrap hash let - rewardAddress = RewardAddress.stakeValidatorHashRewardAddress networkId - hash + rewardAddress = + { networkId + , stakeCredential: StakeCredential $ ScriptHashCredential hash + } ({ rewards }) <- ExceptT $ pure $ note (CannotWithdrawRewardsPlutusScript stakeValidator) mbRewards - _cpsTransaction <<< _body <<< _withdrawals <<< non Map.empty %= - Map.insert rewardAddress (fromMaybe (Coin zero) rewards) + _cpsTransaction <<< _body <<< _withdrawals %= + Map.insert rewardAddress (fromMaybe Coin.zero rewards) _redeemers <>= - [ UnindexedRedeemer - { purpose: ForReward rewardAddress, datum: unwrap redeemerData } - ] - lift $ attachToCps attachPlutusScript (unwrap stakeValidator) + [ { purpose: ForReward rewardAddress, datum: redeemerData } ] + lift $ attachToCps (map pure <<< attachPlutusScript) stakeValidator MustWithdrawStakeNativeScript stakeValidator -> runExceptT do - let hash = nativeScriptStakeValidatorHash stakeValidator + let hash = NativeScript.hash stakeValidator networkId <- lift getNetworkId - mbRewards <- lift $ lift $ wrapQueryM $ - getValidatorHashDelegationsAndRewards hash + mbRewards <- lift $ lift $ wrapQueryM + $ getValidatorHashDelegationsAndRewards + $ wrap hash let - rewardAddress = RewardAddress.stakeValidatorHashRewardAddress networkId - hash + rewardAddress = + { networkId + , stakeCredential: StakeCredential $ ScriptHashCredential hash + } ({ rewards }) <- ExceptT $ pure $ note (CannotWithdrawRewardsNativeScript stakeValidator) mbRewards - _cpsTransaction <<< _body <<< _withdrawals <<< non Map.empty %= - Map.insert rewardAddress (fromMaybe (Coin zero) rewards) - lift $ attachToCps (map pure <<< attachNativeScript) - (unwrap stakeValidator) + _cpsTransaction <<< _body <<< _withdrawals %= + Map.insert rewardAddress (fromMaybe Coin.zero rewards) + lift $ attachToCps (map pure <<< attachNativeScript) stakeValidator MustSatisfyAnyOf xs -> do cps <- get let @@ -856,7 +838,7 @@ processConstraint mpsMap osMap c = do foldM ( \_ constr -> runExceptT do let continue = put cps *> tryNext zs - ( ExceptT $ processConstraint mpsMap osMap constr + ( ExceptT $ processConstraint ctx constr `catchError` \_ -> continue ) `catchError` \_ -> ExceptT continue @@ -866,19 +848,18 @@ processConstraint mpsMap osMap c = do tryNext (toUnfoldable $ map toUnfoldable xs) MustNotBeValid -> runExceptT do _cpsTransaction <<< _isValid .= false + MustRegisterDrep drepCred anchor -> do + { drepDeposit } <- unwrap <$> lift getProtocolParameters + addCertificate $ RegDrepCert drepCred drepDeposit anchor + pure $ Right unit where outputDatum - :: Datum + :: PlutusData -> DatumPresence -> OutputDatum outputDatum dat = case _ of DatumInline -> OutputDatum dat - DatumWitness -> OutputDatumHash $ Hashing.datumHash dat - -credentialToStakeCredential :: Credential -> StakeCredential -credentialToStakeCredential cred = case cred of - PubKeyCredential pubKeyHash -> keyHashCredential (unwrap pubKeyHash) - ScriptCredential scriptHash -> scriptHashCredential (unwrap scriptHash) + DatumWitness -> OutputDatumHash $ Datum.hashPlutusData dat -- Attach a Datum, Redeemer, or PlutusScript depending on the handler. They -- share error type anyway. @@ -890,23 +871,21 @@ attachToCps attachToCps handler object = do tx <- use _cpsTransaction newTx <- liftEffect $ handler object tx - (.=) _cpsTransaction newTx + _cpsTransaction .= newTx -- Attaches datum to the transaction and to Array of datums in the state. addDatum - :: Datum + :: PlutusData -> ConstraintsM Unit addDatum dat = do - attachToCps attachDatum dat + attachToCps (map pure <<< attachDatum) dat _datums <>= Array.singleton dat --- | Returns an index pointing to the location of the newly inserted certificate --- | in the array of transaction certificates. addCertificate :: Certificate -> ConstraintsM Unit addCertificate cert = do - _cpsTransaction <<< _body <<< _certs <<< non [] %= Array.(:) cert + _cpsTransaction <<< _body <<< _certs %= Array.(:) cert getNetworkId :: ConstraintsM NetworkId @@ -914,25 +893,9 @@ getNetworkId = use (_cpsTransaction <<< _body <<< _networkId) >>= maybe (asks _.networkId) pure mkUnbalancedTxImpl - :: forall (validator :: Type) (datum :: Type) (redeemer :: Type) - . ScriptLookups + :: ScriptLookups -> TxConstraints - -> Contract (Either MkUnbalancedTxError UnbalancedTx) + -> Contract (Either MkUnbalancedTxError (Transaction /\ UtxoMap)) mkUnbalancedTxImpl scriptLookups txConstraints = runConstraintsM scriptLookups txConstraints <#> map - \{ transaction, datums, redeemers, usedUtxos } -> - wrap - { transaction: stripDatumsRedeemers $ stripScriptDataHash transaction - , datums - , redeemers - , usedUtxos - } - where - stripScriptDataHash :: Transaction -> Transaction - stripScriptDataHash = - _body <<< _scriptDataHash .~ Nothing - - stripDatumsRedeemers :: Transaction -> Transaction - stripDatumsRedeemers = _witnessSet %~ - over TransactionWitnessSet - _ { plutusData = Nothing, redeemers = Nothing } + \({ transaction, usedUtxos }) -> transaction /\ usedUtxos diff --git a/src/Internal/ProcessConstraints/Error.purs b/src/Internal/ProcessConstraints/Error.purs index e7b96e4ee5..18a944cc8f 100644 --- a/src/Internal/ProcessConstraints/Error.purs +++ b/src/Internal/ProcessConstraints/Error.purs @@ -2,37 +2,32 @@ module Ctl.Internal.ProcessConstraints.Error where import Prelude -import Ctl.Internal.Cardano.Types.NativeScript (pprintNativeScript) -import Ctl.Internal.Cardano.Types.Value (CurrencySymbol, getCurrencySymbol) -import Ctl.Internal.Helpers (bugTrackerLink, pprintTagSet) -import Ctl.Internal.Plutus.Types.Transaction +import Cardano.AsCbor (encodeCbor) +import Cardano.Serialization.Lib (toBytes) +import Cardano.Transaction.Edit (DetachedRedeemer) +import Cardano.Types (DataHash, NativeScript) +import Cardano.Types.Address (Address) +import Cardano.Types.Address as Address +import Cardano.Types.AssetName (AssetName, fromAssetName) +import Cardano.Types.Int as Int +import Cardano.Types.NativeScript (pprintNativeScript) +import Cardano.Types.PlutusData (PlutusData) +import Cardano.Types.PlutusScript (PlutusScript(PlutusScript)) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.ScriptHash (ScriptHash) +import Cardano.Types.StakePubKeyHash (StakePubKeyHash) +import Cardano.Types.TransactionInput (TransactionInput(TransactionInput)) +import Cardano.Types.TransactionOutput ( TransactionOutput , pprintTransactionOutput ) -import Ctl.Internal.Serialization.Address (Address, addressBech32) -import Ctl.Internal.Serialization.Hash - ( ScriptHash - , ed25519KeyHashToBytes - , scriptHashToBytes - ) -import Ctl.Internal.Types.ByteArray (byteArrayToHex) -import Ctl.Internal.Types.Datum (DataHash(DataHash), Datum) +import Ctl.Internal.Helpers (bugTrackerLink, pprintTagSet) import Ctl.Internal.Types.Interval ( POSIXTimeRange , PosixTimeToSlotError , explainPosixTimeToSlotError ) -import Ctl.Internal.Types.PubKeyHash (StakePubKeyHash) -import Ctl.Internal.Types.RawBytes (rawBytesToHex) -import Ctl.Internal.Types.Scripts - ( MintingPolicyHash - , NativeScriptStakeValidator - , PlutusScript(PlutusScript) - , PlutusScriptStakeValidator - , ValidatorHash - ) -import Ctl.Internal.Types.TokenName (TokenName, fromTokenName) -import Ctl.Internal.Types.Transaction (TransactionInput(TransactionInput)) +import Data.ByteArray (byteArrayToHex) import Data.Generic.Rep (class Generic) import Data.Log.Tag (tagSetTag) import Data.Maybe (Maybe(Just, Nothing)) @@ -40,7 +35,6 @@ import Data.Newtype (unwrap) import Data.Show.Generic (genericShow) import Data.Tuple.Nested ((/\)) import Data.UInt as UInt -import JS.BigInt (BigInt) data MkUnbalancedTxError = CannotFindDatum @@ -49,22 +43,24 @@ data MkUnbalancedTxError | CannotSolveTimeConstraints POSIXTimeRange POSIXTimeRange | CannotGetMintingPolicyScriptIndex -- Should be impossible | CannotGetValidatorHashFromAddress Address -- Get `ValidatorHash` from internal `Address` - | CannotMakeValue CurrencySymbol TokenName BigInt + | CannotMakeValue ScriptHash AssetName Int.Int | CannotWithdrawRewardsPubKey StakePubKeyHash - | CannotWithdrawRewardsPlutusScript PlutusScriptStakeValidator - | CannotWithdrawRewardsNativeScript NativeScriptStakeValidator + | CannotWithdrawRewardsPlutusScript PlutusScript + | CannotWithdrawRewardsNativeScript NativeScript | DatumNotFound DataHash - | DatumWrongHash DataHash Datum - | MintingPolicyHashNotCurrencySymbol MintingPolicyHash - | MintingPolicyNotFound MintingPolicyHash + | DatumWrongHash DataHash PlutusData + | MintingPolicyHashNotCurrencySymbol ScriptHash + | MintingPolicyNotFound ScriptHash | OwnPubKeyAndStakeKeyMissing | TxOutRefNotFound TransactionInput | TxOutRefWrongType TransactionInput - | ValidatorHashNotFound ValidatorHash + | ValidatorHashNotFound ScriptHash | WrongRefScriptHash (Maybe ScriptHash) TransactionOutput | CannotSatisfyAny - | ExpectedPlutusScriptGotNativeScript MintingPolicyHash - | CannotMintZero CurrencySymbol TokenName + | ExpectedPlutusScriptGotNativeScript ScriptHash + | CannotMintZero ScriptHash AssetName + | NumericOverflow + | CannotAttachRedeemer DetachedRedeemer derive instance Generic MkUnbalancedTxError _ derive instance Eq MkUnbalancedTxError @@ -76,9 +72,9 @@ instance Show MkUnbalancedTxError where explainMkUnbalancedTxError :: MkUnbalancedTxError -> String explainMkUnbalancedTxError = case _ of CannotFindDatum -> "Cannot find datum" - CannotQueryDatum (DataHash dh) -> + CannotQueryDatum dh -> "Querying for datum by datum hash (" - <> byteArrayToHex dh + <> byteArrayToHex (unwrap $ encodeCbor dh) <> ") failed: no datum found" CannotConvertPOSIXTimeRange tr ttsErr -> "Cannot convert POSIX time range to slot time range.\nRange: " @@ -94,36 +90,38 @@ explainMkUnbalancedTxError = case _ of <> bugTrackerLink CannotGetValidatorHashFromAddress addr -> "Cannot get a payment validator hash from address " <> - addressBech32 addr + Address.toBech32 addr CannotMakeValue _ tn _ -> "Attempted to make an amount with the ADA currency symbol, and " <> "non-empty token name " - <> prettyTokenName tn + <> prettyAssetName tn <> ". This is not allowed, as the ADA currency symbol can only be " <> "combined with the empty token name." CannotWithdrawRewardsPubKey spkh -> "Cannot withdraw rewards, as pubkey " - <> rawBytesToHex (ed25519KeyHashToBytes $ unwrap $ unwrap spkh) + <> byteArrayToHex (unwrap $ encodeCbor $ unwrap spkh) <> " is not registered" CannotWithdrawRewardsPlutusScript pssv -> "Cannot withdraw rewards from Plutus staking script " <> - prettyPlutusScript (unwrap pssv) + prettyPlutusScript pssv CannotWithdrawRewardsNativeScript nssv -> pprintTagSet "Cannot withdraw rewards from native staking script " - ("NativeScript" `tagSetTag` pprintNativeScript (unwrap nssv)) - DatumNotFound (DataHash hash) -> "Datum with hash " <> byteArrayToHex hash <> - " not found." - DatumWrongHash (DataHash dh) datum -> "Datum " + ("NativeScript" `tagSetTag` pprintNativeScript nssv) + DatumNotFound hash -> "Datum with hash " + <> byteArrayToHex (unwrap $ encodeCbor hash) + <> + " not found." + DatumWrongHash dh datum -> "Datum " <> show datum <> " does not have the hash " - <> byteArrayToHex dh + <> byteArrayToHex (unwrap $ encodeCbor dh) MintingPolicyHashNotCurrencySymbol mph -> "Minting policy hash " - <> rawBytesToHex (scriptHashToBytes $ unwrap mph) + <> byteArrayToHex (unwrap $ encodeCbor mph) <> " is not a CurrencySymbol. Please check the validity of the byte representation." MintingPolicyNotFound mp -> "Minting policy with hash " - <> rawBytesToHex (scriptHashToBytes $ unwrap mp) + <> byteArrayToHex (unwrap $ encodeCbor mp) <> " not found in a set of minting policies" OwnPubKeyAndStakeKeyMissing -> "Could not build own address: both payment pubkey and stake pubkey are missing" @@ -136,14 +134,14 @@ explainMkUnbalancedTxError = case _ of <> prettyTxIn ti <> "\nContext: we were trying to spend a script output." ValidatorHashNotFound vh -> "Cannot find validator hash: " <> - rawBytesToHex (scriptHashToBytes $ unwrap vh) + byteArrayToHex (unwrap $ encodeCbor vh) WrongRefScriptHash msh tout -> case msh of Nothing -> pprintTagSet "Output is missing a reference script hash" ("TransactionOutput" `tagSetTag` pprintTransactionOutput tout) Just missingHash -> pprintTagSet ( "TransactionOutput is missing reference script hash " - <> rawBytesToHex (scriptHashToBytes missingHash) + <> byteArrayToHex (unwrap $ encodeCbor missingHash) ) ("TransactionOutput" `tagSetTag` pprintTransactionOutput tout) CannotSatisfyAny -> "One of the following happened:\n" @@ -151,24 +149,28 @@ explainMkUnbalancedTxError = case _ of <> "2. All alternatives of a 'mustSatisfyAnyOf' have failed." ExpectedPlutusScriptGotNativeScript mph -> "Expected a Plutus script, but " - <> rawBytesToHex (scriptHashToBytes $ unwrap mph) + <> byteArrayToHex (unwrap $ encodeCbor mph) <> " is a hash of a native script." CannotMintZero cs tn -> "Cannot mint zero of token " - <> prettyTokenName tn + <> prettyAssetName tn <> " of currency " - <> byteArrayToHex (getCurrencySymbol cs) + <> byteArrayToHex (unwrap $ encodeCbor cs) + NumericOverflow -> "Numeric overflow" + CannotAttachRedeemer redeemer -> do + "Can't attach a redeemer: " <> show redeemer + <> "\nPlease report this as a bug here: " + <> bugTrackerLink where - - prettyTokenName :: TokenName -> String - prettyTokenName = fromTokenName byteArrayToHex show + prettyAssetName :: AssetName -> String + prettyAssetName = fromAssetName byteArrayToHex show prettyPlutusScript :: PlutusScript -> String - prettyPlutusScript (PlutusScript (code /\ lang)) = - show lang <> ": " <> byteArrayToHex code + prettyPlutusScript ps@(PlutusScript (_ /\ lang)) = + show lang <> ": " <> byteArrayToHex (unwrap $ PlutusScript.getBytes ps) prettyTxIn :: TransactionInput -> String prettyTxIn (TransactionInput ti) = - byteArrayToHex (unwrap ti.transactionId) + byteArrayToHex (toBytes $ unwrap ti.transactionId) <> "#" <> UInt.toString ti.index diff --git a/src/Internal/ProcessConstraints/State.purs b/src/Internal/ProcessConstraints/State.purs index a35ae110bf..8f923d2fa0 100644 --- a/src/Internal/ProcessConstraints/State.purs +++ b/src/Internal/ProcessConstraints/State.purs @@ -15,30 +15,26 @@ module Ctl.Internal.ProcessConstraints.State , totalMissingValue , provideValue , requireValue + , sumValueSpentBalances ) where import Prelude hiding (join) +import Cardano.Transaction.Edit (DetachedRedeemer) +import Cardano.Types (CostModel, Language, PlutusData, Transaction, UtxoMap) +import Cardano.Types.Value (Value) import Control.Monad.State.Trans (StateT) -import Ctl.Internal.BalanceTx.RedeemerIndex (UnindexedRedeemer) -import Ctl.Internal.Cardano.Types.Transaction - ( Costmdls - , Transaction - , TransactionOutput - ) -import Ctl.Internal.Cardano.Types.Value (Value, negation, split) import Ctl.Internal.Contract.Monad (Contract) -import Ctl.Internal.Plutus.Types.Transaction (TransactionOutputWithRefScript) as Plutus -import Ctl.Internal.Types.Datum (Datum) import Ctl.Internal.Types.ScriptLookups (ScriptLookups) -import Ctl.Internal.Types.Transaction (TransactionInput) +import Ctl.Internal.Types.Val (Val, split) +import Ctl.Internal.Types.Val as Val import Data.Generic.Rep (class Generic) import Data.Lattice (join) import Data.Lens.Record (prop) import Data.Lens.Types (Lens') import Data.Map (Map) import Data.Show.Generic (genericShow) -import Data.Tuple.Nested ((/\)) +import Data.Tuple (snd) import Type.Proxy (Proxy(Proxy)) -- A `StateT` ontop of `QueryM` ~ ReaderT QueryConfig Aff`. @@ -54,24 +50,23 @@ type ConstraintsM (a :: Type) = type ConstraintProcessingState = { transaction :: Transaction -- ^ The unbalanced transaction that we're building - , usedUtxos :: Map TransactionInput TransactionOutput + , usedUtxos :: UtxoMap -- ^ All UTxOs that are used in the Tx , valueSpentBalancesInputs :: ValueSpentBalances -- ^ Balance of the values given and required for the transaction's inputs , valueSpentBalancesOutputs :: ValueSpentBalances -- ^ Balance of the values produced and required for the transaction's outputs - , datums :: Array Datum + , datums :: Array PlutusData -- ^ Ordered accumulation of datums we can use to `setScriptDataHash` - , redeemers :: Array UnindexedRedeemer + , redeemers :: Array DetachedRedeemer -- ^ Unindexed redeemers that will be attached to the Tx later, on balancing -- stage. , lookups :: ScriptLookups -- ^ ScriptLookups for resolving constraints. Should be treated as an immutable -- value despite living inside the processing state -- TODO: remove: https://github.com/Plutonomicon/cardano-transaction-lib/issues/843 - , refScriptsUtxoMap :: - Map TransactionInput Plutus.TransactionOutputWithRefScript - , costModels :: Costmdls + , refScriptsUtxoMap :: UtxoMap + , costModels :: Map Language CostModel } _cpsTransaction @@ -79,8 +74,7 @@ _cpsTransaction _cpsTransaction = prop (Proxy :: Proxy "transaction") _cpsUsedUtxos - :: Lens' ConstraintProcessingState - (Map TransactionInput TransactionOutput) + :: Lens' ConstraintProcessingState UtxoMap _cpsUsedUtxos = prop (Proxy :: Proxy "usedUtxos") _valueSpentBalancesInputs @@ -92,15 +86,15 @@ _valueSpentBalancesOutputs _valueSpentBalancesOutputs = prop (Proxy :: Proxy "valueSpentBalancesOutputs") _datums - :: Lens' ConstraintProcessingState (Array Datum) + :: Lens' ConstraintProcessingState (Array PlutusData) _datums = prop (Proxy :: Proxy "datums") _costModels - :: Lens' ConstraintProcessingState Costmdls + :: Lens' ConstraintProcessingState (Map Language CostModel) _costModels = prop (Proxy :: Proxy "costModels") _redeemers - :: Lens' ConstraintProcessingState (Array UnindexedRedeemer) + :: Lens' ConstraintProcessingState (Array DetachedRedeemer) _redeemers = prop (Proxy :: Proxy "redeemers") _lookups @@ -108,17 +102,16 @@ _lookups _lookups = prop (Proxy :: Proxy "lookups") _refScriptsUtxoMap - :: Lens' ConstraintProcessingState - (Map TransactionInput Plutus.TransactionOutputWithRefScript) + :: Lens' ConstraintProcessingState UtxoMap _refScriptsUtxoMap = prop (Proxy :: Proxy "refScriptsUtxoMap") -- | The balances we track for computing the missing 'Value' (if any) -- | that needs to be added to the transaction. -- | See note [Balance of value spent]. newtype ValueSpentBalances = ValueSpentBalances - { required :: Value + { required :: Val -- Required value spent by the transaction. - , provided :: Value + , provided :: Val -- Value provided by an input or output of the transaction. } @@ -133,21 +126,26 @@ instance Semigroup ValueSpentBalances where , provided: l.provided `join` r.provided } -missingValueSpent :: ValueSpentBalances -> Value +sumValueSpentBalances + :: ValueSpentBalances -> ValueSpentBalances -> ValueSpentBalances +sumValueSpentBalances (ValueSpentBalances a) (ValueSpentBalances b) = do + let required = a.required <> b.required + let provided = a.provided <> b.provided + ValueSpentBalances { required, provided } + +missingValueSpent :: ValueSpentBalances -> Val missingValueSpent (ValueSpentBalances { required, provided }) = - let - difference = required <> negation provided - _ /\ missing = split difference - in - missing + snd $ split $ Val.minus required provided -totalMissingValue :: ConstraintProcessingState -> Value +totalMissingValue :: ConstraintProcessingState -> Val totalMissingValue { valueSpentBalancesInputs, valueSpentBalancesOutputs } = missingValueSpent valueSpentBalancesInputs `join` missingValueSpent valueSpentBalancesOutputs provideValue :: Value -> ValueSpentBalances -provideValue provided = ValueSpentBalances { provided, required: mempty } +provideValue provided = ValueSpentBalances + { provided: Val.fromValue provided, required: mempty } requireValue :: Value -> ValueSpentBalances -requireValue required = ValueSpentBalances { required, provided: mempty } +requireValue required = ValueSpentBalances + { required: Val.fromValue required, provided: mempty } diff --git a/src/Internal/ProcessConstraints/UnbalancedTx.purs b/src/Internal/ProcessConstraints/UnbalancedTx.purs deleted file mode 100644 index 69c8ea8a43..0000000000 --- a/src/Internal/ProcessConstraints/UnbalancedTx.purs +++ /dev/null @@ -1,31 +0,0 @@ -module Ctl.Internal.ProcessConstraints.UnbalancedTx - ( UnbalancedTx(UnbalancedTx) - ) where - -import Prelude hiding (join) - -import Ctl.Internal.BalanceTx.RedeemerIndex (UnindexedRedeemer) -import Ctl.Internal.Cardano.Types.Transaction (Transaction, TransactionOutput) -import Ctl.Internal.Types.Datum (Datum) -import Ctl.Internal.Types.Transaction (TransactionInput) -import Data.Generic.Rep (class Generic) -import Data.Map (Map) -import Data.Newtype (class Newtype) -import Data.Show.Generic (genericShow) - --- | A newtype for the unbalanced transaction after creating one with datums --- | and redeemers not attached. -newtype UnbalancedTx = UnbalancedTx - { transaction :: Transaction -- the unbalanced tx created - , usedUtxos :: Map TransactionInput TransactionOutput - , datums :: Array Datum -- the array of ordered datums that require attaching - , redeemers :: Array UnindexedRedeemer - } - -derive instance Generic UnbalancedTx _ -derive instance Newtype UnbalancedTx _ -derive newtype instance Eq UnbalancedTx --- derive newtype instance EncodeAeson UnbalancedTx - -instance Show UnbalancedTx where - show = genericShow diff --git a/src/Internal/QueryM.purs b/src/Internal/QueryM.purs index 79137872d6..5dece7cc83 100644 --- a/src/Internal/QueryM.purs +++ b/src/Internal/QueryM.purs @@ -63,6 +63,11 @@ import Affjax.RequestBody as Affjax.RequestBody import Affjax.RequestHeader as Affjax.RequestHeader import Affjax.ResponseFormat as Affjax.ResponseFormat import Affjax.StatusCode as Affjax.StatusCode +import Cardano.Types (PlutusScript) +import Cardano.Types.CborBytes (CborBytes) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.TransactionHash (TransactionHash) +import Cardano.Wallet.Key (PrivatePaymentKey, PrivateStakeKey) import Control.Alt (class Alt) import Control.Alternative (class Alternative) import Control.Monad.Error.Class @@ -132,7 +137,6 @@ import Ctl.Internal.QueryM.Ogmios , PoolParametersR , ReleasedMempool , StakePoolsQueryArgument - , TxHash ) import Ctl.Internal.QueryM.Ogmios as Ogmios import Ctl.Internal.QueryM.UniqueId (ListenerId) @@ -149,13 +153,10 @@ import Ctl.Internal.Service.Error ( ClientError(ClientHttpError, ClientHttpResponseError, ClientDecodeJsonError) , ServiceError(ServiceOtherError) ) -import Ctl.Internal.Types.ByteArray (byteArrayToHex) -import Ctl.Internal.Types.CborBytes (CborBytes) import Ctl.Internal.Types.Chain as Chain -import Ctl.Internal.Types.Scripts (PlutusScript) import Ctl.Internal.Types.SystemStart (SystemStart) -import Ctl.Internal.Wallet.Key (PrivatePaymentKey, PrivateStakeKey) import Data.Bifunctor (lmap) +import Data.ByteArray (byteArrayToHex) import Data.Either (Either(Left, Right), either, isRight) import Data.Foldable (foldl) import Data.HTTP.Method (Method(POST)) @@ -313,7 +314,7 @@ getChainTip = ogmiosChainTipToTip <$> mkOgmiosRequest Ogmios.queryChainTipCall -- Ogmios Local Tx Submission Protocol -------------------------------------------------------------------------------- -submitTxOgmios :: TxHash -> CborBytes -> QueryM Ogmios.SubmitTxR +submitTxOgmios :: TransactionHash -> CborBytes -> QueryM Ogmios.SubmitTxR submitTxOgmios txHash tx = do ws <- asks $ underlyingWebSocket <<< _.ogmiosWs <<< _.runtime listeners' <- asks $ listeners <<< _.ogmiosWs <<< _.runtime @@ -363,7 +364,7 @@ mempoolSnapshotHasTxAff :: OgmiosWebSocket -> Logger -> Ogmios.MempoolSnapshotAcquired - -> TxHash + -> TransactionHash -> Aff Boolean mempoolSnapshotHasTxAff ogmiosWs logger ms txh = unwrap <$> mkOgmiosRequestAff ogmiosWs logger @@ -412,7 +413,7 @@ acquireMempoolSnapshot = mempoolSnapshotHasTx :: Ogmios.MempoolSnapshotAcquired - -> TxHash + -> TransactionHash -> QueryM Boolean mempoolSnapshotHasTx ms txh = unwrap <$> mkOgmiosRequest @@ -486,7 +487,8 @@ postAeson url body = Affjax.request $ Affjax.defaultRequest -- instance (there are some brutal cyclical dependency issues trying to -- write an instance in the `Types.*` modules) scriptToAeson :: PlutusScript -> Aeson -scriptToAeson = encodeAeson <<< byteArrayToHex <<< fst <<< unwrap +scriptToAeson = encodeAeson <<< byteArrayToHex <<< unwrap <<< + PlutusScript.getBytes -------------------------------------------------------------------------------- -- Type-safe `WebSocket` @@ -510,7 +512,7 @@ listeners (WebSocket _ ls) = ls -- OgmiosWebSocket Setup and PrimOps -------------------------------------------------------------------------------- -type IsTxConfirmed = TxHash -> Aff Boolean +type IsTxConfirmed = TransactionHash -> Aff Boolean mkOgmiosWebSocketAff :: IsTxConfirmed @@ -605,16 +607,16 @@ resendPendingSubmitRequests for_ pr' \(listenerId /\ requestBody /\ txHash) -> handlePendingSubmitRequest ms listenerId requestBody txHash where - log :: String -> Boolean -> TxHash -> Aff Unit + log :: String -> Boolean -> TransactionHash -> Aff Unit log label value txHash = liftEffect $ logger Debug $ - label <> ": " <> show value <> " TxHash: " <> show txHash + label <> ": " <> show value <> " TransactionHash: " <> show txHash handlePendingSubmitRequest :: Ogmios.MempoolSnapshotAcquired -> ListenerId -> RequestBody - -> TxHash + -> TransactionHash -> Aff Unit handlePendingSubmitRequest ms listenerId requestBody txHash = do -- Check if the transaction was added to the mempool: @@ -727,7 +729,7 @@ type OgmiosListeners = , systemStart :: ListenerSet Unit Ogmios.OgmiosSystemStart , acquireMempool :: ListenerSet Unit Ogmios.MempoolSnapshotAcquired , releaseMempool :: ListenerSet Unit ReleasedMempool - , mempoolHasTx :: ListenerSet TxHash HasTxR + , mempoolHasTx :: ListenerSet TransactionHash HasTxR , mempoolNextTx :: ListenerSet Unit MaybeMempoolTransaction , mempoolSizeAndCapacity :: ListenerSet Unit Ogmios.MempoolSizeAndCapacity , stakePools :: ListenerSet StakePoolsQueryArgument PoolParametersR @@ -747,7 +749,8 @@ type ListenerSet (request :: Type) (response :: Type) = -- to replay requests in case of a WebSocket failure. } -type SubmitTxListenerSet = ListenerSet (TxHash /\ CborBytes) Ogmios.SubmitTxR +type SubmitTxListenerSet = ListenerSet (TransactionHash /\ CborBytes) + Ogmios.SubmitTxR mkAddMessageListener :: forall (response :: Type) diff --git a/src/Internal/QueryM/Dispatcher.purs b/src/Internal/QueryM/Dispatcher.purs index 7be1da08c6..35f8874159 100644 --- a/src/Internal/QueryM/Dispatcher.purs +++ b/src/Internal/QueryM/Dispatcher.purs @@ -15,8 +15,8 @@ module Ctl.Internal.QueryM.Dispatcher import Prelude import Aeson (Aeson, JsonDecodeError, stringifyAeson) +import Cardano.Types.TransactionHash (TransactionHash) import Ctl.Internal.QueryM.JsonRpc2 (parseJsonRpc2ResponseId) -import Ctl.Internal.QueryM.Ogmios (TxHash) import Ctl.Internal.QueryM.UniqueId (ListenerId) import Data.Either (Either(Left, Right)) import Data.Map (Map) @@ -85,5 +85,5 @@ newPendingRequests = Ref.new Map.empty type PendingRequests = GenericPendingRequests RequestBody -type PendingSubmitTxRequests = GenericPendingRequests (RequestBody /\ TxHash) - +type PendingSubmitTxRequests = GenericPendingRequests + (RequestBody /\ TransactionHash) diff --git a/src/Internal/QueryM/Kupo.purs b/src/Internal/QueryM/Kupo.purs index 85395945ba..3a5eb589b0 100644 --- a/src/Internal/QueryM/Kupo.purs +++ b/src/Internal/QueryM/Kupo.purs @@ -1,7 +1,7 @@ module Ctl.Internal.QueryM.Kupo ( getDatumByHash , getScriptByHash - , getTxMetadata + , getTxAuxiliaryData , getUtxoByOref , getOutputAddressesByTxHash , isTxConfirmed @@ -24,6 +24,34 @@ import Aeson import Affjax (Error, Response, defaultRequest) as Affjax import Affjax.ResponseFormat (string) as Affjax.ResponseFormat import Affjax.StatusCode (StatusCode(StatusCode)) +import Cardano.AsCbor (decodeCbor, encodeCbor) +import Cardano.Serialization.Lib (fromBytes, toBytes) +import Cardano.Types + ( Address + , BigNum + , DataHash + , Language(PlutusV3) + , MultiAsset + , PlutusData + , PlutusScript(PlutusScript) + , ScriptHash + , Slot + , TransactionHash(TransactionHash) + , TransactionInput(TransactionInput) + , TransactionOutput(TransactionOutput) + , UtxoMap + , Value + ) +import Cardano.Types.Address as Address +import Cardano.Types.AssetName (mkAssetName) +import Cardano.Types.AuxiliaryData (AuxiliaryData) +import Cardano.Types.BigNum (toString) as BigNum +import Cardano.Types.CborBytes (CborBytes) +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash, OutputDatum)) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.ScriptRef (ScriptRef(NativeScriptRef, PlutusScriptRef)) +import Cardano.Types.Value as Value import Contract.Log (logTrace') import Control.Alt ((<|>)) import Control.Bind (bindFlipped) @@ -32,20 +60,6 @@ import Control.Monad.Except.Trans (ExceptT(ExceptT), except, runExceptT) import Control.Monad.Reader.Class (asks) import Control.Parallel (parTraverse) import Ctl.Internal.Affjax (request) as Affjax -import Ctl.Internal.Cardano.Types.ScriptRef - ( ScriptRef(NativeScriptRef, PlutusScriptRef) - ) -import Ctl.Internal.Cardano.Types.Transaction - ( TransactionOutput(TransactionOutput) - , UtxoMap - ) -import Ctl.Internal.Cardano.Types.Value - ( NonAdaAsset - , Value - , mkCurrencySymbol - , mkSingletonNonAdaAsset - , mkValue - ) import Ctl.Internal.Contract.QueryHandle.Error ( GetTxMetadataError ( GetTxMetadataClientError @@ -53,48 +67,20 @@ import Ctl.Internal.Contract.QueryHandle.Error , GetTxMetadataMetadataEmptyOrMissingError ) ) -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.Deserialization.NativeScript (decodeNativeScript) -import Ctl.Internal.Deserialization.PlutusData (deserializeData) -import Ctl.Internal.Deserialization.Transaction - ( convertGeneralTransactionMetadata - ) import Ctl.Internal.QueryM (QueryM, handleAffjaxResponse) -import Ctl.Internal.Serialization.Address - ( Address - , Slot - , addressBech32 - , addressFromBech32 - ) -import Ctl.Internal.Serialization.Hash (ScriptHash, scriptHashToBytes) import Ctl.Internal.ServerConfig (ServerConfig, mkHttpUrl) import Ctl.Internal.Service.Error (ClientError(ClientOtherError)) import Ctl.Internal.Service.Helpers (aesonArray, aesonObject, aesonString) -import Ctl.Internal.Types.BigNum (toString) as BigNum -import Ctl.Internal.Types.ByteArray (byteArrayToHex, hexToByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes, hexToCborBytes) -import Ctl.Internal.Types.Datum (DataHash(DataHash), Datum) -import Ctl.Internal.Types.OutputDatum - ( OutputDatum(NoOutputDatum, OutputDatumHash, OutputDatum) - ) -import Ctl.Internal.Types.RawBytes (rawBytesToHex) -import Ctl.Internal.Types.Scripts (plutusV1Script, plutusV2Script) -import Ctl.Internal.Types.TokenName (mkTokenName) -import Ctl.Internal.Types.Transaction - ( TransactionHash(TransactionHash) - , TransactionInput(TransactionInput) - ) -import Ctl.Internal.Types.TransactionMetadata (GeneralTransactionMetadata) import Data.Array (uncons) import Data.Array as Array import Data.Bifunctor (lmap) +import Data.ByteArray (byteArrayToHex, hexToByteArray) import Data.Either (Either(Left, Right), note) -import Data.Foldable (fold) import Data.Generic.Rep (class Generic) import Data.HTTP.Method (Method(GET)) import Data.Lens (_Right, to, (^?)) import Data.Map (Map) -import Data.Map (fromFoldable, isEmpty, lookup, values) as Map +import Data.Map (fromFoldable, lookup, values) as Map import Data.Maybe (Maybe(Just, Nothing), fromMaybe) import Data.Newtype (class Newtype, unwrap, wrap) import Data.Show.Generic (genericShow) @@ -108,7 +94,6 @@ import Effect.Aff (Aff, delay) import Effect.Aff.Class (liftAff) import Foreign.Object (Object) import Foreign.Object (toUnfoldable) as Object -import JS.BigInt (BigInt) -------------------------------------------------------------------------------- -- Requests @@ -116,7 +101,7 @@ import JS.BigInt (BigInt) utxosAt :: Address -> QueryM (Either ClientError UtxoMap) utxosAt address = runExceptT do - let endpoint = "/matches/" <> addressBech32 address <> "?unspent" + let endpoint = "/matches/" <> Address.toBech32 address <> "?unspent" kupoUtxoMap <- ExceptT $ handleAffjaxResponse <$> kupoGetRequest endpoint ExceptT $ resolveKupoUtxoMap kupoUtxoMap @@ -128,15 +113,16 @@ getUtxoByOref oref = runExceptT do pure $ Map.lookup oref utxoMap where endpoint :: String - endpoint = "/matches/" <> outputIndex <> "@" <> txHashHex <> "?unspent" + endpoint = "/matches/" <> outputIndex <> "@" <> txHashToHex txHash <> + "?unspent" where TransactionInput { transactionId: txHash, index } = oref outputIndex :: String outputIndex = UInt.toString index - txHashHex :: String - txHashHex = byteArrayToHex (unwrap txHash) +txHashToHex :: TransactionHash -> String +txHashToHex txHash = byteArrayToHex (toBytes $ unwrap txHash) -- | Specialized function to get addresses only, without resolving script -- | references. Used internally. @@ -149,21 +135,18 @@ getOutputAddressesByTxHash txHash = runExceptT do unwrap >>> _.address where endpoint :: String - endpoint = "/matches/*@" <> txHashHex <> "?unspent" - where - txHashHex :: String - txHashHex = byteArrayToHex (unwrap txHash) + endpoint = "/matches/*@" <> txHashToHex txHash <> "?unspent" -getDatumByHash :: DataHash -> QueryM (Either ClientError (Maybe Datum)) -getDatumByHash (DataHash dataHashBytes) = do - let endpoint = "/datums/" <> byteArrayToHex dataHashBytes +getDatumByHash :: DataHash -> QueryM (Either ClientError (Maybe PlutusData)) +getDatumByHash dataHash = do + let endpoint = "/datums/" <> byteArrayToHex (unwrap $ encodeCbor dataHash) kupoGetRequest endpoint <#> map unwrapKupoDatum <<< handleAffjaxResponse getScriptByHash :: ScriptHash -> QueryM (Either ClientError (Maybe ScriptRef)) getScriptByHash scriptHash = do let - endpoint = "/scripts/" <> rawBytesToHex (scriptHashToBytes scriptHash) + endpoint = "/scripts/" <> byteArrayToHex (unwrap (encodeCbor scriptHash)) kupoGetRequest endpoint <#> map unwrapKupoScriptRef <<< handleAffjaxResponse @@ -175,7 +158,7 @@ isTxConfirmed txHash = do do -- we don't add `?unspent`, because we only care about existence of UTxOs, -- possibly they can be consumed - let endpoint = "/matches/*@" <> byteArrayToHex (unwrap txHash) + let endpoint = "/matches/*@" <> txHashToHex txHash -- Do this clumsy special case logging. It's better than sending it silently logTrace' $ "sending kupo request: " <> endpoint liftAff $ isTxConfirmedAff config txHash @@ -183,33 +166,34 @@ isTxConfirmed txHash = do -- Exported due to Ogmios requiring confirmations at a websocket level isTxConfirmedAff :: ServerConfig -> TransactionHash -> Aff (Either ClientError (Maybe Slot)) -isTxConfirmedAff config (TransactionHash txHash) = runExceptT do - let endpoint = "/matches/*@" <> byteArrayToHex txHash +isTxConfirmedAff config txHash = runExceptT do + let endpoint = "/matches/*@" <> txHashToHex txHash utxos <- ExceptT $ handleAffjaxResponse <$> kupoGetRequestAff config endpoint -- Take the first utxo's slot to give the transactions slot pure $ uncons utxos <#> _.head >>> unwrapKupoUtxoSlot -getTxMetadata +getTxAuxiliaryData :: TransactionHash - -> QueryM (Either GetTxMetadataError GeneralTransactionMetadata) -getTxMetadata txHash = runExceptT do + -> QueryM (Either GetTxMetadataError AuxiliaryData) +getTxAuxiliaryData txHash = runExceptT do ExceptT (lmap GetTxMetadataClientError <$> isTxConfirmed txHash) >>= case _ of Nothing -> throwError GetTxMetadataTxNotFoundError Just slot -> do let endpoint = "/metadata/" <> BigNum.toString (unwrap slot) <> "?transaction_id=" - <> byteArrayToHex (unwrap txHash) - kupoMetadata <- ExceptT $ + <> txHashToHex txHash + kupoAuxData <- ExceptT $ lmap GetTxMetadataClientError <<< handleAffjaxResponse <$> kupoGetRequest endpoint - case unwrapKupoMetadata kupoMetadata of + case unwrapKupoAuxData kupoAuxData of Nothing -> throwError GetTxMetadataMetadataEmptyOrMissingError - Just metadata - | Map.isEmpty (unwrap metadata) -> throwError - GetTxMetadataMetadataEmptyOrMissingError - | otherwise -> pure metadata + Just auxData + | unwrap auxData == mempty -> + throwError GetTxMetadataMetadataEmptyOrMissingError + | otherwise -> + pure auxData -------------------------------------------------------------------------------- -- `utxosAt` response parsing @@ -256,7 +240,9 @@ instance DecodeAeson KupoTransactionOutput where decodeAddress obj = getField obj "address" >>= \x -> note (TypeMismatch "Expected bech32 or base16 encoded Shelley address") - (addressFromBech32 x <|> (fromBytes =<< hexToCborBytes x)) + ( Address.fromBech32 x <|> + (decodeCbor <<< wrap =<< hexToByteArray x) + ) decodeDatumHash :: Object Aeson @@ -274,11 +260,15 @@ instance DecodeAeson KupoTransactionOutput where assets <- getFieldOptional obj "assets" <#> fromMaybe mempty <<< map (Object.toUnfoldable :: _ -> Array _) - mkValue coins <<< fold <$> traverse decodeNonAdaAsset assets + multiAsset <- + note (TypeMismatch "MultiAsset") <<< MultiAsset.sum =<< traverse + decodeMultiAsset + assets + pure $ Value.mkValue coins multiAsset where - decodeNonAdaAsset - :: (String /\ BigInt) -> Either JsonDecodeError NonAdaAsset - decodeNonAdaAsset (assetString /\ assetQuantity) = + decodeMultiAsset + :: (String /\ BigNum) -> Either JsonDecodeError MultiAsset + decodeMultiAsset (assetString /\ assetQuantity) = let csString /\ tnString = case String.indexOf (String.Pattern ".") assetString of @@ -288,14 +278,14 @@ instance DecodeAeson KupoTransactionOutput where String.splitAt ix assetString # \{ before, after } -> before /\ String.drop 1 after in - mkSingletonNonAdaAsset + MultiAsset.singleton <$> - ( note (assetStringTypeMismatch "CurrencySymbol" csString) - (mkCurrencySymbol =<< hexToByteArray csString) + ( note (assetStringTypeMismatch "ScriptHash" csString) + (decodeCbor <<< wrap =<< hexToByteArray csString) ) <*> - ( note (assetStringTypeMismatch "TokenName" tnString) - (mkTokenName =<< hexToByteArray tnString) + ( note (assetStringTypeMismatch "AssetName" tnString) + (mkAssetName =<< hexToByteArray tnString) ) <*> pure assetQuantity where @@ -331,9 +321,12 @@ instance DecodeAeson KupoUtxoMap where decodeTxHash :: Object Aeson -> Either JsonDecodeError TransactionHash decodeTxHash = - flip getField "transaction_id" >=> hexToByteArray >>> case _ of - Nothing -> Left (TypeMismatch "Expected hexstring") - Just txHashBytes -> pure (TransactionHash txHashBytes) + flip getField "transaction_id" + >=> hexToByteArray >>> note (TypeMismatch "Expected hexstring") + >=> fromBytes + >>> note (TypeMismatch "Expected TransactionHash") + >>> + map TransactionHash resolveKupoUtxoMap :: KupoUtxoMap -> QueryM (Either ClientError UtxoMap) resolveKupoUtxoMap (KupoUtxoMap kupoUtxoMap) = @@ -345,19 +338,19 @@ resolveKupoTxOutput (KupoTransactionOutput kupoTxOutput@{ address, amount }) = runExceptT $ mkTxOutput <$> ExceptT resolveDatum <*> ExceptT resolveScriptRef where - mkTxOutput :: OutputDatum -> Maybe ScriptRef -> TransactionOutput + mkTxOutput :: Maybe OutputDatum -> Maybe ScriptRef -> TransactionOutput mkTxOutput datum scriptRef = TransactionOutput { address, amount, datum, scriptRef } - resolveDatum :: QueryM (Either ClientError OutputDatum) + resolveDatum :: QueryM (Either ClientError (Maybe OutputDatum)) resolveDatum = case kupoTxOutput.datumHash of - Nothing -> pure $ Right NoOutputDatum + Nothing -> pure $ Right Nothing Just (datumHash /\ DatumHash) -> - pure $ Right $ OutputDatumHash datumHash + pure $ Right $ Just $ OutputDatumHash datumHash Just (datumHash /\ InlineDatum) -> runExceptT do datum <- ExceptT $ getDatumByHash datumHash - except $ OutputDatum <$> flip note datum + except $ pure <<< OutputDatum <$> flip note datum (ClientOtherError "Kupo: Failed to resolve inline datum") resolveScriptRef :: QueryM (Either ClientError (Maybe ScriptRef)) @@ -373,11 +366,11 @@ resolveKupoTxOutput (KupoTransactionOutput kupoTxOutput@{ address, amount }) = -- `getDatumByHash` response parsing -------------------------------------------------------------------------------- -newtype KupoDatum = KupoDatum (Maybe Datum) +newtype KupoDatum = KupoDatum (Maybe PlutusData) derive instance Newtype KupoDatum _ -unwrapKupoDatum :: KupoDatum -> Maybe Datum +unwrapKupoDatum :: KupoDatum -> Maybe PlutusData unwrapKupoDatum = unwrap instance DecodeAeson KupoDatum where @@ -385,13 +378,17 @@ instance DecodeAeson KupoDatum where | isNull aeson = pure $ KupoDatum Nothing | otherwise = aesonObject (flip getFieldOptional "datum") aeson - >>= pure <<< KupoDatum <<< bindFlipped deserializeData + >>= pure <<< KupoDatum <<< bindFlipped decodeCbor -------------------------------------------------------------------------------- -- `getScriptByHash` response parsing -------------------------------------------------------------------------------- -data KupoScriptLanguage = NativeScript | PlutusV1Script | PlutusV2Script +data KupoScriptLanguage + = NativeScript + | PlutusV1Script + | PlutusV2Script + | PlutusV3Script derive instance Generic KupoScriptLanguage _ @@ -403,9 +400,10 @@ instance DecodeAeson KupoScriptLanguage where "native" -> pure NativeScript "plutus:v1" -> pure PlutusV1Script "plutus:v2" -> pure PlutusV2Script + "plutus:v3" -> pure PlutusV3Script invalid -> Left $ TypeMismatch $ - "language: expected 'native' or 'plutus:v{1|2}', got: " <> invalid + "language: expected 'native' or 'plutus:v{1|2|3}', got: " <> invalid newtype KupoScriptRef = KupoScriptRef (Maybe ScriptRef) @@ -424,11 +422,18 @@ instance DecodeAeson KupoScriptRef where KupoScriptRef <<< Just <$> case language of NativeScript -> - NativeScriptRef <$> decodeNativeScript scriptBytes + NativeScriptRef <$> + note (TypeMismatch "NativeScript") (decodeCbor scriptBytes) PlutusV1Script -> - pure $ PlutusScriptRef $ plutusV1Script scriptBytes + pure $ PlutusScriptRef $ PlutusScript.plutusV1Script $ wrap $ + unwrap scriptBytes PlutusV2Script -> - pure $ PlutusScriptRef $ plutusV2Script scriptBytes + pure $ PlutusScriptRef $ PlutusScript.plutusV2Script $ wrap $ + unwrap scriptBytes + PlutusV3Script -> + -- TODO: add plutusV3Script to Cardano.Types.PlutusScript + pure $ PlutusScriptRef $ PlutusScript $ unwrap scriptBytes /\ + PlutusV3 ------------------------------------------------------------------------------- -- `isTxConfirmed` response parsing @@ -452,28 +457,28 @@ unwrapKupoUtxoSlot :: KupoUtxoSlot -> Slot unwrapKupoUtxoSlot (KupoUtxoSlot slot) = slot -------------------------------------------------------------------------------- --- `getTxMetadata` reponse parsing +-- `getTxAuxiliaryData` response parsing -------------------------------------------------------------------------------- -newtype KupoMetadata = KupoMetadata (Maybe GeneralTransactionMetadata) +newtype KupoAuxiliaryData = KupoAuxiliaryData (Maybe AuxiliaryData) -derive instance Generic KupoMetadata _ -derive instance Eq KupoMetadata +derive instance Generic KupoAuxiliaryData _ +derive instance Eq KupoAuxiliaryData -instance Show KupoMetadata where +instance Show KupoAuxiliaryData where show = genericShow -instance DecodeAeson KupoMetadata where +instance DecodeAeson KupoAuxiliaryData where decodeAeson = decodeAeson >=> case _ of [ { raw: cbor } :: { raw :: CborBytes } ] -> do - metadata <- flip note (fromBytes cbor) $ - TypeMismatch "Hexadecimal encoded Metadata" - pure $ KupoMetadata $ Just $ convertGeneralTransactionMetadata metadata - [] -> Right $ KupoMetadata Nothing + auxData <- note (TypeMismatch "Hexadecimal encoded AuxiliaryData") $ + decodeCbor cbor + pure $ KupoAuxiliaryData $ Just auxData + [] -> Right $ KupoAuxiliaryData Nothing _ -> Left $ TypeMismatch "Singleton or Empty Array" -unwrapKupoMetadata :: KupoMetadata -> Maybe GeneralTransactionMetadata -unwrapKupoMetadata (KupoMetadata mbMetadata) = mbMetadata +unwrapKupoAuxData :: KupoAuxiliaryData -> Maybe AuxiliaryData +unwrapKupoAuxData (KupoAuxiliaryData mAuxData) = mAuxData -------------------------------------------------------------------------------- -- Helpers diff --git a/src/Internal/QueryM/Ogmios.purs b/src/Internal/QueryM/Ogmios.purs index b9a0b0a701..9390021b3b 100644 --- a/src/Internal/QueryM/Ogmios.purs +++ b/src/Internal/QueryM/Ogmios.purs @@ -44,7 +44,6 @@ module Ctl.Internal.QueryM.Ogmios , TxEvaluationFailure(UnparsedError, AdditionalUtxoOverlap, ScriptFailures) , TxEvaluationResult(TxEvaluationResult) , TxEvaluationR(TxEvaluationR) - , TxHash , HasTxR(HasTxR) , MaybeMempoolTransaction(MaybeMempoolTransaction) , acquireMempoolSnapshotCall @@ -66,12 +65,9 @@ module Ctl.Internal.QueryM.Ogmios , releaseMempoolCall , submitTxCall , submitSuccessPartialResp - , slotLengthFactor , parseIpv6String , rationalToSubcoin , showRedeemerPointer - , decodeRedeemerPointer - , redeemerPtrTypeMismatch ) where import Prelude @@ -95,9 +91,28 @@ import Aeson , (.:) , (.:?) ) -import Control.Alt ((<|>)) -import Control.Alternative (guard) -import Ctl.Internal.Cardano.Types.NativeScript +import Cardano.AsCbor (decodeCbor, encodeCbor) +import Cardano.Serialization.Lib (fromBytes, ipv4_new) +import Cardano.Types + ( Bech32String + , BigNum(BigNum) + , Language(PlutusV1, PlutusV2, PlutusV3) + , RedeemerTag + , VRFKeyHash(VRFKeyHash) + ) +import Cardano.Types.AssetName (unAssetName) +import Cardano.Types.BigNum (BigNum) +import Cardano.Types.BigNum (fromBigInt, fromString) as BigNum +import Cardano.Types.CborBytes (CborBytes) +import Cardano.Types.Coin (Coin(Coin)) +import Cardano.Types.CostModel (CostModel(CostModel)) +import Cardano.Types.Ed25519KeyHash (Ed25519KeyHash) +import Cardano.Types.ExUnitPrices (ExUnitPrices(ExUnitPrices)) +import Cardano.Types.ExUnits (ExUnits(ExUnits)) +import Cardano.Types.Int as Cardano +import Cardano.Types.Ipv4 (Ipv4(Ipv4)) +import Cardano.Types.Ipv6 (Ipv6) +import Cardano.Types.NativeScript ( NativeScript ( ScriptPubkey , ScriptAll @@ -107,34 +122,26 @@ import Ctl.Internal.Cardano.Types.NativeScript , TimelockExpiry ) ) -import Ctl.Internal.Cardano.Types.ScriptRef - ( ScriptRef(NativeScriptRef, PlutusScriptRef) +import Cardano.Types.PlutusScript (PlutusScript(PlutusScript)) +import Cardano.Types.PoolMetadata (PoolMetadata(PoolMetadata)) +import Cardano.Types.PoolPubKeyHash (PoolPubKeyHash) +import Cardano.Types.RedeemerTag + ( RedeemerTag(Spend, Mint, Cert, Reward, Vote, Propose) + ) as RedeemerTag +import Cardano.Types.Relay + ( Relay(SingleHostAddr, SingleHostName, MultiHostName) ) -import Ctl.Internal.Cardano.Types.Transaction - ( CostModel(CostModel) - , Costmdls(Costmdls) - , ExUnitPrices - , ExUnits - , Ipv4(Ipv4) - , Ipv6(Ipv6) - , PoolMetadata(PoolMetadata) - , PoolMetadataHash(PoolMetadataHash) - , PoolPubKeyHash - , Relay(MultiHostName, SingleHostAddr, SingleHostName) - , SubCoin - , URL(URL) - , UnitInterval - ) -import Ctl.Internal.Cardano.Types.Value - ( Coin(Coin) - , Value - , getCurrencySymbol - , getLovelace - , getNonAdaAsset - , unwrapNonAdaAsset - , valueToCoin - ) -import Ctl.Internal.Deserialization.FromBytes (fromBytes) +import Cardano.Types.RewardAddress (RewardAddress) +import Cardano.Types.RewardAddress as RewardAddress +import Cardano.Types.ScriptHash (ScriptHash) +import Cardano.Types.ScriptRef (ScriptRef(NativeScriptRef, PlutusScriptRef)) +import Cardano.Types.Slot (Slot(Slot)) +import Cardano.Types.TransactionHash (TransactionHash) +import Cardano.Types.URL (URL(URL)) +import Cardano.Types.UnitInterval (UnitInterval(UnitInterval)) +import Cardano.Types.Value (Value, getMultiAsset, valueToCoin) +import Control.Alt ((<|>)) +import Control.Alternative (guard) import Ctl.Internal.Helpers (encodeMap, showWithParens) import Ctl.Internal.QueryM.JsonRpc2 ( class DecodeOgmios @@ -145,50 +152,27 @@ import Ctl.Internal.QueryM.JsonRpc2 , decodeResult , mkCallType ) -import Ctl.Internal.Serialization.Address (Slot(Slot)) -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash, ScriptHash) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum (fromBigInt, fromString) as BigNum -import Ctl.Internal.Types.ByteArray - ( ByteArray - , byteArrayFromIntArray - , byteArrayToHex - , hexToByteArray - ) -import Ctl.Internal.Types.CborBytes (CborBytes, cborBytesToHex) -import Ctl.Internal.Types.Epoch (Epoch(Epoch)) import Ctl.Internal.Types.EraSummaries ( EraSummaries(EraSummaries) , EraSummary(EraSummary) , EraSummaryParameters(EraSummaryParameters) + , EraSummaryTime(EraSummaryTime) ) -import Ctl.Internal.Types.Int as Csl -import Ctl.Internal.Types.Natural (Natural) -import Ctl.Internal.Types.Natural (fromString) as Natural import Ctl.Internal.Types.ProtocolParameters - ( CoinsPerUtxoUnit(CoinsPerUtxoByte) - , ProtocolParameters(ProtocolParameters) + ( ProtocolParameters(ProtocolParameters) ) import Ctl.Internal.Types.Rational (Rational, (%)) import Ctl.Internal.Types.Rational as Rational -import Ctl.Internal.Types.RedeemerTag (RedeemerTag) -import Ctl.Internal.Types.RedeemerTag (fromString) as RedeemerTag -import Ctl.Internal.Types.RewardAddress (RewardAddress) -import Ctl.Internal.Types.Scripts - ( Language(PlutusV1, PlutusV2) - , PlutusScript(PlutusScript) - ) import Ctl.Internal.Types.SystemStart ( SystemStart , sysStartFromOgmiosTimestamp , sysStartToOgmiosTimestamp ) -import Ctl.Internal.Types.TokenName (getTokenName) -import Ctl.Internal.Types.VRFKeyHash (VRFKeyHash(VRFKeyHash)) import Data.Argonaut.Encode.Encoders as Argonaut import Data.Array (catMaybes) import Data.Array (fromFoldable, length, replicate) as Array import Data.Bifunctor (lmap) +import Data.ByteArray (byteArrayFromIntArray, byteArrayToHex, hexToByteArray) import Data.Either (Either(Left, Right), either, note) import Data.Foldable (fold, foldl) import Data.Generic.Rep (class Generic) @@ -200,7 +184,7 @@ import Data.Map as Map import Data.Maybe (Maybe(Nothing, Just), fromMaybe, maybe) import Data.Newtype (class Newtype, unwrap, wrap) import Data.Show.Generic (genericShow) -import Data.String (Pattern(Pattern), Replacement(Replacement), split) +import Data.String (Pattern(Pattern), Replacement(Replacement)) import Data.String (replaceAll) as String import Data.String.Common (split) as String import Data.String.Utils as StringUtils @@ -211,7 +195,6 @@ import Data.UInt (UInt) import Data.UInt as UInt import Foreign.Object (Object) import Foreign.Object as Object -import JS.BigInt (BigInt) import JS.BigInt as BigInt import Untagged.TypeCheck (class HasRuntimeType) import Untagged.Union (type (|+|), toEither1) @@ -260,7 +243,7 @@ queryDelegationsAndRewards = mkOgmiosCallType } } -type OgmiosAddress = String +type OgmiosAddress = Bech32String -------------------------------------------------------------------------------- -- Local Tx Submission Protocol @@ -269,11 +252,11 @@ type OgmiosAddress = String -- | Sends a serialized signed transaction with its full witness through the -- | Cardano network via Ogmios. -submitTxCall :: JsonRpc2Call (TxHash /\ CborBytes) SubmitTxR +submitTxCall :: JsonRpc2Call (TransactionHash /\ CborBytes) SubmitTxR submitTxCall = mkOgmiosCallType { method: "submitTransaction" , params: \(_ /\ cbor) -> - { transaction: { cbor: cborBytesToHex cbor } + { transaction: { cbor: byteArrayToHex $ unwrap cbor } } } @@ -283,7 +266,7 @@ evaluateTxCall :: JsonRpc2Call (CborBytes /\ AdditionalUtxoSet) TxEvaluationR evaluateTxCall = mkOgmiosCallType { method: "evaluateTransaction" , params: \(cbor /\ utxoqr) -> - { transaction: { cbor: cborBytesToHex cbor } + { transaction: { cbor: byteArrayToHex $ unwrap cbor } , additionalUtxo: utxoqr } } @@ -298,7 +281,7 @@ acquireMempoolSnapshotCall = mkOgmiosCallTypeNoArgs "acquireMempool" mempoolSnapshotHasTxCall - :: MempoolSnapshotAcquired -> JsonRpc2Call TxHash HasTxR + :: MempoolSnapshotAcquired -> JsonRpc2Call TransactionHash HasTxR mempoolSnapshotHasTxCall _ = mkOgmiosCallType { method: "hasTransaction" , params: { id: _ } @@ -366,9 +349,9 @@ instance DecodeOgmios MempoolSnapshotAcquired where -- | The acquired snapshot’s size (in bytes), number of transactions, and capacity -- | (in bytes). newtype MempoolSizeAndCapacity = MempoolSizeAndCapacity - { capacity :: Int - , currentSize :: Int - , numberOfTxs :: Int + { capacity :: Prim.Int + , currentSize :: Prim.Int + , numberOfTxs :: Prim.Int } derive instance Generic MempoolSizeAndCapacity _ @@ -439,12 +422,13 @@ instance DecodeOgmios ReleasedMempool where ---------------- TX SUBMISSION QUERY RESPONSE & PARSING submitSuccessPartialResp - :: TxHash -> { result :: { transaction :: { id :: TxHash } } } + :: TransactionHash + -> { result :: { transaction :: { id :: TransactionHash } } } submitSuccessPartialResp txHash = { "result": { "transaction": { "id": txHash } } } data SubmitTxR - = SubmitTxSuccess TxHash + = SubmitTxSuccess TransactionHash | SubmitFail OgmiosError derive instance Generic SubmitTxR _ @@ -452,8 +436,6 @@ derive instance Generic SubmitTxR _ instance Show SubmitTxR where show = genericShow -type TxHash = ByteArray - instance DecodeOgmios SubmitTxR where decodeOgmios = decodeErrorOrResult { parseError: decodeError } @@ -472,11 +454,11 @@ instance DecodeOgmios SubmitTxR where Left $ TypeMismatch "Expected error code in a range [3000, 3999]" - decodeTxHash :: Aeson -> Either JsonDecodeError TxHash - decodeTxHash = aesonObject $ \o -> - ( getField o "transaction" >>= flip getField "id" >>= hexToByteArray - >>> maybe (Left $ TypeMismatch "Expected hexstring") pure - ) + decodeTxHash :: Aeson -> Either JsonDecodeError TransactionHash + decodeTxHash = aesonObject \o -> do + txHashHex <- getField o "transaction" >>= flip getField "id" + note (TypeMismatch "Expected hexstring of TransactionHash") $ + hexToByteArray txHashHex >>= fromBytes >>> map wrap ---------------- SYSTEM START QUERY RESPONSE & PARSING newtype OgmiosSystemStart = OgmiosSystemStart SystemStart @@ -500,7 +482,7 @@ instance DecodeOgmios OgmiosSystemStart where decodeOgmios = decodeResult decodeAeson ---------------- CURRENT EPOCH QUERY RESPONSE & PARSING -newtype CurrentEpoch = CurrentEpoch BigInt +newtype CurrentEpoch = CurrentEpoch BigNum derive instance Generic CurrentEpoch _ derive instance Newtype CurrentEpoch _ @@ -531,15 +513,23 @@ instance DecodeAeson OgmiosEraSummaries where -- in "start" "end" fields and "slotLength". decodeAeson = aesonArray (map (wrap <<< wrap) <<< traverse decodeEraSummary) where + decodeEraSummaryTime :: Aeson -> Either JsonDecodeError EraSummaryTime + decodeEraSummaryTime = aesonObject \obj -> do + time <- flip getField "seconds" =<< getField obj "time" + slot <- getField obj "slot" + epoch <- getField obj "epoch" + pure $ wrap { time, slot, epoch } + decodeEraSummary :: Aeson -> Either JsonDecodeError EraSummary decodeEraSummary = aesonObject \o -> do - start <- getField o "start" + start <- decodeEraSummaryTime =<< getField o "start" -- The field "end" is required by Ogmios API, but it can optionally return -- Null, so we want to fail if the field is absent but make Null value -- acceptable in presence of the field (hence why "end" is wrapped in -- `Maybe`). end' <- getField o "end" - end <- if isNull end' then pure Nothing else Just <$> decodeAeson end' + end <- + if isNull end' then pure Nothing else Just <$> decodeEraSummaryTime end' parameters <- decodeEraSummaryParameters =<< getField o "parameters" pure $ wrap { start, end, parameters } @@ -547,10 +537,7 @@ instance DecodeAeson OgmiosEraSummaries where :: Object Aeson -> Either JsonDecodeError EraSummaryParameters decodeEraSummaryParameters o = do epochLength <- getField o "epochLength" - slotLength <- wrap <$> - ( (*) slotLengthFactor <$> - (flip getField "seconds" =<< getField o "slotLength") - ) + slotLength <- flip getField "milliseconds" =<< getField o "slotLength" safeZone <- fromMaybe zero <$> getField o "safeZone" pure $ wrap { epochLength, slotLength, safeZone } @@ -558,11 +545,15 @@ instance EncodeAeson OgmiosEraSummaries where encodeAeson (OgmiosEraSummaries (EraSummaries eraSummaries)) = fromArray $ map encodeEraSummary eraSummaries where + encodeEraSummaryTime :: EraSummaryTime -> Aeson + encodeEraSummaryTime (EraSummaryTime { time, slot, epoch }) = + encodeAeson { "time": { "seconds": time }, "slot": slot, "epoch": epoch } + encodeEraSummary :: EraSummary -> Aeson encodeEraSummary (EraSummary { start, end, parameters }) = encodeAeson - { "start": start - , "end": end + { "start": encodeEraSummaryTime start + , "end": encodeEraSummaryTime <$> end , "parameters": encodeEraSummaryParameters parameters } @@ -570,15 +561,10 @@ instance EncodeAeson OgmiosEraSummaries where encodeEraSummaryParameters (EraSummaryParameters params) = encodeAeson { "epochLength": params.epochLength - , "slotLength": { "seconds": params.slotLength } + , "slotLength": { "milliseconds": params.slotLength } , "safeZone": params.safeZone } --- Ogmios returns `slotLength` in seconds, and we use milliseconds, --- so we need to convert between them. -slotLengthFactor :: Number -slotLengthFactor = 1000.0 - instance DecodeOgmios OgmiosEraSummaries where decodeOgmios = decodeResult decodeAeson @@ -661,10 +647,13 @@ instance DecodeOgmios PoolParametersR where decodePoolParameters :: Object Aeson -> Either JsonDecodeError PoolParameters decodePoolParameters objParams = do vrfKeyhash <- decodeVRFKeyHash =<< objParams .: "vrfVerificationKeyHash" - pledge <- objParams .: "pledge" >>= aesonObject (\obj -> obj .: "lovelace") - cost <- objParams .: "cost" >>= aesonObject (\obj -> obj .: "lovelace") + pledge <- objParams .: "pledge" >>= aesonObject \obj -> + obj .: "ada" >>= flip getField "lovelace" + cost <- objParams .: "cost" >>= aesonObject \obj -> + obj .: "ada" >>= flip getField "lovelace" margin <- decodeUnitInterval =<< objParams .: "margin" - rewardAccount <- objParams .: "rewardAccount" + rewardAccount <- objParams .: "rewardAccount" >>= + RewardAddress.fromBech32 >>> note (TypeMismatch "RewardAddress") poolOwners <- objParams .: "owners" relayArr <- objParams .: "relays" relays <- for relayArr decodeRelay @@ -684,8 +673,7 @@ decodeVRFKeyHash :: Aeson -> Either JsonDecodeError VRFKeyHash decodeVRFKeyHash = aesonString $ \vrfKeyhashHex -> do vrfKeyhashBytes <- note (TypeMismatch "VRFKeyHash") $ hexToByteArray vrfKeyhashHex - note (TypeMismatch "VRFKeyHash") $ VRFKeyHash <$> fromBytes - (wrap vrfKeyhashBytes) + note (TypeMismatch "VRFKeyHash") $ VRFKeyHash <$> fromBytes vrfKeyhashBytes decodeUnitInterval :: Aeson -> Either JsonDecodeError UnitInterval decodeUnitInterval aeson = do @@ -694,7 +682,7 @@ decodeUnitInterval aeson = do [ num, den ] -> do numerator <- note (TypeMismatch "BigNum") $ BigNum.fromString num denominator <- note (TypeMismatch "BigNum") $ BigNum.fromString den - pure + pure $ UnitInterval { numerator , denominator } @@ -707,7 +695,8 @@ decodeIpv4 aeson = do bs@[ _, _, _, _ ] -> do ints <- for bs $ note (TypeMismatch "Ipv4") <<< Int.fromString - Ipv4 <$> note (TypeMismatch "Ipv4") (byteArrayFromIntArray ints) + Ipv4 <<< ipv4_new <$> note (TypeMismatch "Ipv4") + (byteArrayFromIntArray ints) _ -> Left $ TypeMismatch "Ipv4" decodeIpv6 :: Aeson -> Either JsonDecodeError Ipv6 @@ -735,7 +724,7 @@ parseIpv6String str = do padded = String.replaceAll (Pattern " ") (Replacement "0") $ fold $ partsFixed <#> StringUtils.padStart 4 - Ipv6 <$> hexToByteArray padded + decodeCbor <<< wrap =<< hexToByteArray padded decodeRelay :: Aeson -> Either JsonDecodeError Relay decodeRelay aeson = do @@ -758,20 +747,22 @@ decodeRelay aeson = do decodePoolMetadata :: Aeson -> Either JsonDecodeError PoolMetadata decodePoolMetadata aeson = do obj <- decodeAeson aeson - hash <- obj .: "hash" >>= note (TypeMismatch "PoolMetadataHash") - <<< map PoolMetadataHash - <<< hexToByteArray + hash <- obj .: "hash" >>= + (hexToByteArray >>> map wrap >=> decodeCbor) >>> + note (TypeMismatch "PoolMetadataHash") url <- obj .: "url" <#> URL pure $ PoolMetadata { hash, url } ---------------- TX EVALUATION QUERY RESPONSE & PARSING -type RedeemerPointer = { redeemerTag :: RedeemerTag, redeemerIndex :: Natural } +type RedeemerPointer = { redeemerTag :: RedeemerTag, redeemerIndex :: UInt } showRedeemerPointer :: RedeemerPointer -> String showRedeemerPointer ptr = show ptr.redeemerTag <> ":" <> show ptr.redeemerIndex -type ExecutionUnits = { memory :: Natural, steps :: Natural } +type ExecutionUnits = { memory :: BigNum, steps :: BigNum } + +type OgmiosRedeemerPtr = { index :: UInt, purpose :: String } newtype TxEvaluationR = TxEvaluationR (Either TxEvaluationFailure TxEvaluationResult) @@ -806,30 +797,38 @@ instance DecodeAeson TxEvaluationResult where :: Aeson -> Either JsonDecodeError (RedeemerPointer /\ ExecutionUnits) decodeRdmrPtrExUnitsItem elem = do res - :: { validator :: String - , budget :: { memory :: Natural, cpu :: Natural } + :: { validator :: OgmiosRedeemerPtr + , budget :: { memory :: BigNum, cpu :: BigNum } } <- decodeAeson elem redeemerPtr <- decodeRedeemerPointer res.validator pure $ redeemerPtr /\ { memory: res.budget.memory, steps: res.budget.cpu } -redeemerPtrTypeMismatch :: JsonDecodeError -redeemerPtrTypeMismatch = TypeMismatch - "Expected redeemer pointer to be encoded as: \ - \^(spend|mint|certificate|withdrawal):[0-9]+$" - -decodeRedeemerPointer :: String -> Either JsonDecodeError RedeemerPointer -decodeRedeemerPointer redeemerPtrRaw = note redeemerPtrTypeMismatch - case split (Pattern ":") redeemerPtrRaw of - [ tagRaw, indexRaw ] -> - { redeemerTag: _, redeemerIndex: _ } - <$> RedeemerTag.fromString tagRaw - <*> Natural.fromString indexRaw - _ -> Nothing +redeemerTypeMismatch :: JsonDecodeError +redeemerTypeMismatch = TypeMismatch + "Expected redeemer to be one of: \ + \(spend|mint|publish|withdraw|vote|propose)" + +decodeRedeemerPointer + :: { index :: UInt, purpose :: String } + -> Either JsonDecodeError RedeemerPointer +decodeRedeemerPointer { index: redeemerIndex, purpose } = + note redeemerTypeMismatch $ { redeemerTag: _, redeemerIndex } <$> + redeemerTagFromString purpose + +redeemerTagFromString :: String -> Maybe RedeemerTag +redeemerTagFromString = case _ of + "spend" -> Just RedeemerTag.Spend + "mint" -> Just RedeemerTag.Mint + "publish" -> Just RedeemerTag.Cert + "withdraw" -> Just RedeemerTag.Reward + "vote" -> Just RedeemerTag.Vote + "propose" -> Just RedeemerTag.Propose + _ -> Nothing type OgmiosDatum = String type OgmiosScript = String type OgmiosTxId = String -type OgmiosTxIn = { txId :: OgmiosTxId, index :: Int } +type OgmiosTxIn = { txId :: OgmiosTxId, index :: Prim.Int } -- | Reason a script failed. -- @@ -878,7 +877,8 @@ instance DecodeAeson ScriptFailure where errorData <- maybe (Left (AtKey "data" MissingValue)) pure error.data case error.code of 3011 -> do - res :: { missingScripts :: Array String } <- decodeAeson errorData + res :: { missingScripts :: Array OgmiosRedeemerPtr } <- decodeAeson + errorData missing <- traverse decodeRedeemerPointer res.missingScripts pure $ MissingRequiredScripts { missing: missing, resolved: Nothing } 3012 -> do @@ -889,14 +889,15 @@ instance DecodeAeson ScriptFailure where 3013 -> do res :: { unsuitableOutputReference :: - { transaction :: { id :: String }, index :: Int } + { transaction :: { id :: String }, index :: Prim.Int } } <- decodeAeson errorData pure $ NonScriptInputReferencedByRedeemer { index: res.unsuitableOutputReference.index , txId: res.unsuitableOutputReference.transaction.id } 3110 -> do - res :: { extraneousRedeemers :: Array String } <- decodeAeson errorData + res :: { extraneousRedeemers :: Array OgmiosRedeemerPtr } <- decodeAeson + errorData ExtraRedeemers <$> traverse decodeRedeemerPointer res.extraneousRedeemers 3111 -> do @@ -906,7 +907,7 @@ instance DecodeAeson ScriptFailure where 3117 -> do res :: { unknownOutputReferences :: - Array { transaction :: { id :: String }, index :: Int } + Array { transaction :: { id :: String }, index :: Prim.Int } } <- decodeAeson errorData pure $ UnknownInputReferencedByRedeemer $ map (\x -> { index: x.index, txId: x.transaction.id }) @@ -947,7 +948,8 @@ instance DecodeAeson TxEvaluationFailure where where parseElem elem = do - res :: { validator :: String, error :: ScriptFailure } <- decodeAeson elem + res :: { validator :: OgmiosRedeemerPtr, error :: ScriptFailure } <- + decodeAeson elem (_ /\ res.error) <$> decodeRedeemerPointer res.validator collectIntoMap :: forall k v. Ord k => Array (k /\ v) -> Map k (List v) @@ -985,31 +987,27 @@ instance DecodeAeson PParamRational where err :: JsonDecodeError err = TypeMismatch "PParamRaional" -rationalToSubcoin :: PParamRational -> Maybe SubCoin +rationalToSubcoin :: PParamRational -> Maybe UnitInterval rationalToSubcoin (PParamRational rat) = do numerator <- BigNum.fromBigInt $ Rational.numerator rat denominator <- BigNum.fromBigInt $ Rational.denominator rat - pure { numerator, denominator } + pure $ UnitInterval { numerator, denominator } + +type OgmiosAdaLovelace = { "ada" :: { "lovelace" :: BigNum } } +type OgmiosBytes = { "bytes" :: UInt } -- | A type that corresponds to Ogmios response. type ProtocolParametersRaw = { "minFeeCoefficient" :: UInt - , "minFeeConstant" :: - { "lovelace" :: UInt } - , "minUtxoDepositCoefficient" :: BigInt - , "maxBlockBodySize" :: - { "bytes" :: UInt } - , "maxBlockHeaderSize" :: - { "bytes" :: UInt } - , "maxTransactionSize" :: - { "bytes" :: UInt } - , "maxValueSize" :: - { "bytes" :: UInt } - , "stakeCredentialDeposit" :: - { "lovelace" :: BigInt } - , "stakePoolDeposit" :: - { "lovelace" :: BigInt } - , "stakePoolRetirementEpochBound" :: BigInt + , "minFeeConstant" :: OgmiosAdaLovelace + , "minUtxoDepositCoefficient" :: BigNum + , "maxBlockBodySize" :: OgmiosBytes + , "maxBlockHeaderSize" :: OgmiosBytes + , "maxTransactionSize" :: OgmiosBytes + , "maxValueSize" :: OgmiosBytes + , "stakeCredentialDeposit" :: OgmiosAdaLovelace + , "stakePoolDeposit" :: OgmiosAdaLovelace + , "stakePoolRetirementEpochBound" :: UInt , "desiredNumberOfStakePools" :: UInt , "stakePoolPledgeInfluence" :: PParamRational , "monetaryExpansion" :: PParamRational @@ -1018,26 +1016,28 @@ type ProtocolParametersRaw = { "major" :: UInt , "minor" :: UInt } - , "minStakePoolCost" :: - { "lovelace" :: BigInt } + , "minStakePoolCost" :: OgmiosAdaLovelace , "plutusCostModels" :: - { "plutus:v1" :: Array Csl.Int - , "plutus:v2" :: Maybe (Array Csl.Int) + { "plutus:v1" :: Array Cardano.Int + , "plutus:v2" :: Maybe (Array Cardano.Int) + , "plutus:v3" :: Maybe (Array Cardano.Int) } , "scriptExecutionPrices" :: { "memory" :: PParamRational , "cpu" :: PParamRational } , "maxExecutionUnitsPerTransaction" :: - { "memory" :: BigInt - , "cpu" :: BigInt + { "memory" :: BigNum + , "cpu" :: BigNum } , "maxExecutionUnitsPerBlock" :: - { "memory" :: BigInt - , "cpu" :: BigInt + { "memory" :: BigNum + , "cpu" :: BigNum } , "collateralPercentage" :: UInt , "maxCollateralInputs" :: UInt + , "governanceActionDeposit" :: Maybe OgmiosAdaLovelace + , "delegateRepresentativeDeposit" :: Maybe OgmiosAdaLovelace } newtype OgmiosProtocolParameters = OgmiosProtocolParameters ProtocolParameters @@ -1057,28 +1057,29 @@ instance DecodeAeson OgmiosProtocolParameters where { protocolVersion: ps.version.major /\ ps.version.minor -- The following two parameters were removed from Babbage , decentralization: zero - , extraPraosEntropy: Nothing , maxBlockHeaderSize: ps.maxBlockHeaderSize.bytes , maxBlockBodySize: ps.maxBlockBodySize.bytes , maxTxSize: ps.maxTransactionSize.bytes - , txFeeFixed: ps.minFeeConstant.lovelace + , txFeeFixed: wrap ps.minFeeConstant.ada.lovelace , txFeePerByte: ps.minFeeCoefficient - , stakeAddressDeposit: Coin ps.stakeCredentialDeposit.lovelace - , stakePoolDeposit: Coin ps.stakePoolDeposit.lovelace - , minPoolCost: Coin ps.minStakePoolCost.lovelace - , poolRetireMaxEpoch: Epoch ps.stakePoolRetirementEpochBound + , stakeAddressDeposit: wrap ps.stakeCredentialDeposit.ada.lovelace + , stakePoolDeposit: wrap ps.stakePoolDeposit.ada.lovelace + , minPoolCost: wrap ps.minStakePoolCost.ada.lovelace + , poolRetireMaxEpoch: wrap ps.stakePoolRetirementEpochBound , stakePoolTargetNum: ps.desiredNumberOfStakePools , poolPledgeInfluence: unwrap ps.stakePoolPledgeInfluence , monetaryExpansion: unwrap ps.monetaryExpansion , treasuryCut: unwrap ps.treasuryExpansion -- Rational - , coinsPerUtxoUnit: CoinsPerUtxoByte (Coin ps.minUtxoDepositCoefficient) - , costModels: Costmdls $ Map.fromFoldable $ catMaybes + , coinsPerUtxoByte: wrap ps.minUtxoDepositCoefficient + , costModels: Map.fromFoldable $ catMaybes [ pure ( PlutusV1 /\ CostModel ps.plutusCostModels."plutus:v1" ) - , (PlutusV2 /\ _) <<< CostModel <$> + , Tuple PlutusV2 <<< CostModel <$> ps.plutusCostModels."plutus:v2" + , Tuple PlutusV3 <<< CostModel <$> + ps.plutusCostModels."plutus:v3" ] , prices: prices , maxTxExUnits: decodeExUnits ps.maxExecutionUnitsPerTransaction @@ -1086,15 +1087,22 @@ instance DecodeAeson OgmiosProtocolParameters where , maxValueSize: ps.maxValueSize.bytes , collateralPercent: ps.collateralPercentage , maxCollateralInputs: ps.maxCollateralInputs + , govActionDeposit: + -- NOTE: Conway fields should be optional to enable integration tests. + -- Reason: cardano-testnet runs in the Babbage era. + maybe mempty (wrap <<< _.ada.lovelace) ps.governanceActionDeposit + , drepDeposit: + maybe mempty (wrap <<< _.ada.lovelace) + ps.delegateRepresentativeDeposit } where decodeExUnits - :: { memory :: BigInt, cpu :: BigInt } -> ExUnits - decodeExUnits { memory, cpu } = { mem: memory, steps: cpu } + :: { memory :: BigNum, cpu :: BigNum } -> ExUnits + decodeExUnits { memory, cpu } = ExUnits { mem: memory, steps: cpu } decodePrices :: ProtocolParametersRaw -> Either JsonDecodeError ExUnitPrices - decodePrices ps = note (TypeMismatch "ExUnitPrices") do + decodePrices ps = note (TypeMismatch "ExUnitPrices") $ ExUnitPrices <$> do memPrice <- rationalToSubcoin ps.scriptExecutionPrices.memory stepPrice <- rationalToSubcoin ps.scriptExecutionPrices.cpu pure { memPrice, stepPrice } -- ExUnits @@ -1215,15 +1223,20 @@ instance EncodeAeson AdditionalUtxoSet where encodeScriptRef :: ScriptRef -> Aeson encodeScriptRef (NativeScriptRef s) = - encodeAeson $ + encodeAeson { "language": "native" -- NOTE: We omit the cbor argument. , "json": (encodeNativeScript s) } - encodeScriptRef (PlutusScriptRef (PlutusScript (s /\ PlutusV1))) = - encodeAeson { "language": "plutus:v1", "cbor": byteArrayToHex s } - encodeScriptRef (PlutusScriptRef (PlutusScript (s /\ PlutusV2))) = - encodeAeson { "language": "plutus:v2", "cbor": byteArrayToHex s } + encodeScriptRef (PlutusScriptRef (PlutusScript (script /\ lang))) = + encodeAeson + { "language": + case lang of + PlutusV1 -> "plutus:v1" + PlutusV2 -> "plutus:v2" + PlutusV3 -> "plutus:v3" + , "cbor": byteArrayToHex script + } encodeValue :: Value -> Aeson encodeValue value = encodeMap $ map encodeMap $ Map.union adaPart nonAdaPart @@ -1231,14 +1244,14 @@ instance EncodeAeson AdditionalUtxoSet where adaPart = Map.fromFoldable [ ( "ada" /\ ( Map.fromFoldable - [ ("lovelace" /\ (value # valueToCoin # getLovelace)) ] + [ ("lovelace" /\ (value # valueToCoin # unwrap)) ] ) ) ] - nonAdaPart = mapKeys (byteArrayToHex <<< getCurrencySymbol) - $ map (mapKeys (byteArrayToHex <<< getTokenName)) - $ unwrapNonAdaAsset - $ getNonAdaAsset value + nonAdaPart = mapKeys (byteArrayToHex <<< unwrap <<< encodeCbor) + $ map (mapKeys (byteArrayToHex <<< unAssetName)) + $ unwrap + $ getMultiAsset value mapKeys :: forall k1 k2 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a mapKeys f = (Map.toUnfoldable :: Map k1 a -> Array (k1 /\ a)) >>> foldl diff --git a/src/Internal/QueryM/Pools.purs b/src/Internal/QueryM/Pools.purs index 8f17cb1f32..d1e9f9c084 100644 --- a/src/Internal/QueryM/Pools.purs +++ b/src/Internal/QueryM/Pools.purs @@ -4,15 +4,14 @@ module Ctl.Internal.QueryM.Pools , getPoolsParameters , getPubKeyHashDelegationsAndRewards , getValidatorHashDelegationsAndRewards - , module X ) where import Prelude -import Ctl.Internal.Cardano.Types.Transaction - ( PoolPubKeyHash - , PoolRegistrationParams - ) +import Cardano.AsCbor (encodeCbor) +import Cardano.Types (PoolParams, PoolPubKeyHash, StakePubKeyHash) +import Cardano.Types.Ed25519KeyHash (toBech32Unsafe) as Ed25519KeyHash +import Cardano.Types.ScriptHash as ScriptHash import Ctl.Internal.Helpers (liftM) import Ctl.Internal.QueryM (QueryM, mkOgmiosRequest) import Ctl.Internal.QueryM.Ogmios @@ -20,28 +19,21 @@ import Ctl.Internal.QueryM.Ogmios , PoolParameters ) import Ctl.Internal.QueryM.Ogmios as Ogmios -import Ctl.Internal.Serialization.Hash - ( ed25519KeyHashToBech32Unsafe - , ed25519KeyHashToBytes - , scriptHashToBech32Unsafe - , scriptHashToBytes - ) -import Ctl.Internal.Types.ByteArray (byteArrayToHex) import Ctl.Internal.Types.DelegationsAndRewards (DelegationsAndRewards) -import Ctl.Internal.Types.DelegationsAndRewards (DelegationsAndRewards) as X -import Ctl.Internal.Types.PubKeyHash (StakePubKeyHash) -import Ctl.Internal.Types.Scripts (StakeValidatorHash) +import Ctl.Internal.Types.StakeValidatorHash (StakeValidatorHash) +import Data.ByteArray (byteArrayToHex) import Data.Map (Map) import Data.Map as Map import Data.Maybe (Maybe(Nothing, Just)) import Data.Newtype (unwrap, wrap) import Data.Tuple (fst) import Effect.Exception (error) +import Partial.Unsafe (unsafePartial) import Record.Builder (build, merge) -- | Get pool parameters of all pools or of the provided pools. getStakePools - :: (Maybe (Array PoolPubKeyHash)) + :: Maybe (Array PoolPubKeyHash) -> QueryM (Map PoolPubKeyHash PoolParameters) getStakePools selected = unwrap <$> mkOgmiosRequest Ogmios.queryStakePoolsCall @@ -52,7 +44,7 @@ getPoolIds :: QueryM (Array PoolPubKeyHash) getPoolIds = (Map.toUnfoldableUnordered >>> map fst) <$> getStakePools Nothing -getPoolParameters :: PoolPubKeyHash -> QueryM PoolRegistrationParams +getPoolParameters :: PoolPubKeyHash -> QueryM PoolParams getPoolParameters poolPubKeyHash = do params <- getPoolsParameters [ poolPubKeyHash ] res <- liftM (error "Unable to find pool ID in the response") $ Map.lookup @@ -61,14 +53,14 @@ getPoolParameters poolPubKeyHash = do pure res getPoolsParameters - :: Array PoolPubKeyHash -> QueryM (Map PoolPubKeyHash PoolRegistrationParams) + :: Array PoolPubKeyHash -> QueryM (Map PoolPubKeyHash PoolParams) getPoolsParameters poolPubKeyHashes = do response <- getStakePools (Just poolPubKeyHashes) pure $ Map.mapMaybeWithKey - ( \poolPkh params -> Just $ build + ( \poolPkh params -> Just $ wrap $ build ( merge { operator: poolPkh - , poolOwners: params.poolOwners <#> wrap >>> wrap + , poolOwners: params.poolOwners } ) params @@ -85,10 +77,10 @@ getValidatorHashDelegationsAndRewards skh = do pure $ Map.lookup byteHex mp where stringRep :: String - stringRep = scriptHashToBech32Unsafe "script" $ unwrap skh + stringRep = unsafePartial $ ScriptHash.toBech32Unsafe "script" $ unwrap skh byteHex :: String - byteHex = byteArrayToHex $ unwrap $ scriptHashToBytes $ unwrap skh + byteHex = byteArrayToHex $ unwrap $ encodeCbor $ unwrap skh -- TODO: batched variant getPubKeyHashDelegationsAndRewards @@ -100,10 +92,10 @@ getPubKeyHashDelegationsAndRewards pkh = do pure $ Map.lookup byteHex mp where stringRep :: String - stringRep = - ed25519KeyHashToBech32Unsafe "stake_vkh" $ unwrap $ unwrap pkh + stringRep = unsafePartial + $ Ed25519KeyHash.toBech32Unsafe "stake_vkh" + $ unwrap pkh byteHex :: String - byteHex = byteArrayToHex $ unwrap $ ed25519KeyHashToBytes - $ unwrap + byteHex = byteArrayToHex $ unwrap $ encodeCbor $ unwrap pkh diff --git a/src/Internal/QuickCheck.purs b/src/Internal/QuickCheck.purs deleted file mode 100644 index df96c398ff..0000000000 --- a/src/Internal/QuickCheck.purs +++ /dev/null @@ -1,26 +0,0 @@ --- | Utils for QuickCheck -module Ctl.Internal.QuickCheck - ( genPositive - , unMaybeGen - ) where - -import Prelude - -import Data.Maybe (Maybe, fromJust, isJust) -import Data.Ord (abs) -import Partial.Unsafe (unsafePartial) -import Test.QuickCheck.Arbitrary (arbitrary) -import Test.QuickCheck.Gen (Gen, resize, sized) - -unsafeFromJust :: forall a. Maybe a -> a -unsafeFromJust x = unsafePartial $ fromJust x - --- | Run Gen (Maybe a) until it generates Just a, and return a -unMaybeGen :: forall a. Gen (Maybe a) -> Gen a -unMaybeGen gen = do - mx <- gen - if isJust mx then pure $ unsafeFromJust mx - else sized (\n -> resize (n + 1) (unMaybeGen gen)) - -genPositive :: Gen Int -genPositive = abs <$> (arbitrary :: Gen Int) diff --git a/src/Internal/Scripts.purs b/src/Internal/Scripts.purs deleted file mode 100644 index 187fcb588a..0000000000 --- a/src/Internal/Scripts.purs +++ /dev/null @@ -1,92 +0,0 @@ -module Ctl.Internal.Scripts - ( mintingPolicyHash - , nativeScriptHashEnterpriseAddress - , nativeScriptStakeValidatorHash - , plutusScriptStakeValidatorHash - , scriptCurrencySymbol - , validatorHash - , validatorHashBaseAddress - , validatorHashEnterpriseAddress - ) where - -import Prelude - -import Ctl.Internal.Hashing (plutusScriptHash) -import Ctl.Internal.NativeScripts (NativeScriptHash, nativeScriptHash) -import Ctl.Internal.Plutus.Types.CurrencySymbol - ( CurrencySymbol(CurrencySymbol) - ) -import Ctl.Internal.Serialization.Address - ( Address - , NetworkId - , baseAddressToAddress - , enterpriseAddress - , enterpriseAddressToAddress - , scriptAddress - , scriptHashCredential - ) -import Ctl.Internal.Serialization.Hash (scriptHashToBytes) -import Ctl.Internal.Types.Scripts - ( MintingPolicy(NativeMintingPolicy, PlutusMintingPolicy) - , MintingPolicyHash - , NativeScriptStakeValidator - , PlutusScriptStakeValidator - , StakeValidatorHash - , Validator - , ValidatorHash - ) -import Data.Newtype (unwrap, wrap) - --- | Helpers for `PlutusScript` and `ScriptHash` newtype wrappers, separate from --- | the data type definitions to prevent cylic dependencies. - --- | Converts a Plutus-style `MintingPolicy` to an `MintingPolicyHash` -mintingPolicyHash :: MintingPolicy -> MintingPolicyHash -mintingPolicyHash = case _ of - PlutusMintingPolicy script -> wrap $ plutusScriptHash script - NativeMintingPolicy nscript -> wrap $ unwrap $ nativeScriptHash nscript - --- | Converts a Plutus-style `Validator` to an `ValidatorHash` -validatorHash :: Validator -> ValidatorHash -validatorHash = wrap <<< plutusScriptHash <<< unwrap - --- | Converts a Plutus-style `ValidatorHash` to a `Address` as a `BaseAddress` -validatorHashBaseAddress :: NetworkId -> ValidatorHash -> Address -validatorHashBaseAddress networkId = - baseAddressToAddress <<< scriptAddress networkId <<< unwrap - --- | Converts a Plutus-style `ValidatorHash` to an `Address` as an --- | `EnterpriseAddress`. This is likely what you will use since Plutus --- | currently uses `scriptHashAddress` on non-staking addresses which is --- | invoked in `validatorAddress` -validatorHashEnterpriseAddress :: NetworkId -> ValidatorHash -> Address -validatorHashEnterpriseAddress network valHash = - enterpriseAddressToAddress $ - enterpriseAddress - { network - , paymentCred: scriptHashCredential (unwrap valHash) - } - --- | Converts a `NativeScriptHash` to an `Address` as an `EnterpriseAddress`. -nativeScriptHashEnterpriseAddress :: NetworkId -> NativeScriptHash -> Address -nativeScriptHashEnterpriseAddress network nsHash = - validatorHashEnterpriseAddress network (wrap $ unwrap nsHash) - --- | Calculates a hash of a PlutusScript stake validator -plutusScriptStakeValidatorHash - :: PlutusScriptStakeValidator -> StakeValidatorHash -plutusScriptStakeValidatorHash = unwrap >>> plutusScriptHash >>> wrap - --- | Calculates a hash of a NativeScript stake validator -nativeScriptStakeValidatorHash - :: NativeScriptStakeValidator -> StakeValidatorHash -nativeScriptStakeValidatorHash = unwrap >>> nativeScriptHash >>> unwrap >>> wrap - --- | Converts a `MintingPolicy` to a `CurrencySymbol`. -scriptCurrencySymbol :: MintingPolicy -> CurrencySymbol -scriptCurrencySymbol = CurrencySymbol - <<< unwrap - <<< scriptHashToBytes - <<< unwrap - <<< - mintingPolicyHash diff --git a/src/Internal/Serialization.js b/src/Internal/Serialization.js deleted file mode 100644 index ee93d49db9..0000000000 --- a/src/Internal/Serialization.js +++ /dev/null @@ -1,444 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -const setter = prop => obj => value => () => obj["set_" + prop](value); - -export function hashTransaction(body) { - return () => lib.hash_transaction(body); -} - -export function newValue(coin) { - return () => lib.Value.new(coin); -} - -export function newValueFromAssets(multiasset) { - return () => lib.Value.new_from_assets(multiasset); -} - -export const valueSetCoin = setter("coin"); - -export function newTransactionInput(transaction_id) { - return index => () => lib.TransactionInput.new(transaction_id, index); -} - -export function newTransactionInputs() { - return lib.TransactionInputs.new(); -} - -export function addTransactionInput(inputs) { - return input => () => inputs.add(input); -} - -export function newTransactionOutput(address) { - return amount => () => lib.TransactionOutput.new(address, amount); -} - -export function newTransactionOutputs() { - return lib.TransactionOutputs.new(); -} - -export function addTransactionOutput(outputs) { - return output => () => outputs.add(output); -} - -export function newTransactionBody(inputs) { - return outputs => fee => () => - lib.TransactionBody.new_tx_body(inputs, outputs, fee); -} - -export function setTxIsValid(tx) { - return isValid => () => tx.set_is_valid(isValid); -} - -export function newTransaction(body) { - return witness_set => auxiliary_data => () => - lib.Transaction.new(body, witness_set, auxiliary_data); -} - -export function newTransaction_(body) { - return witness_set => () => lib.Transaction.new(body, witness_set); -} - -export function newTransactionUnspentOutput(input) { - return output => () => lib.TransactionUnspentOutput.new(input, output); -} - -export function newMultiAsset() { - return lib.MultiAsset.new(); -} - -export function insertMultiAsset(multiasset) { - return key => value => () => multiasset.insert(key, value); -} - -export function newAssets() { - return lib.Assets.new(); -} - -export function insertAssets(assets) { - return key => value => () => assets.insert(key, value); -} - -export function newAssetName(name) { - return () => lib.AssetName.new(name); -} - -export const transactionOutputSetDataHash = setter("data_hash"); -export const transactionOutputSetPlutusData = setter("plutus_data"); -export const transactionOutputSetScriptRef = setter("script_ref"); - -export function scriptRefNewNativeScript(nativeScript) { - return lib.ScriptRef.new_native_script(nativeScript); -} - -export function scriptRefNewPlutusScript(plutusScript) { - return lib.ScriptRef.new_plutus_script(plutusScript); -} - -export function newVkeywitnesses() { - return lib.Vkeywitnesses.new(); -} - -export function makeVkeywitness(hash) { - return key => () => lib.make_vkey_witness(hash, key); -} - -export function newVkeywitness(vkey) { - return signature => () => lib.Vkeywitness.new(vkey, signature); -} - -export function addVkeywitness(witnesses) { - return witness => () => witnesses.add(witness); -} - -export function newVkeyFromPublicKey(public_key) { - return () => lib.Vkey.new(public_key); -} - -export function publicKeyHash(pk) { - return pk.hash(); -} - -export const transactionWitnessSetSetVkeys = setter("vkeys"); - -export function newCostmdls() { - return lib.Costmdls.new(); -} - -export function defaultCostmdls() { - return lib.TxBuilderConstants.plutus_vasil_cost_models(); -} - -export function costmdlsSetCostModel(cms) { - return lang => cm => () => cms.insert(lang, cm); -} - -export function newCostModel() { - return lib.CostModel.new(); -} - -export function costModelSetCost(cm) { - return op => cost => () => cm.set(op, cost); -} - -export function newPlutusV1() { - return lib.Language.new_plutus_v1(); -} - -export function newPlutusV2() { - return lib.Language.new_plutus_v2(); -} - -export function _hashScriptData(rs) { - return cms => ds => () => { - const list = lib.PlutusList.new(); - ds.forEach(d => list.add(d)); - return lib.hash_script_data(rs, cms, list); - }; -} - -export function _hashScriptDataNoDatums(rs) { - return cms => () => lib.hash_script_data(rs, cms); -} - -export function newRedeemers() { - return lib.Redeemers.new(); -} - -export function addRedeemer(rs) { - return r => () => rs.add(r); -} - -export function setTxBodyReferenceInputs(txBody) { - return referenceInputs => () => txBody.set_reference_inputs(referenceInputs); -} - -export const setTxBodyScriptDataHash = setter("script_data_hash"); -export const setTxBodyMint = setter("mint"); - -export function newMint() { - return lib.Mint.new(); -} - -export function _bigIntToInt(maybe) { - return bigInt => { - try { - const str = bigInt.to_str(); - if (str[0] == "-") { - return maybe.just( - lib.Int.new_negative(lib.BigNum.from_str(str.slice(1))) - ); - } else { - return maybe.just(lib.Int.new(lib.BigNum.from_str(str))); - } - } catch (_) { - return maybe.nothing; - } - }; -} - -export const newMintAssets = lib.MintAssets.new; - -export function insertMintAssets(mint) { - return scriptHash => mintAssets => () => mint.insert(scriptHash, mintAssets); -} - -export function insertMintAsset(mintAssets) { - return assetName => int => () => mintAssets.insert(assetName, int); -} - -export function networkIdTestnet() { - return lib.NetworkId.testnet(); -} - -export function networkIdMainnet() { - return lib.NetworkId.mainnet(); -} - -export function setTxBodyCollateralReturn(txBody) { - return collateralReturn => () => - txBody.set_collateral_return(collateralReturn); -} - -export function setTxBodyTotalCollateral(txBody) { - return totalCollateral => () => txBody.set_total_collateral(totalCollateral); -} - -export const setTxBodyTtl = setter("ttl"); -export const setTxBodyCerts = setter("certs"); - -export function newCertificates() { - return lib.Certificates.new(); -} - -export function newStakeRegistrationCertificate(stakeCredential) { - return () => - lib.Certificate.new_stake_registration( - lib.StakeRegistration.new(stakeCredential) - ); -} - -export function newStakeDeregistrationCertificate(stakeCredential) { - return () => - lib.Certificate.new_stake_deregistration( - lib.StakeDeregistration.new(stakeCredential) - ); -} - -export function newStakeDelegationCertificate(stakeCredential) { - return ed25519KeyHash => () => - lib.Certificate.new_stake_delegation( - lib.StakeDelegation.new(stakeCredential, ed25519KeyHash) - ); -} - -export function newPoolRegistrationCertificate(operator) { - return vrfKeyhash => - pledge => - cost => - margin => - reward_account => - poolOwners => - relays => - poolMetadata => - () => - lib.Certificate.new_pool_registration( - lib.PoolRegistration.new( - lib.PoolParams.new( - operator, - vrfKeyhash, - pledge, - cost, - margin, - reward_account, - poolOwners, - relays, - poolMetadata - ) - ) - ); -} - -export function newUnitInterval(numerator) { - return denominator => () => lib.UnitInterval.new(numerator, denominator); -} - -export function newPoolRetirementCertificate(poolKeyHash) { - return epoch => () => - lib.Certificate.new_pool_retirement( - lib.PoolRetirement.new(poolKeyHash, epoch) - ); -} - -export function newGenesisKeyDelegationCertificate(genesisHash) { - return genesisDelegateHash => vrfKeyhash => () => - lib.Certificate.new_genesis_key_delegation( - lib.GenesisKeyDelegation.new(genesisHash, genesisDelegateHash, vrfKeyhash) - ); -} - -export function addCert(certificates) { - return certificate => () => certificates.add(certificate); -} - -export const setTxBodyCollateral = setter("collateral"); -export const setTxBodyNetworkId = setter("network_id"); - -export function transactionBodySetRequiredSigners(containerHelper) { - return body => keyHashes => () => - body.set_required_signers( - containerHelper.pack(lib.Ed25519KeyHashes, keyHashes) - ); -} - -export const transactionBodySetValidityStartInterval = setter( - "validity_start_interval_bignum" -); - -export function transactionBodySetAuxiliaryDataHash(txBody) { - return hash => () => txBody.set_auxiliary_data_hash(hash); -} - -export function convertPoolOwners(containerHelper) { - return keyHashes => () => - containerHelper.pack(lib.Ed25519KeyHashes, keyHashes); -} - -export function packRelays(containerHelper) { - return relays => containerHelper.pack(lib.Relays, relays); -} - -export function newIpv4(data) { - return () => lib.Ipv4.new(data); -} - -export function newIpv6(data) { - return () => lib.Ipv6.new(data); -} - -export function newSingleHostAddr(port) { - return ipv4 => ipv6 => () => - lib.Relay.new_single_host_addr(lib.SingleHostAddr.new(port, ipv4, ipv6)); -} - -export function newSingleHostName(port) { - return dnsName => () => - lib.Relay.new_single_host_name( - lib.SingleHostName.new(port, lib.DNSRecordAorAAAA.new(dnsName)) - ); -} - -export function newMultiHostName(dnsName) { - return () => - lib.Relay.new_multi_host_name( - lib.MultiHostName.new(lib.DNSRecordSRV.new(dnsName)) - ); -} - -export function newPoolMetadata(url) { - return hash => () => lib.PoolMetadata.new(lib.URL.new(url), hash); -} - -export function newMoveInstantaneousRewardToOtherPot(pot) { - return amount => () => - lib.MoveInstantaneousReward.new_to_other_pot(pot, amount); -} - -export function newMoveInstantaneousRewardToStakeCreds(pot) { - return amounts => () => - lib.MoveInstantaneousReward.new_to_stake_creds(pot, amounts); -} - -export function newMIRToStakeCredentials(containerHelper) { - return entries => () => - containerHelper.packMap(lib.MIRToStakeCredentials, entries); -} - -export function newMoveInstantaneousRewardsCertificate(mir) { - return () => - lib.Certificate.new_move_instantaneous_rewards_cert( - lib.MoveInstantaneousRewardsCert.new(mir) - ); -} - -export function newWithdrawals(containerHelper) { - return entries => () => containerHelper.packMap(lib.Withdrawals, entries); -} - -export const setTxBodyWithdrawals = setter("withdrawals"); -export const setTxBodyUpdate = setter("update"); - -export function newUpdate(ppUpdates) { - return epoch => () => lib.Update.new(ppUpdates, epoch); -} - -export const ppuSetMinfeeA = setter("minfee_a"); -export const ppuSetMinfeeB = setter("minfee_b"); -export const ppuSetMaxBlockBodySize = setter("max_block_body_size"); -export const ppuSetMaxTxSize = setter("max_tx_size"); -export const ppuSetMaxBlockHeaderSize = setter("max_block_header_size"); -export const ppuSetKeyDeposit = setter("key_deposit"); -export const ppuSetPoolDeposit = setter("pool_deposit"); -export const ppuSetMaxEpoch = setter("max_epoch"); -export const ppuSetNOpt = setter("n_opt"); -export const ppuSetPoolPledgeInfluence = setter("pool_pledge_influence"); -export const ppuSetExpansionRate = setter("expansion_rate"); -export const ppuSetTreasuryGrowthRate = setter("treasury_growth_rate"); - -export function newProtocolVersion(major) { - return minor => () => lib.ProtocolVersion.new(major, minor); -} - -export function ppuSetProtocolVersion(ppu) { - return version => () => ppu.set_protocol_version(version); -} - -export const ppuSetMinPoolCost = setter("min_pool_cost"); -export const ppuSetAdaPerUtxoByte = setter("ada_per_utxo_byte"); -export const ppuSetCostModels = setter("cost_models"); - -export function newExUnitPrices(mem_price) { - return step_price => () => lib.ExUnitPrices.new(mem_price, step_price); -} - -export const ppuSetExecutionCosts = setter("execution_costs"); -export const ppuSetMaxTxExUnits = setter("max_tx_ex_units"); -export const ppuSetMaxBlockExUnits = setter("max_block_ex_units"); -export const ppuSetMaxValueSize = setter("max_value_size"); -export const ppuSetCollateralPercentage = setter("collateral_percentage"); -export const ppuSetMaxCollateralInputs = setter("max_collateral_inputs"); - -export function newProtocolParamUpdate() { - return lib.ProtocolParamUpdate.new(); -} - -export function newProposedProtocolParameterUpdates(containerHelper) { - return kvs => () => - containerHelper.packMap(lib.ProposedProtocolParameterUpdates, kvs); -} diff --git a/src/Internal/Serialization.purs b/src/Internal/Serialization.purs deleted file mode 100644 index 9fce4b3485..0000000000 --- a/src/Internal/Serialization.purs +++ /dev/null @@ -1,899 +0,0 @@ -module Ctl.Internal.Serialization - ( convertExUnitPrices - , convertTransaction - , convertTxBody - , convertTxInput - , convertTxOutput - , defaultCostmdls - , convertTransactionUnspentOutput - , convertValue - , serializeData - , hashScriptData - , hashTransaction - , publicKeyHash - , makeVkeywitness - , module Ctl.Internal.Serialization.ToBytes - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.ScriptRef - ( ScriptRef(NativeScriptRef, PlutusScriptRef) - ) as T -import Ctl.Internal.Cardano.Types.Transaction - ( Certificate - ( StakeRegistration - , StakeDeregistration - , StakeDelegation - , PoolRegistration - , PoolRetirement - , GenesisKeyDelegation - , MoveInstantaneousRewardsCert - ) - , CostModel(CostModel) - , Costmdls(Costmdls) - , ExUnitPrices - , GenesisDelegateHash(GenesisDelegateHash) - , GenesisHash(GenesisHash) - , MIRToStakeCredentials(MIRToStakeCredentials) - , Mint(Mint) - , MoveInstantaneousReward(ToOtherPot, ToStakeCreds) - , PoolMetadata(PoolMetadata) - , PoolMetadataHash(PoolMetadataHash) - , ProposedProtocolParameterUpdates - , ProtocolParamUpdate - , Redeemer - , Relay(SingleHostAddr, SingleHostName, MultiHostName) - , Transaction(Transaction) - , TransactionOutput(TransactionOutput) - , TxBody(TxBody) - , URL(URL) - , UnitInterval - , Update - ) as T -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - ) as T -import Ctl.Internal.Cardano.Types.Value as Value -import Ctl.Internal.Deserialization.FromBytes (fromBytes, fromBytesEffect) -import Ctl.Internal.FfiHelpers - ( ContainerHelper - , MaybeFfiHelper - , containerHelper - , maybeFfiHelper - ) -import Ctl.Internal.Helpers (fromJustEff) -import Ctl.Internal.Serialization.Address - ( Address - , RewardAddress - , StakeCredential - ) -import Ctl.Internal.Serialization.Address (NetworkId(TestnetId, MainnetId)) as T -import Ctl.Internal.Serialization.AuxiliaryData (convertAuxiliaryData) -import Ctl.Internal.Serialization.BigInt as Serialization -import Ctl.Internal.Serialization.Hash - ( Ed25519KeyHash - , ScriptHash - , VRFKeyHash - , scriptHashFromBytes - ) -import Ctl.Internal.Serialization.NativeScript (convertNativeScript) -import Ctl.Internal.Serialization.PlutusData (convertPlutusData) -import Ctl.Internal.Serialization.PlutusScript (convertPlutusScript) -import Ctl.Internal.Serialization.ToBytes (toBytes) -import Ctl.Internal.Serialization.Types - ( AssetName - , Assets - , AuxiliaryData - , AuxiliaryDataHash - , BigInt - , Certificate - , Certificates - , CostModel - , Costmdls - , DataHash - , Ed25519KeyHashes - , Ed25519Signature - , ExUnitPrices - , ExUnits - , GenesisDelegateHash - , GenesisHash - , Ipv4 - , Ipv6 - , Language - , MIRToStakeCredentials - , Mint - , MintAssets - , MoveInstantaneousReward - , MultiAsset - , NativeScript - , NetworkId - , PlutusData - , PlutusScript - , PoolMetadata - , PoolMetadataHash - , PrivateKey - , ProposedProtocolParameterUpdates - , ProtocolParamUpdate - , ProtocolVersion - , PublicKey - , Redeemer - , Redeemers - , Relay - , Relays - , ScriptDataHash - , ScriptRef - , Transaction - , TransactionBody - , TransactionHash - , TransactionInput - , TransactionInputs - , TransactionOutput - , TransactionOutputs - , TransactionUnspentOutput - , TransactionWitnessSet - , UnitInterval - , Update - , Value - , Vkey - , Vkeywitness - , Vkeywitnesses - , Withdrawals - ) -import Ctl.Internal.Serialization.WitnessSet - ( convertExUnits - , convertRedeemer - , convertWitnessSet - ) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum (fromBigInt, fromStringUnsafe, toString) as BigNum -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes) -import Ctl.Internal.Types.Int as Csl -import Ctl.Internal.Types.OutputDatum - ( OutputDatum(NoOutputDatum, OutputDatumHash, OutputDatum) - ) -import Ctl.Internal.Types.PlutusData as PlutusData -import Ctl.Internal.Types.RewardAddress (RewardAddress, unRewardAddress) as T -import Ctl.Internal.Types.Scripts (Language(PlutusV1, PlutusV2)) as S -import Ctl.Internal.Types.TokenName (getTokenName) as TokenName -import Ctl.Internal.Types.Transaction (TransactionInput(TransactionInput)) as T -import Ctl.Internal.Types.VRFKeyHash (VRFKeyHash(VRFKeyHash), unVRFKeyHash) as T -import Data.Foldable (class Foldable) -import Data.Foldable (null) as Foldable -import Data.FoldableWithIndex (forWithIndex_) -import Data.Map as Map -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (unwrap, wrap) -import Data.Traversable (for, for_, traverse_) -import Data.Tuple (Tuple(Tuple)) -import Data.Tuple.Nested (type (/\), (/\)) -import Data.UInt (UInt) -import Data.UInt as UInt -import Effect (Effect) -import Untagged.Union (UndefinedOr, maybeToUor) - -foreign import hashTransaction :: TransactionBody -> Effect TransactionHash - -foreign import newValue :: BigNum -> Effect Value -foreign import valueSetCoin :: Value -> BigNum -> Effect Unit -foreign import newValueFromAssets :: MultiAsset -> Effect Value -foreign import newTransactionInput - :: TransactionHash -> UInt -> Effect TransactionInput - -foreign import newTransactionInputs :: Effect TransactionInputs -foreign import addTransactionInput - :: TransactionInputs -> TransactionInput -> Effect Unit - -foreign import newTransactionOutput - :: Address -> Value -> Effect TransactionOutput - -foreign import newTransactionOutputs :: Effect TransactionOutputs -foreign import addTransactionOutput - :: TransactionOutputs -> TransactionOutput -> Effect Unit - -foreign import newTransactionBody - :: TransactionInputs - -> TransactionOutputs - -> BigNum - -> Effect TransactionBody - -foreign import newTransaction - :: TransactionBody - -> TransactionWitnessSet - -> AuxiliaryData - -> Effect Transaction - -foreign import newTransaction_ - :: TransactionBody - -> TransactionWitnessSet - -> Effect Transaction - -foreign import newTransactionUnspentOutput - :: TransactionInput -> TransactionOutput -> Effect TransactionUnspentOutput - -foreign import newMultiAsset :: Effect MultiAsset -foreign import insertMultiAsset - :: MultiAsset -> ScriptHash -> Assets -> Effect Unit - -foreign import newAssets :: Effect Assets -foreign import insertAssets :: Assets -> AssetName -> BigNum -> Effect Unit -foreign import newAssetName :: ByteArray -> Effect AssetName -foreign import transactionOutputSetDataHash - :: TransactionOutput -> DataHash -> Effect Unit - -foreign import transactionOutputSetPlutusData - :: TransactionOutput -> PlutusData -> Effect Unit - -foreign import transactionOutputSetScriptRef - :: TransactionOutput -> ScriptRef -> Effect Unit - -foreign import scriptRefNewNativeScript - :: NativeScript -> ScriptRef - -foreign import scriptRefNewPlutusScript - :: PlutusScript -> ScriptRef - -foreign import newVkeywitnesses :: Effect Vkeywitnesses -foreign import makeVkeywitness - :: TransactionHash -> PrivateKey -> Effect Vkeywitness - -foreign import newVkeywitness :: Vkey -> Ed25519Signature -> Effect Vkeywitness -foreign import addVkeywitness :: Vkeywitnesses -> Vkeywitness -> Effect Unit -foreign import newVkeyFromPublicKey :: PublicKey -> Effect Vkey - -foreign import publicKeyHash :: PublicKey -> Ed25519KeyHash - -foreign import transactionWitnessSetSetVkeys - :: TransactionWitnessSet -> Vkeywitnesses -> Effect Unit - -foreign import defaultCostmdls :: Effect Costmdls -foreign import newCostmdls :: Effect Costmdls -foreign import costmdlsSetCostModel - :: Costmdls -> Language -> CostModel -> Effect Unit - -foreign import newCostModel :: Effect CostModel -foreign import costModelSetCost :: CostModel -> Int -> Csl.Int -> Effect Unit -foreign import newPlutusV1 :: Effect Language -foreign import newPlutusV2 :: Effect Language - -foreign import _hashScriptData - :: Redeemers -> Costmdls -> Array PlutusData -> Effect ScriptDataHash - -foreign import _hashScriptDataNoDatums - :: Redeemers -> Costmdls -> Effect ScriptDataHash - -foreign import newRedeemers :: Effect Redeemers -foreign import addRedeemer :: Redeemers -> Redeemer -> Effect Unit -foreign import setTxBodyReferenceInputs - :: TransactionBody - -> TransactionInputs - -> Effect Unit - -foreign import setTxBodyScriptDataHash - :: TransactionBody -> ScriptDataHash -> Effect Unit - -foreign import setTxBodyMint :: TransactionBody -> Mint -> Effect Unit -foreign import newMint :: Effect Mint -foreign import newMintAssets :: Effect MintAssets -foreign import _bigIntToInt :: MaybeFfiHelper -> BigInt -> Maybe Int -foreign import insertMintAssets - :: Mint -> ScriptHash -> MintAssets -> Effect Unit - -foreign import insertMintAsset :: MintAssets -> AssetName -> Int -> Effect Unit -foreign import setTxBodyNetworkId :: TransactionBody -> NetworkId -> Effect Unit -foreign import networkIdTestnet :: Effect NetworkId -foreign import networkIdMainnet :: Effect NetworkId - -foreign import setTxBodyCollateralReturn - :: TransactionBody - -> TransactionOutput - -> Effect Unit - -foreign import setTxBodyTotalCollateral - :: TransactionBody - -> BigNum - -> Effect Unit - -foreign import setTxBodyTtl :: TransactionBody -> BigNum -> Effect Unit - -foreign import setTxBodyCerts :: TransactionBody -> Certificates -> Effect Unit -foreign import newCertificates :: Effect Certificates -foreign import newStakeRegistrationCertificate - :: StakeCredential -> Effect Certificate - -foreign import newStakeDeregistrationCertificate - :: StakeCredential -> Effect Certificate - -foreign import newStakeDelegationCertificate - :: StakeCredential -> Ed25519KeyHash -> Effect Certificate - -foreign import newPoolRegistrationCertificate - :: Ed25519KeyHash - -> VRFKeyHash - -> BigNum - -> BigNum - -> UnitInterval - -> RewardAddress - -> Ed25519KeyHashes - -> Relays - -> UndefinedOr PoolMetadata - -> Effect Certificate - -foreign import newPoolRetirementCertificate - :: Ed25519KeyHash -> Int -> Effect Certificate - -foreign import newGenesisKeyDelegationCertificate - :: GenesisHash -> GenesisDelegateHash -> VRFKeyHash -> Effect Certificate - -foreign import addCert :: Certificates -> Certificate -> Effect Unit -foreign import newUnitInterval :: BigNum -> BigNum -> Effect UnitInterval -foreign import convertPoolOwners - :: ContainerHelper -> Array Ed25519KeyHash -> Effect Ed25519KeyHashes - -foreign import packRelays :: ContainerHelper -> Array Relay -> Relays -foreign import newIpv4 :: ByteArray -> Effect Ipv4 -foreign import newIpv6 :: ByteArray -> Effect Ipv6 -foreign import newSingleHostAddr - :: UndefinedOr Int -> UndefinedOr Ipv4 -> UndefinedOr Ipv6 -> Effect Relay - -foreign import newSingleHostName :: UndefinedOr Int -> String -> Effect Relay -foreign import newMultiHostName :: String -> Effect Relay -foreign import newPoolMetadata - :: String -> PoolMetadataHash -> Effect PoolMetadata - -foreign import newMoveInstantaneousRewardToOtherPot - :: Number -> BigNum -> Effect MoveInstantaneousReward - -foreign import newMoveInstantaneousRewardToStakeCreds - :: Number -> MIRToStakeCredentials -> Effect MoveInstantaneousReward - -foreign import newMIRToStakeCredentials - :: ContainerHelper - -> Array (StakeCredential /\ Csl.Int) - -> Effect MIRToStakeCredentials - -foreign import newMoveInstantaneousRewardsCertificate - :: MoveInstantaneousReward -> Effect Certificate - -foreign import setTxBodyCollateral - :: TransactionBody -> TransactionInputs -> Effect Unit - -foreign import transactionBodySetRequiredSigners - :: ContainerHelper -> TransactionBody -> Array Ed25519KeyHash -> Effect Unit - -foreign import transactionBodySetValidityStartInterval - :: TransactionBody -> BigNum -> Effect Unit - -foreign import transactionBodySetAuxiliaryDataHash - :: TransactionBody -> AuxiliaryDataHash -> Effect Unit - -foreign import newWithdrawals - :: ContainerHelper - -> Array (RewardAddress /\ BigNum) - -> Effect Withdrawals - -foreign import setTxBodyWithdrawals - :: TransactionBody -> Withdrawals -> Effect Unit - -foreign import setTxBodyUpdate - :: TransactionBody -> Update -> Effect Unit - -foreign import newUpdate - :: ProposedProtocolParameterUpdates -> Int -> Effect Update - -foreign import newProtocolParamUpdate :: Effect ProtocolParamUpdate - -foreign import ppuSetMinfeeA :: ProtocolParamUpdate -> BigNum -> Effect Unit - -foreign import ppuSetMinfeeB :: ProtocolParamUpdate -> BigNum -> Effect Unit - -foreign import ppuSetMaxBlockBodySize - :: ProtocolParamUpdate -> Int -> Effect Unit - -foreign import ppuSetMaxTxSize :: ProtocolParamUpdate -> Int -> Effect Unit - -foreign import ppuSetMaxBlockHeaderSize - :: ProtocolParamUpdate -> Int -> Effect Unit - -foreign import ppuSetKeyDeposit - :: ProtocolParamUpdate -> BigNum -> Effect Unit - -foreign import ppuSetPoolDeposit - :: ProtocolParamUpdate -> BigNum -> Effect Unit - -foreign import ppuSetMaxEpoch :: ProtocolParamUpdate -> Int -> Effect Unit - -foreign import ppuSetNOpt :: ProtocolParamUpdate -> Int -> Effect Unit - -foreign import ppuSetPoolPledgeInfluence - :: ProtocolParamUpdate -> UnitInterval -> Effect Unit - -foreign import ppuSetExpansionRate - :: ProtocolParamUpdate -> UnitInterval -> Effect Unit - -foreign import ppuSetTreasuryGrowthRate - :: ProtocolParamUpdate -> UnitInterval -> Effect Unit - -foreign import newProtocolVersion :: Int -> Int -> Effect ProtocolVersion - -foreign import ppuSetProtocolVersion - :: ProtocolParamUpdate - -> ProtocolVersion - -> Effect Unit - -foreign import ppuSetMinPoolCost - :: ProtocolParamUpdate - -> BigNum - -> Effect Unit - -foreign import ppuSetAdaPerUtxoByte - :: ProtocolParamUpdate - -> BigNum - -> Effect Unit - -foreign import ppuSetCostModels - :: ProtocolParamUpdate - -> Costmdls - -> Effect Unit - -foreign import newExUnitPrices - :: UnitInterval - -> UnitInterval - -> Effect ExUnitPrices - -foreign import ppuSetExecutionCosts - :: ProtocolParamUpdate - -> ExUnitPrices - -> Effect Unit - -foreign import ppuSetMaxTxExUnits - :: ProtocolParamUpdate - -> ExUnits - -> Effect Unit - -foreign import ppuSetMaxBlockExUnits - :: ProtocolParamUpdate - -> ExUnits - -> Effect Unit - -foreign import ppuSetMaxValueSize - :: ProtocolParamUpdate - -> Int - -> Effect Unit - -foreign import ppuSetCollateralPercentage - :: ProtocolParamUpdate - -> Int - -> Effect Unit - -foreign import ppuSetMaxCollateralInputs - :: ProtocolParamUpdate - -> Int - -> Effect Unit - -foreign import newProposedProtocolParameterUpdates - :: ContainerHelper - -> Array (GenesisHash /\ ProtocolParamUpdate) - -> Effect ProposedProtocolParameterUpdates - -foreign import setTxIsValid :: Transaction -> Boolean -> Effect Unit - -convertTxBody :: T.TxBody -> Effect TransactionBody -convertTxBody (T.TxBody body) = do - inputs <- convertTxInputs body.inputs - outputs <- convertTxOutputs body.outputs - fee <- fromJustEff "Failed to convert fee" $ BigNum.fromBigInt - (unwrap body.fee) - txBody <- newTransactionBody inputs outputs fee - for_ body.ttl $ unwrap >>> setTxBodyTtl txBody - for_ body.certs $ convertCerts >=> setTxBodyCerts txBody - for_ body.withdrawals $ convertWithdrawals >=> setTxBodyWithdrawals txBody - for_ body.update $ convertUpdate >=> setTxBodyUpdate txBody - for_ body.auxiliaryDataHash $ - unwrap >>> wrap >>> fromBytes >>> fromJustEff - "Failed to convert auxiliary data hash" - >=> transactionBodySetAuxiliaryDataHash txBody - for_ body.validityStartInterval - $ unwrap - >>> BigNum.toString - >>> BigNum.fromStringUnsafe - >>> - transactionBodySetValidityStartInterval txBody - for_ body.requiredSigners - $ map unwrap - >>> transactionBodySetRequiredSigners containerHelper txBody - for_ body.networkId $ convertNetworkId >=> setTxBodyNetworkId txBody - for_ body.mint $ convertMint >=> setTxBodyMint txBody - for_ body.scriptDataHash $ - unwrap >>> wrap >>> fromBytes >>> fromJustEff - "Failed to convert script data hash" - >=> setTxBodyScriptDataHash txBody - for_ body.collateral $ convertTxInputs >=> setTxBodyCollateral txBody - for_ body.requiredSigners - $ map unwrap - >>> transactionBodySetRequiredSigners containerHelper txBody - for_ body.networkId $ convertNetworkId >=> setTxBodyNetworkId txBody - for_ body.collateralReturn $ convertTxOutput >=> setTxBodyCollateralReturn - txBody - for_ body.totalCollateral - $ - unwrap - >>> BigNum.fromBigInt - >>> fromJustEff "Failed to convert fee" - >=> - setTxBodyTotalCollateral txBody - if Foldable.null body.referenceInputs then pure unit - else convertTxInputs body.referenceInputs >>= setTxBodyReferenceInputs txBody - pure txBody - -convertTransaction :: T.Transaction -> Effect Transaction -convertTransaction - ( T.Transaction - { body, witnessSet, isValid, auxiliaryData } - ) = - do - txBody <- convertTxBody body - ws <- convertWitnessSet witnessSet - mbAuxiliaryData <- for auxiliaryData convertAuxiliaryData - tx <- case mbAuxiliaryData of - Nothing -> newTransaction_ txBody ws - Just ad -> newTransaction txBody ws ad - setTxIsValid tx isValid - pure tx - -convertUpdate :: T.Update -> Effect Update -convertUpdate { proposedProtocolParameterUpdates, epoch } = do - ppUpdates <- convertProposedProtocolParameterUpdates - proposedProtocolParameterUpdates - newUpdate ppUpdates $ UInt.toInt $ unwrap epoch - -convertProposedProtocolParameterUpdates - :: T.ProposedProtocolParameterUpdates - -> Effect ProposedProtocolParameterUpdates -convertProposedProtocolParameterUpdates ppus = - newProposedProtocolParameterUpdates containerHelper =<< - for (Map.toUnfoldable $ unwrap ppus) \(genesisHash /\ ppu) -> do - Tuple - <$> - ( fromJustEff "Failed to convert genesis hash" $ fromBytes $ wrap - $ unwrap genesisHash - ) - <*> - convertProtocolParamUpdate ppu - -convertProtocolParamUpdate - :: T.ProtocolParamUpdate -> Effect ProtocolParamUpdate -convertProtocolParamUpdate - { minfeeA - , minfeeB - , maxBlockBodySize - , maxTxSize - , maxBlockHeaderSize - , keyDeposit - , poolDeposit - , maxEpoch - , nOpt - , poolPledgeInfluence - , expansionRate - , treasuryGrowthRate - , protocolVersion - , minPoolCost - , adaPerUtxoByte - , costModels - , executionCosts - , maxTxExUnits - , maxBlockExUnits - , maxValueSize - , collateralPercentage - , maxCollateralInputs - } = do - ppu <- newProtocolParamUpdate - for_ minfeeA $ ppuSetMinfeeA ppu - <=< fromJustEff "convertProtocolParamUpdate: min_fee_a must not be negative" - <<< BigNum.fromBigInt - <<< unwrap - for_ minfeeB $ ppuSetMinfeeB ppu - <=< fromJustEff "convertProtocolParamUpdate: min_fee_b must not be negative" - <<< BigNum.fromBigInt - <<< unwrap - for_ maxBlockBodySize $ ppuSetMaxBlockBodySize ppu <<< UInt.toInt - for_ maxTxSize $ ppuSetMaxTxSize ppu <<< UInt.toInt - for_ maxBlockHeaderSize $ ppuSetMaxBlockHeaderSize ppu <<< UInt.toInt - for_ keyDeposit $ ppuSetKeyDeposit ppu - <=< - fromJustEff - "convertProtocolParamUpdate: key_deposit must not be negative" - <<< BigNum.fromBigInt - <<< unwrap - for_ poolDeposit $ ppuSetPoolDeposit ppu - <=< - fromJustEff - "convertProtocolParamUpdate: pool_deposit must not be negative" - <<< BigNum.fromBigInt - <<< unwrap - for_ maxEpoch $ ppuSetMaxEpoch ppu <<< UInt.toInt <<< unwrap - for_ nOpt $ ppuSetNOpt ppu <<< UInt.toInt - for_ poolPledgeInfluence - $ mkUnitInterval - >=> ppuSetPoolPledgeInfluence ppu - for_ expansionRate - $ mkUnitInterval - >=> ppuSetExpansionRate ppu - for_ treasuryGrowthRate - $ mkUnitInterval - >=> ppuSetTreasuryGrowthRate ppu - for_ protocolVersion \pv -> - ppuSetProtocolVersion ppu =<< - newProtocolVersion (UInt.toInt pv.major) - (UInt.toInt pv.minor) - for_ minPoolCost $ ppuSetMinPoolCost ppu - for_ adaPerUtxoByte $ ppuSetAdaPerUtxoByte ppu - for_ costModels $ convertCostmdls >=> ppuSetCostModels ppu - for_ executionCosts $ convertExUnitPrices >=> ppuSetExecutionCosts ppu - for_ maxTxExUnits $ convertExUnits >=> ppuSetMaxTxExUnits ppu - for_ maxBlockExUnits $ convertExUnits >=> ppuSetMaxBlockExUnits ppu - for_ maxValueSize $ UInt.toInt >>> ppuSetMaxValueSize ppu - for_ collateralPercentage $ UInt.toInt >>> ppuSetCollateralPercentage ppu - for_ maxCollateralInputs $ UInt.toInt >>> ppuSetMaxCollateralInputs ppu - pure ppu - -mkUnitInterval - :: T.UnitInterval -> Effect UnitInterval -mkUnitInterval x = newUnitInterval x.numerator x.denominator - -convertExUnitPrices - :: T.ExUnitPrices - -> Effect ExUnitPrices -convertExUnitPrices { memPrice, stepPrice } = - join $ newExUnitPrices <$> mkUnitInterval memPrice <*> mkUnitInterval - stepPrice - -convertWithdrawals :: Map.Map T.RewardAddress Value.Coin -> Effect Withdrawals -convertWithdrawals mp = - newWithdrawals containerHelper =<< do - for (Map.toUnfoldable mp) \(k /\ Value.Coin v) -> do - Tuple (T.unRewardAddress k) <$> fromJustEff - "convertWithdrawals: Failed to convert BigNum" - (BigNum.fromBigInt v) - -convertCerts :: Array T.Certificate -> Effect Certificates -convertCerts certs = do - certificates <- newCertificates - for_ certs $ convertCert >=> addCert certificates - pure certificates - -convertCert :: T.Certificate -> Effect Certificate -convertCert = case _ of - T.StakeRegistration stakeCredential -> - newStakeRegistrationCertificate stakeCredential - T.StakeDeregistration stakeCredential -> - newStakeDeregistrationCertificate stakeCredential - T.StakeDelegation stakeCredential keyHash -> - newStakeDelegationCertificate stakeCredential (unwrap $ unwrap keyHash) - T.PoolRegistration - { operator - , vrfKeyhash - , pledge - , cost - , margin - , rewardAccount - , poolOwners - , relays - , poolMetadata - } -> do - margin' <- newUnitInterval margin.numerator margin.denominator - poolOwners' <- convertPoolOwners containerHelper - (unwrap <<< unwrap <$> poolOwners) - relays' <- convertRelays relays - poolMetadata' <- for poolMetadata convertPoolMetadata - newPoolRegistrationCertificate (unwrap $ unwrap operator) - (T.unVRFKeyHash vrfKeyhash) - pledge - cost - margin' - (T.unRewardAddress rewardAccount) - poolOwners' - relays' - (maybeToUor poolMetadata') - T.PoolRetirement { poolKeyHash, epoch } -> - newPoolRetirementCertificate (unwrap $ unwrap poolKeyHash) - (UInt.toInt $ unwrap epoch) - T.GenesisKeyDelegation - { genesisHash: T.GenesisHash genesisHash - , genesisDelegateHash: T.GenesisDelegateHash genesisDelegateHash - , vrfKeyhash: T.VRFKeyHash vrfKeyhash - } -> do - join $ newGenesisKeyDelegationCertificate - <$> - ( fromJustEff "Failed to convert genesis hash" - $ fromBytes - $ wrap genesisHash - ) - <*> - ( fromJustEff "Failed to convert genesis delegate hash" - $ fromBytes - $ wrap genesisDelegateHash - ) - <*> - pure vrfKeyhash - T.MoveInstantaneousRewardsCert mir -> do - newMoveInstantaneousRewardsCertificate =<< - convertMoveInstantaneousReward mir - -convertMIRToStakeCredentials - :: T.MIRToStakeCredentials -> Effect MIRToStakeCredentials -convertMIRToStakeCredentials (T.MIRToStakeCredentials mp) = - newMIRToStakeCredentials containerHelper (Map.toUnfoldable mp) - -convertMoveInstantaneousReward - :: T.MoveInstantaneousReward -> Effect MoveInstantaneousReward -convertMoveInstantaneousReward (T.ToOtherPot { pot, amount }) = - newMoveInstantaneousRewardToOtherPot pot amount -convertMoveInstantaneousReward (T.ToStakeCreds { pot, amounts }) = - convertMIRToStakeCredentials amounts >>= - newMoveInstantaneousRewardToStakeCreds pot - -convertPoolMetadata :: T.PoolMetadata -> Effect PoolMetadata -convertPoolMetadata - (T.PoolMetadata { url: T.URL url, hash: T.PoolMetadataHash hash }) = - ( fromJustEff "Failed to convert script data hash" <<< fromBytes <<< wrap - >=> newPoolMetadata url - ) hash - -convertRelays :: Array T.Relay -> Effect Relays -convertRelays relays = do - packRelays containerHelper <$> for relays \relay -> case relay of - T.SingleHostAddr { port, ipv4, ipv6 } -> do - ipv4' <- maybeToUor <$> for (unwrap <$> ipv4) newIpv4 - ipv6' <- maybeToUor <$> for (unwrap <$> ipv6) newIpv6 - newSingleHostAddr (maybeToUor port) ipv4' ipv6' - T.SingleHostName { port, dnsName } -> - newSingleHostName (maybeToUor port) dnsName - T.MultiHostName { dnsName } -> - newMultiHostName dnsName - -convertNetworkId :: T.NetworkId -> Effect NetworkId -convertNetworkId = case _ of - T.TestnetId -> networkIdTestnet - T.MainnetId -> networkIdMainnet - -convertMint :: T.Mint -> Effect Mint -convertMint (T.Mint nonAdaAssets) = do - mint <- newMint - let assetsMap = Value.unwrapNonAdaAsset nonAdaAssets - forWithIndex_ assetsMap \scriptHashBytes' values -> do - let - mScripthash = scriptHashFromBytes $ Value.getCurrencySymbol - scriptHashBytes' - scripthash <- fromJustEff - "scriptHashFromBytes failed while converting value" - mScripthash - assets <- newMintAssets - forWithIndex_ values \tokenName' bigIntValue -> do - let tokenName = TokenName.getTokenName tokenName' - assetName <- newAssetName tokenName - bigInt <- fromJustEff "convertMint: failed to convert BigInt" $ - Serialization.convertBigInt bigIntValue - int <- fromJustEff "convertMint: numeric overflow or underflow" $ - _bigIntToInt maybeFfiHelper bigInt - insertMintAsset assets assetName int - insertMintAssets mint scripthash assets - pure mint - -convertTxInputs - :: forall (f :: Type -> Type) - . Foldable f - => f T.TransactionInput - -> Effect TransactionInputs -convertTxInputs fInputs = do - inputs <- newTransactionInputs - traverse_ (convertTxInput >=> addTransactionInput inputs) fInputs - pure inputs - -convertTxInput :: T.TransactionInput -> Effect TransactionInput -convertTxInput (T.TransactionInput { transactionId, index }) = do - tx_hash <- fromBytesEffect $ wrap $ unwrap transactionId - newTransactionInput tx_hash index - -convertTxOutputs :: Array T.TransactionOutput -> Effect TransactionOutputs -convertTxOutputs arrOutputs = do - outputs <- newTransactionOutputs - traverse_ (convertTxOutput >=> addTransactionOutput outputs) arrOutputs - pure outputs - -convertTxOutput :: T.TransactionOutput -> Effect TransactionOutput -convertTxOutput - (T.TransactionOutput { address, amount, datum, scriptRef }) = do - value <- convertValue amount - txo <- newTransactionOutput address value - case datum of - NoOutputDatum -> pure unit - OutputDatumHash dataHash -> do - for_ (fromBytes $ wrap $ unwrap dataHash) $ - transactionOutputSetDataHash txo - OutputDatum datumValue -> do - transactionOutputSetPlutusData txo - $ convertPlutusData - $ unwrap datumValue - for_ scriptRef $ - convertScriptRef >>> transactionOutputSetScriptRef txo - pure txo - -convertScriptRef :: T.ScriptRef -> ScriptRef -convertScriptRef (T.NativeScriptRef nativeScript) = - scriptRefNewNativeScript $ convertNativeScript nativeScript -convertScriptRef (T.PlutusScriptRef plutusScript) = - scriptRefNewPlutusScript $ convertPlutusScript plutusScript - -convertValue :: Value.Value -> Effect Value -convertValue val = do - let - lovelace = Value.valueToCoin' val - m = Value.getNonAdaAsset' val - multiasset <- newMultiAsset - forWithIndex_ m \scriptHashBytes' values -> do - let - mScripthash = scriptHashFromBytes $ Value.getCurrencySymbol - scriptHashBytes' - scripthash <- fromJustEff - "scriptHashFromBytes failed while converting value" - mScripthash - assets <- newAssets - forWithIndex_ values \tokenName' bigIntValue -> do - let tokenName = TokenName.getTokenName tokenName' - assetName <- newAssetName tokenName - value <- fromJustEff "convertValue: number must not be negative" $ - BigNum.fromBigInt bigIntValue - insertAssets assets assetName value - insertMultiAsset multiasset scripthash assets - value <- newValueFromAssets multiasset - valueSetCoin value =<< fromJustEff - "convertValue: coin value must not be negative" - (BigNum.fromBigInt lovelace) - pure value - -convertCostmdls :: T.Costmdls -> Effect Costmdls -convertCostmdls (T.Costmdls cs) = do - costmdls <- newCostmdls - forWithIndex_ cs \language costModel -> do - language' <- case language of - S.PlutusV1 -> newPlutusV1 - S.PlutusV2 -> newPlutusV2 - costModel' <- convertCostModel costModel - costmdlsSetCostModel costmdls language' costModel' - pure costmdls - -convertCostModel :: T.CostModel -> Effect CostModel -convertCostModel (T.CostModel costs) = do - costModel <- newCostModel - forWithIndex_ costs $ \operation cost -> - costModelSetCost costModel operation cost - pure costModel - -convertTransactionUnspentOutput - :: T.TransactionUnspentOutput -> Effect TransactionUnspentOutput -convertTransactionUnspentOutput (T.TransactionUnspentOutput { input, output }) = - do - input' <- convertTxInput input - output' <- convertTxOutput output - newTransactionUnspentOutput input' output' - -hashScriptData - :: T.Costmdls - -> Array T.Redeemer - -> Array PlutusData.PlutusData - -> Effect ScriptDataHash -hashScriptData cms rs ps = do - rs' <- newRedeemers - cms' <- convertCostmdls cms - traverse_ (addRedeemer rs' <=< convertRedeemer) rs - -- If an empty `PlutusData` array is passed to CSL's script integrity hashing - -- function, the resulting hash will be wrong - case ps of - [] -> _hashScriptDataNoDatums rs' cms' - _ -> _hashScriptData rs' cms' $ map convertPlutusData ps - -serializeData :: forall (a :: Type). ToData a => a -> CborBytes -serializeData = toBytes <<< convertPlutusData <<< toData diff --git a/src/Internal/Serialization/Address.js b/src/Internal/Serialization/Address.js deleted file mode 100644 index 083ece7f85..0000000000 --- a/src/Internal/Serialization/Address.js +++ /dev/null @@ -1,177 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -const callClassStaticMaybe = (classname, functionname) => maybe => input => { - let ret = null; - try { - ret = lib[classname][functionname](input); - } catch (_) { - // ignored - } - if (ret == null) { - return maybe.nothing; - } - return maybe.just(ret); -}; - -const callMethodParameterless = methodname => object => { - return object[methodname](); -}; -const callToAddress = callMethodParameterless("to_address"); -const callToBytes = callMethodParameterless("to_bytes"); -const callToBech32 = callMethodParameterless("to_bech32"); -const callNetworkId = callMethodParameterless("network_id"); -const callPaymentCred = callMethodParameterless("payment_cred"); -const callStakeCred = callMethodParameterless("stake_cred"); - -export function withStakeCredential(cbObj) { - return stakeCred => { - return stakeCred.kind() == lib.StakeCredKind.Key - ? cbObj.onKeyHash(stakeCred.to_keyhash()) - : cbObj.onScriptHash(stakeCred.to_scripthash()); - }; -} - -export const keyHashCredential = lib.StakeCredential.from_keyhash; -export const scriptHashCredential = lib.StakeCredential.from_scripthash; -export { callToBytes as addressBytes }; -export { callToBytes as byronAddressBytes }; -export { callToBytes as stakeCredentialToBytes }; -export { callToBech32 as addressBech32 }; - -export function _addressNetworkId(toAdt) { - return addr => { - return toAdt(callNetworkId(addr)); - }; -} - -export function _byronAddressNetworkId(toAdt) { - return addr => { - return toAdt(callNetworkId(addr)); - }; -} - -export const _addressFromBytes = callClassStaticMaybe("Address", "from_bytes"); - -export const _stakeCredentialFromBytes = callClassStaticMaybe( - "StakeCredential", - "from_bytes" -); - -export const _byronAddressFromBytes = callClassStaticMaybe( - "ByronAddress", - "from_bytes" -); - -export const _addressFromBech32 = callClassStaticMaybe( - "Address", - "from_bech32" -); - -export const _byronAddressFromBase58 = callClassStaticMaybe( - "ByronAddress", - "from_base58" -); - -export const _baseAddressFromAddress = callClassStaticMaybe( - "BaseAddress", - "from_address" -); - -export const _byronAddressFromAddress = callClassStaticMaybe( - "ByronAddress", - "from_address" -); - -export const _enterpriseAddressFromAddress = callClassStaticMaybe( - "EnterpriseAddress", - "from_address" -); - -export const _pointerAddressFromAddress = callClassStaticMaybe( - "PointerAddress", - "from_address" -); - -export const _rewardAddressFromAddress = callClassStaticMaybe( - "RewardAddress", - "from_address" -); - -export { callToAddress as baseAddressToAddress }; -export { callToAddress as byronAddressToAddress }; -export { callToAddress as enterpriseAddressToAddress }; -export { callToAddress as pointerAddressToAddress }; -export { callToAddress as rewardAddressToAddress }; -export { callPaymentCred as baseAddressPaymentCred }; -export { callPaymentCred as rewardAddressPaymentCred }; -export { callPaymentCred as enterpriseAddressPaymentCred }; -export { callPaymentCred as pointerAddressPaymentCred }; -export { callStakeCred as baseAddressDelegationCred }; -export const byronAddressAttributes = callMethodParameterless("attributes"); -export const byronAddressIsValid = lib.ByronAddress.is_valid; -export const byronAddressToBase58 = callMethodParameterless("to_base58"); -export const byronProtocolMagic = callMethodParameterless( - "byron_protocol_magic" -); - -export function icarusFromKey(bip32pubkey) { - return byronProtocolMagic => { - return lib.ByronAddress.icarus_from_key(bip32pubkey, byronProtocolMagic); - }; -} - -export function pointerAddressStakePointer(pa) { - const pointerForeign = pa.stake_pointer(); - return { - slot: pointerForeign.slot_bignum(), - txIx: pointerForeign.tx_index_bignum(), - certIx: pointerForeign.cert_index_bignum() - }; -} - -export function _enterpriseAddress(netIdToInt) { - return inpRec => { - return lib.EnterpriseAddress.new( - netIdToInt(inpRec.network), - inpRec.paymentCred - ); - }; -} - -export function _rewardAddress(netIdToInt) { - return inpRec => { - return lib.RewardAddress.new( - netIdToInt(inpRec.network), - inpRec.paymentCred - ); - }; -} - -export function _baseAddress(netIdToInt) { - return inpRec => { - return lib.BaseAddress.new( - netIdToInt(inpRec.network), - inpRec.paymentCred, - inpRec.delegationCred - ); - }; -} - -export function _pointerAddress(netIdToInt) { - return inpRec => { - const p = inpRec.stakePointer; - const pointerForeign = lib.Pointer.new_pointer(p.slot, p.txIx, p.certIx); - return lib.PointerAddress.new( - netIdToInt(inpRec.network), - inpRec.paymentCred, - pointerForeign - ); - }; -} diff --git a/src/Internal/Serialization/Address.purs b/src/Internal/Serialization/Address.purs deleted file mode 100644 index c4432174c8..0000000000 --- a/src/Internal/Serialization/Address.purs +++ /dev/null @@ -1,664 +0,0 @@ -module Ctl.Internal.Serialization.Address - ( Slot(Slot) - , BlockId(BlockId) - , TransactionIndex(TransactionIndex) - , CertificateIndex(CertificateIndex) - , Pointer - , Address - , BaseAddress - , ByronAddress - , EnterpriseAddress - , PointerAddress - , RewardAddress - , StakeCredential - , addressBech32 - , addressNetworkId - , intToNetworkId - , keyHashCredential - , scriptHashCredential - , withStakeCredential - , baseAddress - , baseAddressPaymentCred - , baseAddressDelegationCred - , baseAddressToAddress - , paymentKeyHashStakeKeyHashAddress - , scriptHashStakeKeyHashAddress - , paymentKeyHashScriptHashAddress - , scriptHashScriptHashAddress - , scriptAddress - , ByronProtocolMagic(ByronProtocolMagic) - , NetworkId(MainnetId, TestnetId) - , stakeCredentialToKeyHash - , stakeCredentialToScriptHash - , addressFromBech32 - , addressPaymentCred - , addressStakeCred - , baseAddressFromAddress - , baseAddressBytes - , baseAddressBech32 - , baseAddressFromBytes - , baseAddressFromBech32 - , baseAddressNetworkId - , byronAddressToBase58 - , byronAddressFromBase58 - , byronProtocolMagic - , byronAddressAttributes - , byronAddressNetworkId - , byronAddressFromAddress - , byronAddressToAddress - , byronAddressIsValid - , icarusFromKey - , enterpriseAddress - , enterpriseAddressPaymentCred - , enterpriseAddressToAddress - , enterpriseAddressFromAddress - , enterpriseAddressBytes - , enterpriseAddressBech32 - , enterpriseAddressFromBytes - , enterpriseAddressFromBech32 - , enterpriseAddressNetworkId - , paymentKeyHashEnterpriseAddress - , scriptHashEnterpriseAddress - , pointerAddress - , pointerAddressPaymentCred - , pointerAddressToAddress - , pointerAddressFromAddress - , pointerAddressStakePointer - , pointerAddressBytes - , pointerAddressBech32 - , pointerAddressFromBytes - , pointerAddressFromBech32 - , pointerAddressNetworkId - , paymentKeyHashPointerAddress - , scriptHashPointerAddress - , rewardAddress - , rewardAddressPaymentCred - , rewardAddressToAddress - , rewardAddressBytes - , rewardAddressBech32 - , rewardAddressFromBytes - , rewardAddressFromBech32 - , rewardAddressNetworkId - , rewardAddressFromAddress - , unsafeIntToNetId - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , decodeAeson - , encodeAeson - ) -import Control.Alt ((<|>)) -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Helpers (encodeTagged') -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash, ScriptHash) -import Ctl.Internal.Serialization.Types (Bip32PublicKey) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.Aliases (Base58String, Bech32String) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes) -import Ctl.Internal.Types.PlutusData (PlutusData(Bytes)) -import Data.Either (note) -import Data.Function (on) -import Data.Generic.Rep (class Generic) -import Data.Maybe (Maybe(Just, Nothing), fromJust, fromMaybe) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Show.Generic (genericShow) -import Data.UInt (UInt) -import Partial.Unsafe (unsafePartial) -import Test.QuickCheck.Arbitrary (class Arbitrary) -import Test.QuickCheck.Gen (chooseInt) - -newtype Slot = Slot BigNum - -derive instance Newtype Slot _ -derive instance Generic Slot _ -derive newtype instance Eq Slot -derive newtype instance Ord Slot -derive newtype instance DecodeAeson Slot -derive newtype instance EncodeAeson Slot -derive newtype instance FromData Slot -derive newtype instance ToData Slot - -instance Show Slot where - show = genericShow - --- it is an integer in ogmios --- bytestring in plutus --- uint32 in csl -newtype BlockId = BlockId UInt - -derive newtype instance Eq BlockId -derive instance Newtype BlockId _ -derive instance Generic BlockId _ - -instance EncodeAeson BlockId where - encodeAeson (BlockId id) = encodeAeson id - -instance Show BlockId where - show = genericShow - -newtype TransactionIndex = TransactionIndex BigNum - -derive instance Eq TransactionIndex -derive instance Ord TransactionIndex -derive instance Newtype TransactionIndex _ -derive instance Generic TransactionIndex _ -derive newtype instance DecodeAeson TransactionIndex -derive newtype instance EncodeAeson TransactionIndex -derive newtype instance ToData TransactionIndex -derive newtype instance FromData TransactionIndex - -instance Show TransactionIndex where - show = genericShow - -newtype CertificateIndex = CertificateIndex BigNum - -derive instance Eq CertificateIndex -derive instance Ord CertificateIndex -derive instance Newtype CertificateIndex _ -derive instance Generic CertificateIndex _ -derive newtype instance DecodeAeson CertificateIndex -derive newtype instance EncodeAeson CertificateIndex -derive newtype instance ToData CertificateIndex -derive newtype instance FromData CertificateIndex - -instance Show CertificateIndex where - show = genericShow - -type Pointer = - { slot :: Slot - , txIx :: TransactionIndex - , certIx :: CertificateIndex - } - -foreign import data Address :: Type - -instance Show Address where - show a = "(Address " <> addressBech32 a <> ")" - -instance EncodeAeson Address where - encodeAeson = encodeAeson <<< addressBech32 - -showVia - :: forall (a :: Type) (b :: Type). Show b => String -> (a -> b) -> a -> String -showVia nm toShowable addr = "(" <> nm <> " " <> show (toShowable addr) <> ")" - -instance Eq Address where - eq = eq `on` addressBytes - -instance Ord Address where - compare = compare `on` addressBytes - --- FIX ME: https://github.com/Plutonomicon/cardano-transaction-lib/issues/193 --- Plutus uses `PlutusTx.makeIsDataIndexed ''Address [('Address,0)]` on their --- record, I'm not sure if this will become an issue given our foreign --- representation. -instance FromData Address where - fromData (Bytes res) = addressFromBytes (wrap res) - fromData _ = Nothing - -instance ToData Address where - toData addr = toData <<< unwrap <<< addressBytes $ addr - -foreign import data BaseAddress :: Type - -instance Show BaseAddress where - show = showVia "BaseAddress" baseAddressToAddress - -instance Eq BaseAddress where - eq = eq `on` baseAddressToAddress - -instance FromData BaseAddress where - fromData (Bytes res) = baseAddressFromBytes (wrap res) - fromData _ = Nothing - -instance ToData BaseAddress where - toData = toData <<< baseAddressToAddress - -foreign import data ByronAddress :: Type - -instance Eq ByronAddress where - eq = eq `on` byronAddressToAddress - -instance Show ByronAddress where - show = showVia "ByronAddress" byronAddressToAddress - -instance FromData ByronAddress where - fromData (Bytes res) = byronAddressFromBytes (wrap res) - fromData _ = Nothing - -instance ToData ByronAddress where - toData = toData <<< byronAddressToAddress - -foreign import data EnterpriseAddress :: Type - -instance Eq EnterpriseAddress where - eq = eq `on` enterpriseAddressToAddress - -instance Show EnterpriseAddress where - show = showVia "EnterpriseAddress" enterpriseAddressToAddress - -instance FromData EnterpriseAddress where - fromData (Bytes res) = enterpriseAddressFromBytes (wrap res) - fromData _ = Nothing - -instance ToData EnterpriseAddress where - toData = toData <<< enterpriseAddressToAddress - -foreign import data PointerAddress :: Type - -instance Eq PointerAddress where - eq = eq `on` pointerAddressToAddress - -instance Show PointerAddress where - show = showVia "PointerAddress" pointerAddressToAddress - -instance FromData PointerAddress where - fromData (Bytes res) = pointerAddressFromBytes (wrap res) - fromData _ = Nothing - -instance ToData PointerAddress where - toData = toData <<< pointerAddressToAddress - -foreign import data RewardAddress :: Type - -instance Eq RewardAddress where - eq = eq `on` rewardAddressToAddress - -instance Show RewardAddress where - show = showVia "RewardAddress" rewardAddressToAddress - -instance Ord RewardAddress where - compare = compare `on` rewardAddressBytes - -instance FromData RewardAddress where - fromData (Bytes res) = rewardAddressFromBytes (wrap res) - fromData _ = Nothing - -instance ToData RewardAddress where - toData = toData <<< rewardAddressBytes - -instance EncodeAeson RewardAddress where - encodeAeson = encodeAeson <<< rewardAddressBech32 - -instance DecodeAeson RewardAddress where - decodeAeson = decodeAeson >=> - note (TypeMismatch "RewardAddress") <<< rewardAddressFromBech32 - -foreign import data StakeCredential :: Type - -instance Eq StakeCredential where - eq = eq `on` stakeCredentialToBytes - -instance Ord StakeCredential where - compare = compare `on` stakeCredentialToBytes - -instance Show StakeCredential where - show = showVia "StakeCredenetial" $ withStakeCredential - { onKeyHash: show, onScriptHash: show } - -instance FromData StakeCredential where - fromData (Bytes res) = stakeCredentialFromBytes $ wrap res - fromData _ = Nothing - -instance ToData StakeCredential where - toData = toData <<< unwrap <<< stakeCredentialToBytes - -instance EncodeAeson StakeCredential where - encodeAeson = withStakeCredential - { onKeyHash: encodeAeson, onScriptHash: encodeAeson } - -foreign import _addressFromBech32 - :: MaybeFfiHelper -> Bech32String -> Maybe Address - --- We can't use FromBytes class here, because of cyclic dependencies -foreign import _addressFromBytes :: MaybeFfiHelper -> CborBytes -> Maybe Address -foreign import addressBytes :: Address -> CborBytes -foreign import addressBech32 :: Address -> Bech32String - -foreign import _addressNetworkId :: (Int -> NetworkId) -> Address -> NetworkId - -addressNetworkId :: Address -> NetworkId -addressNetworkId = _addressNetworkId unsafeIntToNetId - -intToNetworkId :: Int -> Maybe NetworkId -intToNetworkId = case _ of - 0 -> Just TestnetId - 1 -> Just MainnetId - _ -> Nothing - -foreign import keyHashCredential :: Ed25519KeyHash -> StakeCredential -foreign import scriptHashCredential :: ScriptHash -> StakeCredential -foreign import withStakeCredential - :: forall (a :: Type) - . { onKeyHash :: Ed25519KeyHash -> a, onScriptHash :: ScriptHash -> a } - -> StakeCredential - -> a - -foreign import stakeCredentialToBytes :: StakeCredential -> CborBytes -foreign import _stakeCredentialFromBytes - :: MaybeFfiHelper -> CborBytes -> Maybe StakeCredential - -foreign import _baseAddress - :: (NetworkId -> Int) - -> { network :: NetworkId - , paymentCred :: StakeCredential - , delegationCred :: StakeCredential - } - -> BaseAddress - -baseAddress - :: { network :: NetworkId - , paymentCred :: StakeCredential - , delegationCred :: StakeCredential - } - -> BaseAddress -baseAddress = _baseAddress networkIdToInt - -foreign import baseAddressPaymentCred :: BaseAddress -> StakeCredential -foreign import baseAddressDelegationCred :: BaseAddress -> StakeCredential -foreign import _baseAddressFromAddress - :: MaybeFfiHelper -> Address -> Maybe BaseAddress - -foreign import baseAddressToAddress :: BaseAddress -> Address - -newtype ByronProtocolMagic = ByronProtocolMagic UInt - -data NetworkId - = TestnetId - | MainnetId - -instance EncodeAeson NetworkId where - encodeAeson = case _ of - TestnetId -> encodeTagged' "TestnetId" {} - MainnetId -> encodeTagged' "MainnetId" {} - -instance Ord NetworkId where - compare = compare `on` networkIdToInt - -networkIdToInt :: NetworkId -> Int -networkIdToInt = case _ of - TestnetId -> 0 - MainnetId -> 1 - -derive instance Eq NetworkId -derive instance Generic NetworkId _ - -instance Show NetworkId where - show = genericShow - -instance Arbitrary NetworkId where - arbitrary = fromMaybe MainnetId <<< intToNetworkId <$> chooseInt 0 1 - -paymentKeyHashStakeKeyHashAddress - :: NetworkId -> Ed25519KeyHash -> Ed25519KeyHash -> BaseAddress -paymentKeyHashStakeKeyHashAddress networkId pkh skh = baseAddress - { network: networkId - , paymentCred: keyHashCredential pkh - , delegationCred: keyHashCredential skh - } - -scriptHashStakeKeyHashAddress - :: NetworkId -> ScriptHash -> Ed25519KeyHash -> BaseAddress -scriptHashStakeKeyHashAddress networkId sh skh = baseAddress - { network: networkId - , paymentCred: scriptHashCredential sh - , delegationCred: keyHashCredential skh - } - -paymentKeyHashScriptHashAddress - :: NetworkId -> Ed25519KeyHash -> ScriptHash -> BaseAddress -paymentKeyHashScriptHashAddress networkId pkh sh = baseAddress - { network: networkId - , paymentCred: keyHashCredential pkh - , delegationCred: scriptHashCredential sh - } - -scriptHashScriptHashAddress - :: NetworkId -> ScriptHash -> ScriptHash -> BaseAddress -scriptHashScriptHashAddress networkId sh sh' = baseAddress - { network: networkId - , paymentCred: scriptHashCredential sh - , delegationCred: scriptHashCredential sh' - } - -scriptAddress :: NetworkId -> ScriptHash -> BaseAddress -scriptAddress networkId sh = - scriptHashScriptHashAddress networkId sh sh - -stakeCredentialToKeyHash :: StakeCredential -> Maybe Ed25519KeyHash -stakeCredentialToKeyHash = withStakeCredential - { onKeyHash: Just - , onScriptHash: const Nothing - } - -stakeCredentialToScriptHash :: StakeCredential -> Maybe ScriptHash -stakeCredentialToScriptHash = withStakeCredential - { onKeyHash: const Nothing - , onScriptHash: Just - } - -stakeCredentialFromBytes :: CborBytes -> Maybe StakeCredential -stakeCredentialFromBytes = _stakeCredentialFromBytes maybeFfiHelper - -addressFromBytes :: CborBytes -> Maybe Address -addressFromBytes = _addressFromBytes maybeFfiHelper - -addressFromBech32 :: Bech32String -> Maybe Address -addressFromBech32 = _addressFromBech32 maybeFfiHelper - -addressPaymentCred :: Address -> Maybe StakeCredential -addressPaymentCred addr = - (baseAddressPaymentCred <$> baseAddressFromAddress addr) - <|> (pointerAddressPaymentCred <$> pointerAddressFromAddress addr) - <|> (enterpriseAddressPaymentCred <$> enterpriseAddressFromAddress addr) - -addressStakeCred :: Address -> Maybe StakeCredential -addressStakeCred addr = - (baseAddressDelegationCred <$> baseAddressFromAddress addr) - -baseAddressFromAddress :: Address -> Maybe BaseAddress -baseAddressFromAddress = _baseAddressFromAddress maybeFfiHelper - -baseAddressBytes :: BaseAddress -> CborBytes -baseAddressBytes = baseAddressToAddress >>> addressBytes - -baseAddressBech32 :: BaseAddress -> Bech32String -baseAddressBech32 = baseAddressToAddress >>> addressBech32 - -baseAddressFromBytes :: CborBytes -> Maybe BaseAddress -baseAddressFromBytes = addressFromBytes >=> baseAddressFromAddress - -baseAddressFromBech32 :: Bech32String -> Maybe BaseAddress -baseAddressFromBech32 = addressFromBech32 >=> baseAddressFromAddress - -baseAddressNetworkId :: BaseAddress -> NetworkId -baseAddressNetworkId = baseAddressToAddress >>> addressNetworkId - -foreign import byronAddressToBase58 :: ByronAddress -> Base58String -foreign import _byronAddressFromBase58 - :: MaybeFfiHelper -> Base58String -> Maybe ByronAddress - -byronAddressFromBase58 :: Base58String -> Maybe ByronAddress -byronAddressFromBase58 = _byronAddressFromBase58 maybeFfiHelper - -foreign import _byronAddressFromBytes - :: MaybeFfiHelper -> CborBytes -> Maybe ByronAddress - -byronAddressFromBytes :: CborBytes -> Maybe ByronAddress -byronAddressFromBytes = _byronAddressFromBytes maybeFfiHelper - -foreign import byronAddressBytes :: ByronAddress -> CborBytes - -foreign import byronProtocolMagic :: ByronAddress -> ByronProtocolMagic -foreign import byronAddressAttributes :: ByronAddress -> ByteArray -foreign import _byronAddressNetworkId - :: (Int -> NetworkId) -> ByronAddress -> NetworkId - -byronAddressNetworkId :: ByronAddress -> NetworkId -byronAddressNetworkId = _byronAddressNetworkId unsafeIntToNetId - -byronAddressFromAddress :: Address -> Maybe ByronAddress -byronAddressFromAddress = _byronAddressFromAddress maybeFfiHelper - -foreign import _byronAddressFromAddress - :: MaybeFfiHelper -> Address -> Maybe ByronAddress - -foreign import byronAddressToAddress :: ByronAddress -> Address - -foreign import byronAddressIsValid :: String -> Boolean - -foreign import icarusFromKey - :: Bip32PublicKey -> ByronProtocolMagic -> ByronAddress - -foreign import _enterpriseAddress - :: (NetworkId -> Int) - -> { network :: NetworkId, paymentCred :: StakeCredential } - -> EnterpriseAddress - -enterpriseAddress - :: { network :: NetworkId, paymentCred :: StakeCredential } - -> EnterpriseAddress -enterpriseAddress = _enterpriseAddress networkIdToInt - -paymentKeyHashEnterpriseAddress - :: NetworkId -> Ed25519KeyHash -> EnterpriseAddress -paymentKeyHashEnterpriseAddress networkId pkh = enterpriseAddress - { network: networkId - , paymentCred: keyHashCredential pkh - } - -scriptHashEnterpriseAddress - :: NetworkId -> ScriptHash -> EnterpriseAddress -scriptHashEnterpriseAddress networkId sh = enterpriseAddress - { network: networkId - , paymentCred: scriptHashCredential sh - } - -foreign import enterpriseAddressPaymentCred - :: EnterpriseAddress -> StakeCredential - -foreign import _enterpriseAddressFromAddress - :: MaybeFfiHelper -> Address -> Maybe EnterpriseAddress - -foreign import enterpriseAddressToAddress :: EnterpriseAddress -> Address - -enterpriseAddressFromAddress :: Address -> Maybe EnterpriseAddress -enterpriseAddressFromAddress = _enterpriseAddressFromAddress maybeFfiHelper - -enterpriseAddressBytes :: EnterpriseAddress -> CborBytes -enterpriseAddressBytes = enterpriseAddressToAddress >>> addressBytes - -enterpriseAddressBech32 :: EnterpriseAddress -> Bech32String -enterpriseAddressBech32 = enterpriseAddressToAddress >>> addressBech32 - -enterpriseAddressFromBytes :: CborBytes -> Maybe EnterpriseAddress -enterpriseAddressFromBytes = addressFromBytes >=> enterpriseAddressFromAddress - -enterpriseAddressFromBech32 :: Bech32String -> Maybe EnterpriseAddress -enterpriseAddressFromBech32 = addressFromBech32 >=> enterpriseAddressFromAddress - -enterpriseAddressNetworkId :: EnterpriseAddress -> NetworkId -enterpriseAddressNetworkId = enterpriseAddressToAddress >>> addressNetworkId - -foreign import _pointerAddress - :: (NetworkId -> Int) - -> { network :: NetworkId - , paymentCred :: StakeCredential - , stakePointer :: Pointer - } - -> PointerAddress - -pointerAddress - :: { network :: NetworkId - , paymentCred :: StakeCredential - , stakePointer :: Pointer - } - -> PointerAddress -pointerAddress = _pointerAddress networkIdToInt - -paymentKeyHashPointerAddress - :: NetworkId -> Ed25519KeyHash -> Pointer -> PointerAddress -paymentKeyHashPointerAddress networkId pkh ptr = pointerAddress - { network: networkId - , paymentCred: keyHashCredential pkh - , stakePointer: ptr - } - -scriptHashPointerAddress - :: NetworkId -> ScriptHash -> Pointer -> PointerAddress -scriptHashPointerAddress networkId sh ptr = pointerAddress - { network: networkId - , paymentCred: scriptHashCredential sh - , stakePointer: ptr - } - -foreign import pointerAddressPaymentCred :: PointerAddress -> StakeCredential -foreign import _pointerAddressFromAddress - :: MaybeFfiHelper -> Address -> Maybe PointerAddress - -foreign import pointerAddressToAddress :: PointerAddress -> Address - -pointerAddressFromAddress :: Address -> Maybe PointerAddress -pointerAddressFromAddress = _pointerAddressFromAddress maybeFfiHelper - -foreign import pointerAddressStakePointer :: PointerAddress -> Pointer - -pointerAddressBytes :: PointerAddress -> CborBytes -pointerAddressBytes = pointerAddressToAddress >>> addressBytes - -pointerAddressBech32 :: PointerAddress -> Bech32String -pointerAddressBech32 = pointerAddressToAddress >>> addressBech32 - -pointerAddressFromBytes :: CborBytes -> Maybe PointerAddress -pointerAddressFromBytes = addressFromBytes >=> pointerAddressFromAddress - -pointerAddressFromBech32 :: Bech32String -> Maybe PointerAddress -pointerAddressFromBech32 = addressFromBech32 >=> pointerAddressFromAddress - -pointerAddressNetworkId :: PointerAddress -> NetworkId -pointerAddressNetworkId = pointerAddressToAddress >>> addressNetworkId - -foreign import _rewardAddress - :: (NetworkId -> Int) - -> { network :: NetworkId, paymentCred :: StakeCredential } - -> RewardAddress - -rewardAddress - :: { network :: NetworkId, paymentCred :: StakeCredential } -> RewardAddress -rewardAddress = _rewardAddress networkIdToInt - -foreign import rewardAddressPaymentCred :: RewardAddress -> StakeCredential -foreign import _rewardAddressFromAddress - :: MaybeFfiHelper -> Address -> Maybe RewardAddress - -foreign import rewardAddressToAddress :: RewardAddress -> Address - -rewardAddressFromAddress :: Address -> Maybe RewardAddress -rewardAddressFromAddress = _rewardAddressFromAddress maybeFfiHelper - -rewardAddressBytes :: RewardAddress -> CborBytes -rewardAddressBytes = rewardAddressToAddress >>> addressBytes - -rewardAddressBech32 :: RewardAddress -> Bech32String -rewardAddressBech32 = rewardAddressToAddress >>> addressBech32 - -rewardAddressFromBytes :: CborBytes -> Maybe RewardAddress -rewardAddressFromBytes = addressFromBytes >=> rewardAddressFromAddress - -rewardAddressFromBech32 :: Bech32String -> Maybe RewardAddress -rewardAddressFromBech32 = addressFromBech32 >=> rewardAddressFromAddress - -rewardAddressNetworkId :: RewardAddress -> NetworkId -rewardAddressNetworkId = rewardAddressToAddress >>> addressNetworkId - --- based on the assumption that CSL will never return invalid networkid -unsafeIntToNetId :: Int -> NetworkId -unsafeIntToNetId i = unsafePartial $ fromJust $ intToNetworkId i diff --git a/src/Internal/Serialization/AuxiliaryData.js b/src/Internal/Serialization/AuxiliaryData.js deleted file mode 100644 index 33fd344de2..0000000000 --- a/src/Internal/Serialization/AuxiliaryData.js +++ /dev/null @@ -1,53 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -const setter = prop => obj => value => () => obj["set_" + prop](value); - -export function newAuxiliaryData() { - return lib.AuxiliaryData.new(); -} - -export function _hashAuxiliaryData(auxiliaryData) { - return lib.hash_auxiliary_data(auxiliaryData); -} - -export const setAuxiliaryDataNativeScripts = setter("native_scripts"); -export const setAuxiliaryDataPlutusScripts = setter("plutus_scripts"); -export const setAuxiliaryDataGeneralTransactionMetadata = setter("metadata"); - -export function newGeneralTransactionMetadata(containerHelper) { - return entries => () => - containerHelper.packMap(lib.GeneralTransactionMetadata, entries); -} - -export function newMetadataMap(containerHelper) { - return entries => () => - lib.TransactionMetadatum.new_map( - containerHelper.packMap(lib.MetadataMap, entries) - ); -} - -export function newMetadataList(containerHelper) { - return entries => () => - lib.TransactionMetadatum.new_list( - containerHelper.pack(lib.MetadataList, entries) - ); -} - -export function newMetadataInt(int) { - return () => lib.TransactionMetadatum.new_int(int); -} - -export function newMetadataBytes(bytes) { - return () => lib.TransactionMetadatum.new_bytes(bytes); -} - -export function newMetadataText(text) { - return () => lib.TransactionMetadatum.new_text(text); -} diff --git a/src/Internal/Serialization/AuxiliaryData.purs b/src/Internal/Serialization/AuxiliaryData.purs deleted file mode 100644 index de2bf5873d..0000000000 --- a/src/Internal/Serialization/AuxiliaryData.purs +++ /dev/null @@ -1,124 +0,0 @@ -module Ctl.Internal.Serialization.AuxiliaryData - ( convertAuxiliaryData - , hashAuxiliaryData - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.Transaction - ( AuxiliaryData(AuxiliaryData) - , AuxiliaryDataHash - ) as T -import Ctl.Internal.FfiHelpers (ContainerHelper, containerHelper) -import Ctl.Internal.Helpers (fromJustEff) -import Ctl.Internal.Serialization.NativeScript (convertNativeScripts) -import Ctl.Internal.Serialization.PlutusScript (convertPlutusScript) -import Ctl.Internal.Serialization.ToBytes (toBytes) -import Ctl.Internal.Serialization.Types - ( AuxiliaryData - , AuxiliaryDataHash - , GeneralTransactionMetadata - , NativeScripts - , PlutusScripts - , TransactionMetadatum - ) -import Ctl.Internal.Serialization.WitnessSet (addPlutusScript, newPlutusScripts) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum (fromBigInt) as BigNum -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.Int as Int -import Ctl.Internal.Types.TransactionMetadata - ( GeneralTransactionMetadata(GeneralTransactionMetadata) - , TransactionMetadatum(Text, Bytes, Int, MetadataList, MetadataMap) - , TransactionMetadatumLabel(TransactionMetadatumLabel) - ) as T -import Data.Map as Map -import Data.Newtype (unwrap, wrap) -import Data.Traversable (for, for_, traverse) -import Data.Tuple (Tuple(Tuple)) -import Data.Tuple.Nested (type (/\), (/\)) -import Effect (Effect) - -foreign import newAuxiliaryData :: Effect AuxiliaryData - -foreign import setAuxiliaryDataNativeScripts - :: AuxiliaryData -> NativeScripts -> Effect Unit - -foreign import setAuxiliaryDataPlutusScripts - :: AuxiliaryData -> PlutusScripts -> Effect Unit - -foreign import setAuxiliaryDataGeneralTransactionMetadata - :: AuxiliaryData -> GeneralTransactionMetadata -> Effect Unit - -foreign import newGeneralTransactionMetadata - :: ContainerHelper - -> Array (BigNum /\ TransactionMetadatum) - -> Effect GeneralTransactionMetadata - -foreign import newMetadataMap - :: ContainerHelper - -> Array (TransactionMetadatum /\ TransactionMetadatum) - -> Effect TransactionMetadatum - -foreign import newMetadataList - :: ContainerHelper - -> Array TransactionMetadatum - -> Effect TransactionMetadatum - -foreign import newMetadataInt - :: Int.Int -> Effect TransactionMetadatum - -foreign import newMetadataBytes - :: ByteArray -> Effect TransactionMetadatum - -foreign import newMetadataText - :: String -> Effect TransactionMetadatum - -foreign import _hashAuxiliaryData - :: AuxiliaryData -> AuxiliaryDataHash - -hashAuxiliaryData :: T.AuxiliaryData -> Effect T.AuxiliaryDataHash -hashAuxiliaryData = - map (wrap <<< unwrap <<< toBytes <<< _hashAuxiliaryData) <<< - convertAuxiliaryData - -convertAuxiliaryData :: T.AuxiliaryData -> Effect AuxiliaryData -convertAuxiliaryData - (T.AuxiliaryData { metadata, nativeScripts, plutusScripts }) = do - ad <- newAuxiliaryData - for_ metadata $ - convertGeneralTransactionMetadata >=> - setAuxiliaryDataGeneralTransactionMetadata ad - for_ nativeScripts $ - convertNativeScripts >>> setAuxiliaryDataNativeScripts ad - for_ plutusScripts \ps -> do - scripts <- newPlutusScripts - for_ ps (convertPlutusScript >>> addPlutusScript scripts) - setAuxiliaryDataPlutusScripts ad scripts - pure ad - -convertGeneralTransactionMetadata - :: T.GeneralTransactionMetadata -> Effect GeneralTransactionMetadata -convertGeneralTransactionMetadata (T.GeneralTransactionMetadata mp) = do - newGeneralTransactionMetadata containerHelper =<< - for (Map.toUnfoldable mp) - \(T.TransactionMetadatumLabel l /\ d) -> do - label <- - fromJustEff - "convertGeneralTransactionMetadata: failing to convert MetadataumLabel" - (BigNum.fromBigInt l) - datum <- convertTransactionMetadatum d - pure $ label /\ datum - -convertTransactionMetadatum - :: T.TransactionMetadatum -> Effect TransactionMetadatum -convertTransactionMetadatum = case _ of - T.MetadataMap mp -> - newMetadataMap containerHelper =<< for (Map.toUnfoldable mp) \(k /\ v) -> do - Tuple <$> convertTransactionMetadatum k <*> convertTransactionMetadatum v - T.MetadataList l -> - newMetadataList containerHelper =<< - traverse convertTransactionMetadatum l - T.Int int -> newMetadataInt int - T.Bytes bytes -> newMetadataBytes bytes - T.Text text -> newMetadataText text diff --git a/src/Internal/Serialization/BigInt.js b/src/Internal/Serialization/BigInt.js deleted file mode 100644 index dc61768cc1..0000000000 --- a/src/Internal/Serialization/BigInt.js +++ /dev/null @@ -1,18 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function _BigInt_from_str(helper) { - return str => { - try { - return helper.just(lib.BigInt.from_str(str)); - } catch (_) { - return helper.nothing; - } - }; -} diff --git a/src/Internal/Serialization/BigInt.purs b/src/Internal/Serialization/BigInt.purs deleted file mode 100644 index 8a0418ce9b..0000000000 --- a/src/Internal/Serialization/BigInt.purs +++ /dev/null @@ -1,15 +0,0 @@ -module Ctl.Internal.Serialization.BigInt - ( convertBigInt - ) where - -import Prelude - -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Ctl.Internal.Serialization.Types (BigInt) -import Data.Maybe (Maybe) -import JS.BigInt as BigInt - -convertBigInt :: BigInt.BigInt -> Maybe BigInt -convertBigInt = _BigInt_from_str maybeFfiHelper <<< BigInt.toString - -foreign import _BigInt_from_str :: MaybeFfiHelper -> String -> Maybe BigInt diff --git a/src/Internal/Serialization/Hash.js b/src/Internal/Serialization/Hash.js deleted file mode 100644 index 1ac1b8c796..0000000000 --- a/src/Internal/Serialization/Hash.js +++ /dev/null @@ -1,68 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function hashToBytes(hash) { - return hash.to_bytes(); -} - -export function hashFromBytes(name) { - return maybe => bytes => { - return hashFromImpl(lib[name].from_bytes)(maybe)(bytes); - }; -} - -export function hashToBech32Unsafe(prefix) { - return hash => { - return hash.to_bech32(prefix); - }; -} - -const hashFromImpl = hashClassFrom => maybe => input => { - let ret = null; - try { - ret = hashClassFrom(input); - } catch (e) { - // Do nothing - } - if (ret == null) { - return maybe.nothing; - } - return maybe.just(ret); -}; - -export function hashToBech32Impl(maybe) { - return prefix => hash => { - let ret = null; - try { - ret = hash.to_bech32(prefix); - } catch (e) { - // Do nothing - } - if (ret == null) { - return maybe.nothing; - } - return maybe.just(ret); - }; -} - -export function _ed25519KeyHashFromBech32Impl(maybe) { - return bech32str => { - return hashFromImpl(lib.Ed25519KeyHash.from_bech32)(maybe)(bech32str); - }; -} - -export function _scriptHashFromBech32Impl(maybe) { - return bech32str => { - return hashFromImpl(lib.ScriptHash.from_bech32)(maybe)(bech32str); - }; -} - -export function nativeScriptHash(script) { - return script.hash(); -} diff --git a/src/Internal/Serialization/Hash.purs b/src/Internal/Serialization/Hash.purs deleted file mode 100644 index af5b1fcad1..0000000000 --- a/src/Internal/Serialization/Hash.purs +++ /dev/null @@ -1,229 +0,0 @@ -module Ctl.Internal.Serialization.Hash - ( Ed25519KeyHash - , ScriptHash - , VRFKeyHash - , ed25519KeyHashFromBech32 - , ed25519KeyHashFromBytes - , ed25519KeyHashToBech32 - , ed25519KeyHashToBech32Unsafe - , ed25519KeyHashToBytes - , nativeScriptHash - , scriptHashFromBech32 - , scriptHashFromBytes - , scriptHashToBech32 - , scriptHashToBech32Unsafe - , scriptHashToBytes - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , caseAesonString - , encodeAeson - ) -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata, toMetadata) -import Ctl.Internal.Serialization.Types (NativeScript) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.ByteArray - ( ByteArray - , byteArrayFromIntArrayUnsafe - , byteArrayToHex - , hexToByteArray - ) -import Ctl.Internal.Types.PlutusData (PlutusData(Bytes)) -import Ctl.Internal.Types.RawBytes (RawBytes, rawBytesToHex) -import Ctl.Internal.Types.TransactionMetadata (TransactionMetadatum(Bytes)) as Metadata -import Data.Either (Either(Left, Right), note) -import Data.Function (on) -import Data.Maybe (Maybe(Nothing, Just), fromJust, maybe) -import Data.Newtype (unwrap, wrap) -import Partial.Unsafe (unsafePartial) -import Test.QuickCheck.Arbitrary (class Arbitrary) -import Test.QuickCheck.Gen (chooseInt, vectorOf) - --- We can't use ToBytes class here, because of cyclic dependencies --- | Encodes the hash to `CborBytes` -foreign import hashToBytes :: forall (a :: Type). a -> ByteArray - --- We can't use FromBytes class here, because of cyclic dependencies --- | Decodes `CborBytes` to the hash -foreign import hashFromBytes - :: forall (a :: Type) - . String - -> MaybeFfiHelper - -> ByteArray - -> Maybe a - -foreign import nativeScriptHash :: NativeScript -> ScriptHash - -foreign import hashToBech32Unsafe - :: forall (a :: Type) - . String - -> a - -> Bech32String - -foreign import hashToBech32Impl - :: forall (a :: Type) - . MaybeFfiHelper - -> String - -> a - -> Maybe Bech32String - -foreign import _ed25519KeyHashFromBech32Impl - :: MaybeFfiHelper - -> Bech32String - -> Maybe Ed25519KeyHash - -foreign import _scriptHashFromBech32Impl - :: MaybeFfiHelper - -> Bech32String - -> Maybe ScriptHash - --- | PubKeyHash and StakeKeyHash refers to blake2b-224 hash digests of Ed25519 --- | verification keys -foreign import data Ed25519KeyHash :: Type - -instance Eq Ed25519KeyHash where - eq = eq `on` ed25519KeyHashToBytes - -instance Ord Ed25519KeyHash where - compare = compare `on` ed25519KeyHashToBytes - -instance Show Ed25519KeyHash where - show edkh = "(Ed25519KeyHash " <> rawBytesToHex (ed25519KeyHashToBytes edkh) - <> ")" - -instance ToData Ed25519KeyHash where - toData = toData <<< unwrap <<< ed25519KeyHashToBytes - -instance FromData Ed25519KeyHash where - fromData (Bytes kh) = ed25519KeyHashFromBytes kh - fromData _ = Nothing - -instance ToMetadata Ed25519KeyHash where - toMetadata = toMetadata <<< ed25519KeyHashToBytes - -instance FromMetadata Ed25519KeyHash where - fromMetadata (Metadata.Bytes kh) = ed25519KeyHashFromBytes kh - fromMetadata _ = Nothing - --- This is needed for `ApplyArgs`. -instance DecodeAeson Ed25519KeyHash where - -- ed25519KeyHashFromBech32 goes from Bech32String directly although this - -- feels unsafe. - decodeAeson = caseAesonString - (Left $ TypeMismatch "Expected Plutus BuiltinByteString") - ( note (TypeMismatch "Invalid Ed25519KeyHash") <<< ed25519KeyHashFromBytes - <=< note (TypeMismatch "Invalid ByteArray") <<< hexToByteArray - ) - -instance EncodeAeson Ed25519KeyHash where - encodeAeson = encodeAeson <<< rawBytesToHex <<< ed25519KeyHashToBytes - -instance Arbitrary Ed25519KeyHash where - arbitrary = - unsafePartial fromJust <<< ed25519KeyHashFromBytes <<< - byteArrayFromIntArrayUnsafe <$> vectorOf 28 (chooseInt 0 255) - --- | Convert ed25519KeyHash to Bech32 representation with given prefix. --- | Will crash if prefix is invalid (length, mixed-case, etc) --- | More on prefixes: https://cips.cardano.org/cips/cip5 -ed25519KeyHashToBech32Unsafe ∷ String → Ed25519KeyHash → Bech32String -ed25519KeyHashToBech32Unsafe = hashToBech32Unsafe - -ed25519KeyHashToBytes :: Ed25519KeyHash -> RawBytes -ed25519KeyHashToBytes = wrap <<< hashToBytes - -scriptHashToBech32Unsafe ∷ String → ScriptHash → Bech32String -scriptHashToBech32Unsafe = hashToBech32Unsafe - -ed25519KeyHashFromBytes :: ByteArray -> Maybe Ed25519KeyHash -ed25519KeyHashFromBytes = hashFromBytes "Ed25519KeyHash" maybeFfiHelper - -ed25519KeyHashFromBech32 :: Bech32String -> Maybe Ed25519KeyHash -ed25519KeyHashFromBech32 = _ed25519KeyHashFromBech32Impl maybeFfiHelper - --- | Convert ed25519KeyHash to Bech32 representation with given prefix. --- | Will return Nothing if prefix is invalid (length, mixed-case, etc) --- | More on prefixes: https://cips.cardano.org/cips/cip5 -ed25519KeyHashToBech32 :: String -> Ed25519KeyHash -> Maybe Bech32String -ed25519KeyHashToBech32 = _ed25519KeyHashToBech32Impl maybeFfiHelper - --- | blake2b-224 hash digests of serialized monetary scripts -foreign import data ScriptHash :: Type - -instance Eq ScriptHash where - eq = eq `on` scriptHashToBytes - -instance Ord ScriptHash where - compare = compare `on` scriptHashToBytes - -instance Show ScriptHash where - show edkh = "(ScriptHash " <> rawBytesToHex (scriptHashToBytes edkh) <> ")" - -instance ToData ScriptHash where - toData = toData <<< unwrap <<< scriptHashToBytes - -instance FromData ScriptHash where - fromData (Bytes bytes) = scriptHashFromBytes bytes - fromData _ = Nothing - -instance ToMetadata ScriptHash where - toMetadata = toMetadata <<< scriptHashToBytes - -instance FromMetadata ScriptHash where - fromMetadata (Metadata.Bytes bytes) = scriptHashFromBytes bytes - fromMetadata _ = Nothing - --- Corresponds to Plutus' `Plutus.V1.Ledger.Api.Script` Aeson instances -instance DecodeAeson ScriptHash where - decodeAeson = do - maybe (Left $ TypeMismatch "Expected hex-encoded script hash") Right <<< - caseAesonString Nothing (Just <=< scriptHashFromBytes <=< hexToByteArray) - -instance EncodeAeson ScriptHash where - encodeAeson sh = encodeAeson $ scriptHashToBytes sh - -_ed25519KeyHashToBech32Impl - ∷ MaybeFfiHelper → String → Ed25519KeyHash → Maybe Bech32String -_ed25519KeyHashToBech32Impl = hashToBech32Impl - -scriptHashToBytes :: ScriptHash -> RawBytes -scriptHashToBytes = wrap <<< hashToBytes - -_scriptHashToBech32Impl - ∷ MaybeFfiHelper → String → ScriptHash → Maybe Bech32String -_scriptHashToBech32Impl = hashToBech32Impl - --- | Decodes a script hash from its CBOR bytes encoding --- | NOTE. It does _not_ compute hash of given bytes. -scriptHashFromBytes :: ByteArray -> Maybe ScriptHash -scriptHashFromBytes = hashFromBytes "ScriptHash" maybeFfiHelper - --- | Decodes a script hash from its Bech32 representation -scriptHashFromBech32 :: Bech32String -> Maybe ScriptHash -scriptHashFromBech32 = _scriptHashFromBech32Impl maybeFfiHelper - --- | Convert scriptHash to Bech32 representation with given prefix. --- | Will return `Nothing` if prefix is invalid (length, mixed-case, etc) --- | More on prefixes: https://cips.cardano.org/cips/cip5 -scriptHashToBech32 :: String -> ScriptHash -> Maybe Bech32String -scriptHashToBech32 = _scriptHashToBech32Impl maybeFfiHelper - -foreign import data VRFKeyHash :: Type - -instance Show VRFKeyHash where - show = hashToBytes >>> byteArrayToHex - -instance Eq VRFKeyHash where - eq = eq `on` show - -instance EncodeAeson VRFKeyHash where - encodeAeson = hashToBytes >>> byteArrayToHex >>> encodeAeson diff --git a/src/Internal/Serialization/Keys.js b/src/Internal/Serialization/Keys.js deleted file mode 100644 index 3c80c09b4f..0000000000 --- a/src/Internal/Serialization/Keys.js +++ /dev/null @@ -1,16 +0,0 @@ -/* global BROWSER_RUNTIME */ - -const bytesFromKey = key => key.as_bytes(); - -export { bytesFromKey as bytesFromPublicKey }; -export { bytesFromKey as bytesFromPrivateKey }; - -export function publicKeyFromPrivateKey(private_key) { - return private_key.to_public(); -} - -const bech32FromX = key => key.to_bech32(); - -export { bech32FromX as bech32FromPublicKey }; -export { bech32FromX as bech32FromPrivateKey }; -export { bech32FromX as bech32FromEd25519Signature }; diff --git a/src/Internal/Serialization/Keys.purs b/src/Internal/Serialization/Keys.purs deleted file mode 100644 index 5a6dd58ec8..0000000000 --- a/src/Internal/Serialization/Keys.purs +++ /dev/null @@ -1,34 +0,0 @@ -module Ctl.Internal.Serialization.Keys - ( bytesFromPrivateKey - , bytesFromPublicKey - , bech32FromPublicKey - , bech32FromPrivateKey - , bech32FromEd25519Signature - , publicKeyFromPrivateKey - ) where - -import Ctl.Internal.Serialization.Types - ( Ed25519Signature - , PrivateKey - , PublicKey - ) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.RawBytes (RawBytes) - -foreign import publicKeyFromPrivateKey - :: PrivateKey -> PublicKey - -foreign import bytesFromPrivateKey - :: PrivateKey -> RawBytes - -foreign import bytesFromPublicKey - :: PublicKey -> RawBytes - -foreign import bech32FromPublicKey - :: PublicKey -> Bech32String - -foreign import bech32FromPrivateKey - :: PrivateKey -> Bech32String - -foreign import bech32FromEd25519Signature - :: Ed25519Signature -> Bech32String diff --git a/src/Internal/Serialization/MinFee.js b/src/Internal/Serialization/MinFee.js deleted file mode 100644 index 52e0732ada..0000000000 --- a/src/Internal/Serialization/MinFee.js +++ /dev/null @@ -1,23 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function _minFee(maybe) { - return tx => txFeeFixed => txFeePerByte => { - try { - const linearFee = lib.LinearFee.new(txFeePerByte, txFeeFixed); - return maybe.just(lib.min_fee(tx, linearFee)); - } catch (_) { - return maybe.nothing; - } - }; -} - -export function _minScriptFee(exUnitPrices) { - return tx => lib.min_script_fee(tx, exUnitPrices); -} diff --git a/src/Internal/Serialization/MinFee.purs b/src/Internal/Serialization/MinFee.purs index 12cd006944..d5bf69e5ae 100644 --- a/src/Internal/Serialization/MinFee.purs +++ b/src/Internal/Serialization/MinFee.purs @@ -3,30 +3,41 @@ module Ctl.Internal.Serialization.MinFee (calculateMinFeeCsl) where import Prelude -import Control.Monad.Error.Class (class MonadThrow, liftMaybe) -import Ctl.Internal.Cardano.Types.NativeScript (NativeScript(ScriptAll)) -import Ctl.Internal.Cardano.Types.Transaction (_vkeys, _witnessSet) -import Ctl.Internal.Cardano.Types.Transaction as T -import Ctl.Internal.Cardano.Types.Value (Coin) -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) +import Cardano.Serialization.Lib (linearFee_new, minFee, minScriptFee) +import Cardano.Types + ( Coin + , Ed25519KeyHash + , Transaction + , Vkey(Vkey) + , Vkeywitness(Vkeywitness) + , _vkeys + , _witnessSet + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Ed25519Signature as Ed25519Signature +import Cardano.Types.ExUnitPrices as ExUnitPrices +import Cardano.Types.NativeScript (NativeScript(ScriptAll)) +import Cardano.Types.PublicKey as PublicKey +import Cardano.Types.Transaction as Transaction +import Contract.Prim.ByteArray (hexToRawBytes) +import Control.Monad.Error.Class (class MonadThrow) +import Ctl.Internal.Helpers (unsafeFromJust) import Ctl.Internal.NativeScripts (getMaximumSigners) -import Ctl.Internal.Serialization as Serialization -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash) -import Ctl.Internal.Serialization.Types (ExUnitPrices, Transaction) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum as BigNum import Ctl.Internal.Types.ProtocolParameters ( ProtocolParameters(ProtocolParameters) ) -import Data.Array as Array +import Data.Array (range, replicate) as Array +import Data.Foldable (fold) +import Data.Int (hexadecimal) as Radix +import Data.Int (toStringAs) as Int import Data.Lens ((.~)) -import Data.Maybe (Maybe(Just), fromJust, fromMaybe) +import Data.Maybe (fromJust) import Data.Newtype (unwrap, wrap) import Data.Set (Set) -import Data.Set as Set -import Data.Tuple.Nested ((/\)) -import Effect.Class (class MonadEffect, liftEffect) -import Effect.Exception (Error, error) +import Data.Set (fromFoldable, isEmpty, size) as Set +import Data.String (length) as String +import Effect.Class (class MonadEffect) +import Effect.Exception (Error) import Partial.Unsafe (unsafePartial) calculateMinFeeCsl @@ -35,70 +46,76 @@ calculateMinFeeCsl => MonadThrow Error m => ProtocolParameters -> Set Ed25519KeyHash - -> T.Transaction + -> Transaction -> m Coin calculateMinFeeCsl (ProtocolParameters pparams) selfSigners txNoSigs = do let tx = addFakeSignatures selfSigners txNoSigs - cslTx <- liftEffect $ Serialization.convertTransaction tx - minFee <- liftMaybe (error "Unable to calculate min_fee") $ - BigNum.toBigInt <$> _minFee maybeFfiHelper cslTx - (BigNum.fromUInt pparams.txFeeFixed) - (BigNum.fromUInt pparams.txFeePerByte) + let cslTx = Transaction.toCsl tx + let + cslLinearFee = linearFee_new + (unwrap $ BigNum.fromUInt pparams.txFeePerByte) + (unwrap $ unwrap pparams.txFeeFixed) + + let fee = minFee cslTx cslLinearFee let exUnitPrices = pparams.prices - exUnitPricesCsl <- liftEffect $ Serialization.convertExUnitPrices exUnitPrices - let minScriptFee = BigNum.toBigInt (_minScriptFee exUnitPricesCsl cslTx) - pure $ wrap $ minFee + minScriptFee + let exUnitPricesCsl = ExUnitPrices.toCsl exUnitPrices + let scriptFee = minScriptFee cslTx exUnitPricesCsl + -- Ignore the overflow here: fees are much lower + pure $ wrap $ unsafeFromJust "calculateMinFeeCsl" $ BigNum.add (wrap fee) + (wrap scriptFee) -- | Adds fake signatures for each expected signature of a transaction. -addFakeSignatures :: Set Ed25519KeyHash -> T.Transaction -> T.Transaction +addFakeSignatures :: Set Ed25519KeyHash -> Transaction -> Transaction addFakeSignatures selfSigners tx = let - -- requiredSigners field of a transaction + -- `requiredSigners` field of the transaction requiredSigners :: Set Ed25519KeyHash requiredSigners = tx # unwrap >>> _.body >>> unwrap >>> _.requiredSigners - >>> fromMaybe mempty - >>> map unwrap >>> Set.fromFoldable - -- All possible signers from NativeScript. - nsPossibleSigners :: Int - nsPossibleSigners = getMaximumSigners requiredSigners $ ScriptAll - ( tx # unwrap >>> _.witnessSet >>> unwrap >>> _.nativeScripts >>> - fromMaybe mempty - ) - - -- We want to add space for required signatures (at least one, if - -- none specified). - nRequiredSigners = tx # unwrap >>> _.body >>> unwrap >>> _.requiredSigners - >>> map (map unwrap >>> Array.length) - >>> fromMaybe 0 + requiredAndSelfSigners :: Set Ed25519KeyHash + requiredAndSelfSigners = requiredSigners <> selfSigners - nSelfSigners = let n = Set.size selfSigners in if n == 0 then 1 else n + -- All possible signers from native scripts. + numNativeScriptSigners :: Int + numNativeScriptSigners = + getMaximumSigners requiredAndSelfSigners $ + ScriptAll + ( tx # unwrap >>> _.witnessSet >>> unwrap >>> _.nativeScripts + ) + numFakeSigs :: Int + numFakeSigs = + Set.size requiredAndSelfSigners + + numNativeScriptSigners + -- We want to add space for required signatures + -- (at least one, if none specified). + + if Set.isEmpty selfSigners then one else zero in - tx # _witnessSet <<< _vkeys .~ Just - ( Array.replicate (nRequiredSigners + nsPossibleSigners + nSelfSigners) - fakeVkeywitness - ) + -- Generate unique vkeys because Vkeywitnesses now has Set + -- semantics. + tx # _witnessSet <<< _vkeys .~ map mkFakeVkeyWitness + (Array.range one numFakeSigs) -fakeVkeywitness :: T.Vkeywitness -fakeVkeywitness = T.Vkeywitness - ( ( T.Vkey - ( unsafePartial $ fromJust $ T.mkPublicKey - -- This should not fail assuming the hardcoded bech32 key is valid. - "ed25519_pk1p9sf9wz3t46u9ghht44203gerxt82kzqaqw74fqrmwjmdy8sjxmqknzq8j" +mkFakeVkeyWitness :: Int -> Vkeywitness +mkFakeVkeyWitness n = Vkeywitness + { vkey: + Vkey + ( let + nHex = Int.toStringAs Radix.hexadecimal n + in + unsafeFromJust "Ctl.Internal.Serialization.MinFee.mkFakeVkeyWitness" + ( fold (Array.replicate (64 - String.length nHex) "0") <> nHex # + ( PublicKey.fromRawBytes + <=< hexToRawBytes + ) + ) ) - ) - /\ - ( unsafePartial $ fromJust $ T.mkEd25519Signature - "ed25519_sig1mr6pm5kanam2wkmae70jx7fjkzepghefj0lmnczu6fra\ - \6auf2urgrte5axxhunw4x34l3l8tj9c0t4le39tj8lpjdgxmqnujw07t\ - \kzs9m6t6x" - ) - ) - -foreign import _minFee - :: MaybeFfiHelper -> Transaction -> BigNum -> BigNum -> Maybe BigNum - -foreign import _minScriptFee :: ExUnitPrices -> Transaction -> BigNum + , signature: + ( unsafePartial $ fromJust $ Ed25519Signature.fromBech32 + "ed25519_sig1mr6pm5kanam2wkmae70jx7fjkzepghefj0lmnczu6fra\ + \6auf2urgrte5axxhunw4x34l3l8tj9c0t4le39tj8lpjdgxmqnujw07t\ + \kzs9m6t6x" + ) + } diff --git a/src/Internal/Serialization/NativeScript.js b/src/Internal/Serialization/NativeScript.js deleted file mode 100644 index 810331fa7c..0000000000 --- a/src/Internal/Serialization/NativeScript.js +++ /dev/null @@ -1,45 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -const mkScript = prop => arg => lib.NativeScript[prop](arg); - -export function mkScriptPubkey(keyHash) { - return lib.ScriptPubkey.new(keyHash); -} - -export const nativeScript_new_script_pubkey = mkScript("new_script_pubkey"); -export const nativeScript_new_script_all = mkScript("new_script_all"); -export const nativeScript_new_script_any = mkScript("new_script_any"); -export const nativeScript_new_script_n_of_k = mkScript("new_script_n_of_k"); -export const nativeScript_new_timelock_start = mkScript("new_timelock_start"); -export const nativeScript_new_timelock_expiry = mkScript("new_timelock_expiry"); - -export function _packNativeScripts(helper) { - return nss => helper.pack(lib.NativeScripts, nss); -} - -export function mkScriptAll(nss) { - return lib.ScriptAll.new(nss); -} - -export function mkScriptAny(nss) { - return lib.ScriptAny.new(nss); -} - -export function mkScriptNOfK(n) { - return nss => lib.ScriptNOfK.new(n, nss); -} - -export function mkTimelockExpiry(n) { - return lib.TimelockExpiry.new_timelockexpiry(n); -} - -export function mkTimelockStart(n) { - return lib.TimelockStart.new_timelockstart(n); -} diff --git a/src/Internal/Serialization/NativeScript.purs b/src/Internal/Serialization/NativeScript.purs deleted file mode 100644 index feb4d2cdf1..0000000000 --- a/src/Internal/Serialization/NativeScript.purs +++ /dev/null @@ -1,91 +0,0 @@ -module Ctl.Internal.Serialization.NativeScript - ( convertNativeScript - , convertNativeScripts - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.NativeScript - ( NativeScript - ( ScriptPubkey - , ScriptAll - , ScriptAny - , ScriptNOfK - , TimelockStart - , TimelockExpiry - ) - ) as T -import Ctl.Internal.FfiHelpers (ContainerHelper, containerHelper) -import Ctl.Internal.Serialization.Address (Slot(Slot)) as T -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash) as T -import Ctl.Internal.Serialization.Types - ( NativeScript - , NativeScripts - , ScriptAll - , ScriptAny - , ScriptNOfK - , ScriptPubkey - , TimelockExpiry - , TimelockStart - ) -import Ctl.Internal.Types.BigNum (BigNum) - -convertNativeScripts :: Array T.NativeScript -> NativeScripts -convertNativeScripts = packNativeScripts <<< map convertNativeScript - --- | Note: unbounded recursion here. -convertNativeScript :: T.NativeScript -> NativeScript -convertNativeScript = case _ of - T.ScriptPubkey keyHash -> convertScriptPubkey keyHash - T.ScriptAll nss -> convertScriptAll nss - T.ScriptAny nss -> convertScriptAny nss - T.ScriptNOfK n nss -> convertScriptNOfK n nss - T.TimelockStart slot -> convertTimelockStart slot - T.TimelockExpiry slot -> convertTimelockExpiry slot - -convertScriptPubkey :: T.Ed25519KeyHash -> NativeScript -convertScriptPubkey hash = do - nativeScript_new_script_pubkey $ mkScriptPubkey hash - -convertScriptAll :: Array T.NativeScript -> NativeScript -convertScriptAll nss = - nativeScript_new_script_all <<< mkScriptAll <<< - packNativeScripts $ map convertNativeScript nss - -convertScriptAny :: Array T.NativeScript -> NativeScript -convertScriptAny nss = - nativeScript_new_script_any <<< mkScriptAny <<< - packNativeScripts $ map convertNativeScript nss - -convertScriptNOfK :: Int -> Array T.NativeScript -> NativeScript -convertScriptNOfK n nss = - nativeScript_new_script_n_of_k <<< mkScriptNOfK n <<< - packNativeScripts $ map convertNativeScript nss - -convertTimelockStart :: T.Slot -> NativeScript -convertTimelockStart (T.Slot slot) = - nativeScript_new_timelock_start (mkTimelockStart slot) - -convertTimelockExpiry :: T.Slot -> NativeScript -convertTimelockExpiry (T.Slot slot) = - nativeScript_new_timelock_expiry (mkTimelockExpiry slot) - -packNativeScripts :: Array NativeScript -> NativeScripts -packNativeScripts = _packNativeScripts containerHelper - -foreign import mkScriptPubkey :: T.Ed25519KeyHash -> ScriptPubkey -foreign import _packNativeScripts - :: ContainerHelper -> Array NativeScript -> NativeScripts - -foreign import mkScriptAll :: NativeScripts -> ScriptAll -foreign import mkScriptAny :: NativeScripts -> ScriptAny -foreign import mkScriptNOfK :: Int -> NativeScripts -> ScriptNOfK -foreign import mkTimelockStart :: BigNum -> TimelockStart -foreign import mkTimelockExpiry :: BigNum -> TimelockExpiry -foreign import nativeScript_new_script_pubkey :: ScriptPubkey -> NativeScript -foreign import nativeScript_new_script_all :: ScriptAll -> NativeScript -foreign import nativeScript_new_script_any :: ScriptAny -> NativeScript -foreign import nativeScript_new_script_n_of_k :: ScriptNOfK -> NativeScript -foreign import nativeScript_new_timelock_start :: TimelockStart -> NativeScript -foreign import nativeScript_new_timelock_expiry - :: TimelockExpiry -> NativeScript diff --git a/src/Internal/Serialization/PlutusData.js b/src/Internal/Serialization/PlutusData.js deleted file mode 100644 index 9c642c773e..0000000000 --- a/src/Internal/Serialization/PlutusData.js +++ /dev/null @@ -1,56 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function _mkPlutusData_bytes(bytes) { - return lib.PlutusData.new_bytes(bytes); -} - -export function _mkPlutusData_list(list) { - return lib.PlutusData.new_list(list); -} - -export function _mkPlutusData_map(list) { - return lib.PlutusData.new_map(list); -} - -export function _mkPlutusData_integer(int) { - return lib.PlutusData.new_integer(int); -} - -export function _mkPlutusData_constr(constr) { - return lib.PlutusData.new_constr_plutus_data(constr); -} - -export function _packPlutusList(containerHelper) { - return elems => containerHelper.pack(lib.PlutusList, elems); -} - -export function _mkConstrPlutusData(n) { - return list => lib.ConstrPlutusData.new(n, list); -} - -export function _bigIntFromString(maybe) { - return str => { - try { - return maybe.just(lib.BigInt.from_str(str)); - } catch (_) { - return maybe.nothing; - } - }; -} - -export function _packMap(first) { - return second => kvs => { - const res = lib.PlutusMap.new(); - for (let kv of kvs) { - res.insert(first(kv), second(kv)); - } - return res; - }; -} diff --git a/src/Internal/Serialization/PlutusData.purs b/src/Internal/Serialization/PlutusData.purs deleted file mode 100644 index e15a4bd44a..0000000000 --- a/src/Internal/Serialization/PlutusData.purs +++ /dev/null @@ -1,87 +0,0 @@ -module Ctl.Internal.Serialization.PlutusData - ( convertPlutusData - , packPlutusList - ) where - -import Prelude - -import Ctl.Internal.FfiHelpers - ( ContainerHelper - , MaybeFfiHelper - , containerHelper - , maybeFfiHelper - ) -import Ctl.Internal.Serialization.Types - ( BigInt - , ConstrPlutusData - , PlutusData - , PlutusList - , PlutusMap - ) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.PlutusData as T -import Data.Maybe (Maybe, fromJust) -import Data.Tuple (Tuple, fst, snd) -import Data.Tuple.Nested (type (/\), (/\)) -import JS.BigInt as BigInt -import Partial.Unsafe (unsafePartial) - -convertPlutusData :: T.PlutusData -> PlutusData -convertPlutusData x = case x of - T.Constr alt list -> convertConstr alt list - T.Map mp -> convertPlutusMap mp - T.List lst -> convertPlutusList lst - T.Integer n -> convertPlutusInteger n - T.Bytes b -> _mkPlutusData_bytes b - -convertConstr :: BigNum -> Array T.PlutusData -> PlutusData -convertConstr alt list = - _mkPlutusData_constr $ _mkConstrPlutusData - alt - (_packPlutusList containerHelper $ map convertPlutusData list) - -convertPlutusList :: Array T.PlutusData -> PlutusData -convertPlutusList x = - (_mkPlutusData_list <<< (_packPlutusList containerHelper)) $ - (map convertPlutusData x) - -convertPlutusMap :: Array (T.PlutusData /\ T.PlutusData) -> PlutusData -convertPlutusMap mp = - let - entries :: Array (PlutusData /\ PlutusData) - entries = mp <#> \(k /\ v) -> (convertPlutusData k /\ convertPlutusData v) - in - _mkPlutusData_map $ _packMap fst snd entries - -convertPlutusInteger :: BigInt.BigInt -> PlutusData -convertPlutusInteger n = - _mkPlutusData_integer $ convertBigInt n - -convertBigInt :: BigInt.BigInt -> BigInt --- Unsafe is safe here, cuz both BigInt's are dynamic sized, --- so range errors are not a concern, and `BigInt.toString` always --- returns parsable string -convertBigInt n = unsafePartial $ fromJust $ - _bigIntFromString maybeFfiHelper (BigInt.toString n) - -packPlutusList :: Array T.PlutusData -> PlutusList -packPlutusList = (_packPlutusList containerHelper) - <<< map convertPlutusData - -foreign import _mkPlutusData_bytes :: ByteArray -> PlutusData -foreign import _mkPlutusData_list :: PlutusList -> PlutusData -foreign import _mkPlutusData_map :: PlutusMap -> PlutusData -foreign import _mkPlutusData_integer :: BigInt -> PlutusData -foreign import _mkPlutusData_constr :: ConstrPlutusData -> PlutusData - -foreign import _packPlutusList - :: ContainerHelper -> Array PlutusData -> PlutusList - -foreign import _mkConstrPlutusData :: BigNum -> PlutusList -> ConstrPlutusData -foreign import _bigIntFromString :: MaybeFfiHelper -> String -> Maybe BigInt -foreign import _packMap - :: (forall a b. Tuple a b -> a) - -> (forall a b. Tuple a b -> b) - -> Array (PlutusData /\ PlutusData) - -> PlutusMap diff --git a/src/Internal/Serialization/PlutusScript.js b/src/Internal/Serialization/PlutusScript.js deleted file mode 100644 index ab48270fec..0000000000 --- a/src/Internal/Serialization/PlutusScript.js +++ /dev/null @@ -1,20 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function newPlutusV1Script(bytes) { - return lib.PlutusScript.new(bytes); -} - -export function newPlutusV2Script(bytes) { - return lib.PlutusScript.new_v2(bytes); -} - -export function plutusScriptBytes(script) { - return script.bytes(); -} diff --git a/src/Internal/Serialization/PlutusScript.purs b/src/Internal/Serialization/PlutusScript.purs deleted file mode 100644 index 341ed79f16..0000000000 --- a/src/Internal/Serialization/PlutusScript.purs +++ /dev/null @@ -1,26 +0,0 @@ -module Ctl.Internal.Serialization.PlutusScript - ( plutusScriptBytes - , convertPlutusScript - ) where - -import Prelude - -import Ctl.Internal.Serialization.Types (PlutusScript) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.Scripts - ( Language(PlutusV1, PlutusV2) - , PlutusScript(PlutusScript) - ) as T -import Data.Tuple.Nested ((/\)) - -foreign import plutusScriptBytes :: PlutusScript -> ByteArray - -foreign import newPlutusV1Script :: ByteArray -> PlutusScript - -foreign import newPlutusV2Script :: ByteArray -> PlutusScript - -convertPlutusScript :: T.PlutusScript -> PlutusScript -convertPlutusScript (T.PlutusScript (bytes /\ language)) = - bytes # case language of - T.PlutusV1 -> newPlutusV1Script - T.PlutusV2 -> newPlutusV2Script diff --git a/src/Internal/Serialization/ToBytes.js b/src/Internal/Serialization/ToBytes.js deleted file mode 100644 index 7ec989fcad..0000000000 --- a/src/Internal/Serialization/ToBytes.js +++ /dev/null @@ -1,3 +0,0 @@ -export function _toBytes(sth) { - return sth.to_bytes(); -} diff --git a/src/Internal/Serialization/ToBytes.purs b/src/Internal/Serialization/ToBytes.purs deleted file mode 100644 index e9b14b87ee..0000000000 --- a/src/Internal/Serialization/ToBytes.purs +++ /dev/null @@ -1,80 +0,0 @@ -module Ctl.Internal.Serialization.ToBytes - ( toBytes - ) where - -import Prelude - -import Ctl.Internal.Serialization.Address - ( Address - , ByronAddress - , StakeCredential - ) -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash, ScriptHash, VRFKeyHash) -import Ctl.Internal.Serialization.Types - ( AuxiliaryDataHash - , DataHash - , Ed25519Signature - , GenesisDelegateHash - , GenesisHash - , Mint - , NativeScript - , PlutusData - , PoolMetadataHash - , Redeemers - , ScriptDataHash - , Transaction - , TransactionBody - , TransactionHash - , TransactionOutput - , TransactionUnspentOutput - , TransactionWitnessSet - , Value - , Vkeywitness - , Vkeywitnesses - ) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes(CborBytes)) -import Untagged.Castable (class Castable) -import Untagged.Union (type (|+|)) - -type SerializableData = Address - |+| AuxiliaryDataHash - |+| ByronAddress - |+| DataHash - |+| Ed25519KeyHash - |+| Ed25519Signature - |+| GenesisDelegateHash - |+| GenesisHash - |+| Mint - |+| NativeScript - |+| PlutusData - |+| PoolMetadataHash - |+| Redeemers - |+| ScriptDataHash - |+| ScriptHash - |+| StakeCredential - |+| Transaction - |+| TransactionBody - |+| TransactionHash - |+| TransactionOutput - |+| TransactionUnspentOutput - |+| TransactionWitnessSet - |+| Value - |+| VRFKeyHash - |+| Vkeywitness - |+| Vkeywitnesses - |+| BigNum - --- Add more as needed - --- NOTE returns cbor encoding for all but hash types, for which it returns raw bytes -foreign import _toBytes - :: forall a. a -> ByteArray - -toBytes - :: forall a - . Castable a SerializableData - => a - -> CborBytes -toBytes = CborBytes <<< _toBytes diff --git a/src/Internal/Serialization/Types.purs b/src/Internal/Serialization/Types.purs deleted file mode 100644 index 3e906b0adb..0000000000 --- a/src/Internal/Serialization/Types.purs +++ /dev/null @@ -1,171 +0,0 @@ -module Ctl.Internal.Serialization.Types - ( AssetName - , Assets - , AuxiliaryData - , AuxiliaryDataHash - , BigInt - , Bip32PrivateKey - , Bip32PublicKey - , BootstrapWitness - , BootstrapWitnesses - , Certificate - , Certificates - , ConstrPlutusData - , CostModel - , Costmdls - , DataCost - , DataHash - , Ed25519KeyHashes - , Ed25519Signature - , ExUnitPrices - , ExUnits - , GeneralTransactionMetadata - , GenesisDelegateHash - , GenesisHash - , GenesisKeyDelegation - , Ipv4 - , Ipv6 - , Language - , MIRToStakeCredentials - , MetadataList - , MetadataMap - , Mint - , MintAssets - , MoveInstantaneousReward - , MultiAsset - , MultiHostName - , NativeScript - , NativeScripts - , NetworkId - , Nonce - , PlutusData - , PlutusList - , PlutusMap - , PlutusScript - , PlutusScripts - , PoolMetadata - , PoolMetadataHash - , PoolParams - , PrivateKey - , ProposedProtocolParameterUpdates - , ProtocolParamUpdate - , ProtocolVersion - , PublicKey - , Redeemer - , RedeemerTag - , Redeemers - , Relay - , Relays - , ScriptAll - , ScriptAny - , ScriptDataHash - , ScriptNOfK - , ScriptPubkey - , ScriptRef - , SingleHostAddr - , SingleHostName - , TimelockExpiry - , TimelockStart - , Transaction - , TransactionBody - , TransactionHash - , TransactionInput - , TransactionInputs - , TransactionMetadatum - , TransactionOutput - , TransactionOutputs - , TransactionUnspentOutput - , TransactionWitnessSet - , UnitInterval - , Update - , Value - , Vkey - , Vkeywitness - , Vkeywitnesses - , Withdrawals - ) where - -foreign import data AssetName :: Type -foreign import data Assets :: Type -foreign import data AuxiliaryData :: Type -foreign import data AuxiliaryDataHash :: Type -foreign import data BigInt :: Type -foreign import data Bip32PrivateKey :: Type -foreign import data Bip32PublicKey :: Type -foreign import data BootstrapWitness :: Type -foreign import data BootstrapWitnesses :: Type -foreign import data Certificate :: Type -foreign import data Certificates :: Type -foreign import data ConstrPlutusData :: Type -foreign import data CostModel :: Type -foreign import data Costmdls :: Type -foreign import data DataCost :: Type -foreign import data DataHash :: Type -foreign import data Ed25519KeyHashes :: Type -foreign import data Ed25519Signature :: Type -foreign import data ExUnitPrices :: Type -foreign import data ExUnits :: Type -foreign import data GeneralTransactionMetadata :: Type -foreign import data GenesisDelegateHash :: Type -foreign import data GenesisHash :: Type -foreign import data GenesisKeyDelegation :: Type -foreign import data Ipv4 :: Type -foreign import data Ipv6 :: Type -foreign import data Language :: Type -foreign import data MIRToStakeCredentials :: Type -foreign import data MetadataList :: Type -foreign import data MetadataMap :: Type -foreign import data Mint :: Type -foreign import data MintAssets :: Type -foreign import data MoveInstantaneousReward :: Type -foreign import data MultiAsset :: Type -foreign import data MultiHostName :: Type -foreign import data NativeScript :: Type -foreign import data NativeScripts :: Type -foreign import data NetworkId :: Type -foreign import data Nonce :: Type -foreign import data PlutusData :: Type -foreign import data PlutusList :: Type -foreign import data PlutusMap :: Type -foreign import data PlutusScript :: Type -foreign import data PlutusScripts :: Type -foreign import data PoolMetadata :: Type -foreign import data PoolMetadataHash :: Type -foreign import data PoolParams :: Type -foreign import data ProposedProtocolParameterUpdates :: Type -foreign import data ProtocolParamUpdate :: Type -foreign import data ProtocolVersion :: Type -foreign import data PublicKey :: Type -foreign import data PrivateKey :: Type -foreign import data Redeemer :: Type -foreign import data RedeemerTag :: Type -foreign import data Redeemers :: Type -foreign import data Relay :: Type -foreign import data Relays :: Type -foreign import data ScriptAll :: Type -foreign import data ScriptAny :: Type -foreign import data ScriptDataHash :: Type -foreign import data ScriptNOfK :: Type -foreign import data ScriptPubkey :: Type -foreign import data ScriptRef :: Type -foreign import data SingleHostAddr :: Type -foreign import data SingleHostName :: Type -foreign import data TimelockExpiry :: Type -foreign import data TimelockStart :: Type -foreign import data Transaction :: Type -foreign import data TransactionBody :: Type -foreign import data TransactionHash :: Type -foreign import data TransactionInput :: Type -foreign import data TransactionInputs :: Type -foreign import data TransactionMetadatum :: Type -foreign import data TransactionOutput :: Type -foreign import data TransactionOutputs :: Type -foreign import data TransactionUnspentOutput :: Type -foreign import data TransactionWitnessSet :: Type -foreign import data UnitInterval :: Type -foreign import data Update :: Type -foreign import data Value :: Type -foreign import data Vkey :: Type -foreign import data Vkeywitness :: Type -foreign import data Vkeywitnesses :: Type -foreign import data Withdrawals :: Type diff --git a/src/Internal/Serialization/WitnessSet.js b/src/Internal/Serialization/WitnessSet.js deleted file mode 100644 index 96b8fd2cda..0000000000 --- a/src/Internal/Serialization/WitnessSet.js +++ /dev/null @@ -1,95 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export function newTransactionWitnessSet() { - return lib.TransactionWitnessSet.new(); -} - -export function newPublicKey(bech32) { - return () => lib.PublicKey.from_bech32(bech32); -} - -export function newVkeyFromPublicKey(public_key) { - return () => lib.Vkey.new(public_key); -} - -export function newVkeywitnesses() { - return lib.Vkeywitnesses.new(); -} - -export function newVkeywitness(vkey) { - return signature => () => lib.Vkeywitness.new(vkey, signature); -} - -export function addVkeywitness(witnesses) { - return witness => () => witnesses.add(witness); -} - -export function newPlutusScripts() { - return lib.PlutusScripts.new(); -} - -export function addPlutusScript(scripts) { - return script => () => scripts.add(script); -} - -export function transactionWitnessSetSetVkeys(ws) { - return vkeys => () => ws.set_vkeys(vkeys); -} - -export function txWitnessSetSetPlutusScripts(ws) { - return scripts => () => ws.set_plutus_scripts(scripts); -} - -export function transactionWitnessSetSetNativeScripts(ws) { - return scripts => () => ws.set_native_scripts(scripts); -} - -export function _wsSetBootstraps(helper) { - return ws => bootstraps => () => - ws.set_bootstraps(helper.pack(lib.BootstrapWitnesses, bootstraps)); -} - -export function newBootstrapWitness(vkey) { - return signature => chain_code => attributes => () => { - lib.BootstrapWitness.new(vkey, signature, chain_code, attributes); - }; -} - -export function _wsSetPlutusData(helper) { - return ws => plutus_data => () => - ws.set_plutus_data(helper.pack(lib.PlutusList, plutus_data)); -} - -export function newRedeemer(tag) { - return index => data => ex_units => () => - lib.Redeemer.new(tag, index, data, ex_units); -} - -export function _newRedeemerTag(tag) { - return () => lib.RedeemerTag["new_" + tag](); -} - -export function newExUnits(mem) { - return steps => lib.ExUnits.new(mem, steps); -} - -export function _wsSetRedeemers(helper) { - return ws => redeemers => () => - ws.set_redeemers(helper.pack(lib.Redeemers, redeemers)); -} - -export function _mkRedeemers(helper) { - return redeemers => helper.pack(lib.Redeemers, redeemers); -} - -export function _wsSetPlutusScripts(helper) { - return ws => scripts => () => - ws.set_plutus_scripts(helper.pack(lib.PlutusScripts, scripts)); -} diff --git a/src/Internal/Serialization/WitnessSet.purs b/src/Internal/Serialization/WitnessSet.purs deleted file mode 100644 index 5c09c17da7..0000000000 --- a/src/Internal/Serialization/WitnessSet.purs +++ /dev/null @@ -1,213 +0,0 @@ -module Ctl.Internal.Serialization.WitnessSet - ( setPlutusData - , setRedeemers - , setPlutusScripts - , convertWitnessSet - , convertRedeemers - , convertRedeemer - , convertRedeemerTag - , convertExUnits - , convertBootstrap - , convertVkeywitnesses - , convertVkeywitness - , convertVkey - , newTransactionWitnessSet - , newPublicKey - , newVkeyFromPublicKey - , newVkeywitnesses - , newVkeywitness - , addVkeywitness - , newPlutusScripts - , addPlutusScript - , transactionWitnessSetSetVkeys - , txWitnessSetSetPlutusScripts - , transactionWitnessSetSetNativeScripts - , _wsSetBootstraps - , newBootstrapWitness - , _wsSetPlutusData - , newRedeemer - , _newRedeemerTag - , newExUnits - , _wsSetRedeemers - , _mkRedeemers - , _wsSetPlutusScripts - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.Transaction - ( BootstrapWitness - , ExUnits - , Redeemer(Redeemer) - , TransactionWitnessSet(TransactionWitnessSet) - , Vkey(Vkey) - , Vkeywitness(Vkeywitness) - , convertEd25519Signature - , convertPubKey - ) as T -import Ctl.Internal.FfiHelpers (ContainerHelper, containerHelper) -import Ctl.Internal.Serialization.NativeScript (convertNativeScripts) -import Ctl.Internal.Serialization.PlutusData (convertPlutusData) -import Ctl.Internal.Serialization.PlutusScript (convertPlutusScript) -import Ctl.Internal.Serialization.Types - ( BootstrapWitness - , Ed25519Signature - , ExUnits - , NativeScripts - , PlutusScript - , PlutusScripts - , PublicKey - , Redeemer - , RedeemerTag - , Redeemers - , TransactionWitnessSet - , Vkey - , Vkeywitness - , Vkeywitnesses - ) -import Ctl.Internal.Serialization.Types (PlutusData) as PDS -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum (fromBigInt) as BigNum -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.RedeemerTag as Tag -import Data.Maybe (maybe) -import Data.Traversable (for_, traverse, traverse_) -import Data.Tuple.Nested ((/\)) -import Effect (Effect) -import Effect.Exception (throw) - -setPlutusData :: Array PDS.PlutusData -> TransactionWitnessSet -> Effect Unit -setPlutusData pd ws = setWitnesses _wsSetPlutusData ws pd - -setRedeemers :: Array Redeemer -> TransactionWitnessSet -> Effect Unit -setRedeemers rs ws = setWitnesses _wsSetRedeemers ws rs - -setPlutusScripts :: Array PlutusScript -> TransactionWitnessSet -> Effect Unit -setPlutusScripts ps ws = setWitnesses _wsSetPlutusScripts ws ps - -setWitnesses - :: forall (a :: Type) - . (ContainerHelper -> TransactionWitnessSet -> Array a -> Effect Unit) - -> TransactionWitnessSet - -> Array a - -> Effect Unit -setWitnesses f ws = f containerHelper ws - -convertWitnessSet :: T.TransactionWitnessSet -> Effect TransactionWitnessSet -convertWitnessSet (T.TransactionWitnessSet tws) = do - ws <- newTransactionWitnessSet - for_ tws.vkeys - (convertVkeywitnesses >=> transactionWitnessSetSetVkeys ws) - for_ tws.nativeScripts $ - transactionWitnessSetSetNativeScripts ws <<< convertNativeScripts - for_ tws.bootstraps - (traverse convertBootstrap >=> _wsSetBootstraps containerHelper ws) - for_ tws.plutusScripts \ps -> do - scripts <- newPlutusScripts - for_ ps (convertPlutusScript >>> addPlutusScript scripts) - txWitnessSetSetPlutusScripts ws scripts - for_ tws.plutusData - (map convertPlutusData >>> _wsSetPlutusData containerHelper ws) - for_ tws.redeemers - (traverse convertRedeemer >=> _wsSetRedeemers containerHelper ws) - pure ws - -convertRedeemers :: Array T.Redeemer -> Effect Redeemers -convertRedeemers redeemers = do - _mkRedeemers containerHelper <$> traverse convertRedeemer redeemers - -convertRedeemer :: T.Redeemer -> Effect Redeemer -convertRedeemer (T.Redeemer { tag, index, "data": data_, exUnits }) = do - tag' <- convertRedeemerTag tag - index' <- maybe (throw "Failed to convert redeemer index") pure $ - BigNum.fromBigInt index - let data' = convertPlutusData data_ - exUnits' <- convertExUnits exUnits - newRedeemer tag' index' data' exUnits' - -convertRedeemerTag :: Tag.RedeemerTag -> Effect RedeemerTag -convertRedeemerTag = _newRedeemerTag <<< case _ of - Tag.Spend -> "spend" - Tag.Mint -> "mint" - Tag.Cert -> "cert" - Tag.Reward -> "reward" - -convertExUnits :: T.ExUnits -> Effect ExUnits -convertExUnits { mem, steps } = - maybe (throw "Failed to construct ExUnits") pure do - mem' <- BigNum.fromBigInt mem - steps' <- BigNum.fromBigInt steps - pure $ newExUnits mem' steps' - -convertBootstrap :: T.BootstrapWitness -> Effect BootstrapWitness -convertBootstrap { vkey, signature, chainCode, attributes } = do - vkey' <- convertVkey vkey - let signature' = T.convertEd25519Signature signature - newBootstrapWitness vkey' signature' chainCode attributes - -convertVkeywitnesses :: Array T.Vkeywitness -> Effect Vkeywitnesses -convertVkeywitnesses arr = do - witnesses <- newVkeywitnesses - traverse_ (convertVkeywitness >=> addVkeywitness witnesses) arr - pure witnesses - -convertVkeywitness :: T.Vkeywitness -> Effect Vkeywitness -convertVkeywitness (T.Vkeywitness (vkey /\ signature)) = do - vkey' <- convertVkey vkey - let signature' = T.convertEd25519Signature signature - newVkeywitness vkey' signature' - -convertVkey :: T.Vkey -> Effect Vkey -convertVkey (T.Vkey pk) = newVkeyFromPublicKey $ T.convertPubKey pk - -foreign import newTransactionWitnessSet :: Effect TransactionWitnessSet -foreign import newPublicKey :: Bech32String -> Effect PublicKey -foreign import newVkeyFromPublicKey :: PublicKey -> Effect Vkey -foreign import newVkeywitnesses :: Effect Vkeywitnesses -foreign import newVkeywitness :: Vkey -> Ed25519Signature -> Effect Vkeywitness -foreign import addVkeywitness :: Vkeywitnesses -> Vkeywitness -> Effect Unit -foreign import newPlutusScripts :: Effect PlutusScripts -foreign import addPlutusScript :: PlutusScripts -> PlutusScript -> Effect Unit -foreign import transactionWitnessSetSetVkeys - :: TransactionWitnessSet -> Vkeywitnesses -> Effect Unit - -foreign import txWitnessSetSetPlutusScripts - :: TransactionWitnessSet -> PlutusScripts -> Effect Unit - -foreign import transactionWitnessSetSetNativeScripts - :: TransactionWitnessSet -> NativeScripts -> Effect Unit - -foreign import _wsSetBootstraps - :: ContainerHelper - -> TransactionWitnessSet - -> Array BootstrapWitness - -> Effect Unit - -foreign import newBootstrapWitness - :: Vkey - -> Ed25519Signature - -> ByteArray - -> ByteArray - -> Effect BootstrapWitness - -foreign import _wsSetPlutusData - :: ContainerHelper - -> TransactionWitnessSet - -> Array PDS.PlutusData - -> Effect Unit - -foreign import newRedeemer - :: RedeemerTag -> BigNum -> PDS.PlutusData -> ExUnits -> Effect Redeemer - -foreign import _newRedeemerTag :: String -> Effect RedeemerTag -foreign import newExUnits :: BigNum -> BigNum -> ExUnits -foreign import _wsSetRedeemers - :: ContainerHelper -> TransactionWitnessSet -> Array Redeemer -> Effect Unit - -foreign import _mkRedeemers :: ContainerHelper -> Array Redeemer -> Redeemers -foreign import _wsSetPlutusScripts - :: ContainerHelper - -> TransactionWitnessSet - -> Array PlutusScript - -> Effect Unit diff --git a/src/Internal/ServerConfig.purs b/src/Internal/ServerConfig.purs index 76d4a883ba..8b42d91096 100644 --- a/src/Internal/ServerConfig.purs +++ b/src/Internal/ServerConfig.purs @@ -4,6 +4,7 @@ module Ctl.Internal.ServerConfig , blockfrostPublicMainnetServerConfig , blockfrostPublicPreprodServerConfig , blockfrostPublicPreviewServerConfig + , blockfrostPublicSanchonetServerConfig , blockfrostSelfHostedServerConfig , defaultKupoServerConfig , defaultOgmiosWsConfig @@ -61,6 +62,14 @@ blockfrostPublicPreprodServerConfig = , path: Just "/api/v0" } +blockfrostPublicSanchonetServerConfig :: ServerConfig +blockfrostPublicSanchonetServerConfig = + { port: UInt.fromInt 443 + , host: "cardano-sanchonet.blockfrost.io" + , secure: true + , path: Just "/api/v0" + } + blockfrostPublicMainnetServerConfig :: ServerConfig blockfrostPublicMainnetServerConfig = { port: UInt.fromInt 443 diff --git a/src/Internal/Service/Blockfrost.purs b/src/Internal/Service/Blockfrost.purs index 59abc11e28..e873e691ad 100644 --- a/src/Internal/Service/Blockfrost.purs +++ b/src/Internal/Service/Blockfrost.purs @@ -49,6 +49,7 @@ module Ctl.Internal.Service.Blockfrost , getScriptByHash , getScriptInfo , getSystemStart + , getTxAuxiliaryData , getTxMetadata , getUtxoByOref , getValidatorHashDelegationsAndRewards @@ -81,11 +82,61 @@ import Affjax.RequestBody (RequestBody, arrayView, string) as Affjax import Affjax.RequestHeader (RequestHeader(ContentType, RequestHeader)) as Affjax import Affjax.ResponseFormat (string) as Affjax.ResponseFormat import Affjax.StatusCode (StatusCode(StatusCode)) as Affjax -import Contract.RewardAddress - ( rewardAddressToBech32 - , stakePubKeyHashRewardAddress - , stakeValidatorHashRewardAddress +import Cardano.AsCbor (decodeCbor, encodeCbor) +import Cardano.Serialization.Lib (toBytes) +import Cardano.Types + ( AssetClass(AssetClass) + , AuxiliaryData + , DataHash + , GeneralTransactionMetadata(GeneralTransactionMetadata) + , Language(PlutusV3, PlutusV2, PlutusV1) + , PlutusData + , PoolPubKeyHash + , RawBytes + , RedeemerTag + , ScriptHash + , StakePubKeyHash + , Transaction + , TransactionHash + , TransactionInput(TransactionInput) + , TransactionOutput(TransactionOutput) + , UnitInterval(UnitInterval) + , UtxoMap + , Value + ) +import Cardano.Types.Address (Address) +import Cardano.Types.Address as Address +import Cardano.Types.Bech32String (Bech32String) +import Cardano.Types.BigNum (BigNum) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.CborBytes (CborBytes) +import Cardano.Types.Coin (Coin(Coin)) +import Cardano.Types.Credential + ( Credential(PubKeyHashCredential, ScriptHashCredential) + ) +import Cardano.Types.Epoch (Epoch(Epoch)) +import Cardano.Types.ExUnitPrices (ExUnitPrices(ExUnitPrices)) +import Cardano.Types.ExUnits (ExUnits(ExUnits)) +import Cardano.Types.GeneralTransactionMetadata as GeneralTransactionMetadata +import Cardano.Types.NativeScript + ( NativeScript + ( ScriptAll + , ScriptAny + , ScriptNOfK + , ScriptPubkey + , TimelockExpiry + , TimelockStart + ) ) +import Cardano.Types.NetworkId (NetworkId) +import Cardano.Types.OutputDatum (OutputDatum(OutputDatum, OutputDatumHash)) +import Cardano.Types.PlutusScript (PlutusScript) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.PoolPubKeyHash as PoolPubKeyHash +import Cardano.Types.RedeemerTag (RedeemerTag(Spend, Mint, Cert, Reward)) as RedeemerTag +import Cardano.Types.RewardAddress as RewardAddress +import Cardano.Types.ScriptRef (ScriptRef(NativeScriptRef, PlutusScriptRef)) +import Cardano.Types.Value (assetToValue, lovelaceValueOf, sum) as Value import Control.Alt ((<|>)) import Control.Monad.Error.Class (liftMaybe, throwError) import Control.Monad.Except.Trans (ExceptT(ExceptT), runExceptT) @@ -97,33 +148,6 @@ import Control.Monad.Reader.Class (ask, asks) import Control.Monad.Reader.Trans (ReaderT, runReaderT) import Control.Parallel (parTraverse) import Ctl.Internal.Affjax (request) as Affjax -import Ctl.Internal.Cardano.Types.NativeScript - ( NativeScript - ( ScriptAll - , ScriptAny - , ScriptNOfK - , ScriptPubkey - , TimelockExpiry - , TimelockStart - ) - ) -import Ctl.Internal.Cardano.Types.ScriptRef - ( ScriptRef(NativeScriptRef, PlutusScriptRef) - ) -import Ctl.Internal.Cardano.Types.Transaction - ( Costmdls(Costmdls) - , PoolPubKeyHash - , Transaction - , TransactionOutput(TransactionOutput) - , UtxoMap - , poolPubKeyHashToBech32 - ) -import Ctl.Internal.Cardano.Types.Value (Coin(Coin), Value) -import Ctl.Internal.Cardano.Types.Value - ( lovelaceValueOf - , mkSingletonNonAdaAsset - , mkValue - ) as Value import Ctl.Internal.Contract.QueryBackend (BlockfrostBackend) import Ctl.Internal.Contract.QueryHandle.Error ( GetTxMetadataError @@ -132,11 +156,6 @@ import Ctl.Internal.Contract.QueryHandle.Error , GetTxMetadataMetadataEmptyOrMissingError ) ) -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.Deserialization.PlutusData (deserializeData) -import Ctl.Internal.Deserialization.Transaction - ( convertGeneralTransactionMetadata - ) import Ctl.Internal.QueryM.Ogmios ( AdditionalUtxoSet , ExecutionUnits @@ -148,22 +167,8 @@ import Ctl.Internal.QueryM.Ogmios , TxEvaluationFailure(ScriptFailures, UnparsedError) , TxEvaluationR , TxEvaluationResult(TxEvaluationResult) - , decodeRedeemerPointer ) import Ctl.Internal.QueryM.Ogmios as Ogmios -import Ctl.Internal.QueryM.Pools (DelegationsAndRewards) -import Ctl.Internal.Serialization as Serialization -import Ctl.Internal.Serialization.Address - ( Address - , NetworkId - , addressBech32 - , addressFromBech32 - ) -import Ctl.Internal.Serialization.Hash - ( ScriptHash - , ed25519KeyHashFromBytes - , scriptHashToBytes - ) import Ctl.Internal.ServerConfig (ServerConfig, mkHttpUrl) import Ctl.Internal.Service.Error ( ClientError @@ -180,81 +185,62 @@ import Ctl.Internal.Service.Helpers , aesonString , decodeAssetClass ) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum as BigNum -import Ctl.Internal.Types.ByteArray (ByteArray, byteArrayToHex) -import Ctl.Internal.Types.CborBytes (CborBytes, cborBytesToHex) import Ctl.Internal.Types.Chain (Tip(Tip, TipAtGenesis)) -import Ctl.Internal.Types.Datum (DataHash(DataHash), Datum) -import Ctl.Internal.Types.Epoch (Epoch(Epoch)) +import Ctl.Internal.Types.DelegationsAndRewards (DelegationsAndRewards) import Ctl.Internal.Types.EraSummaries ( EraSummaries , EraSummary , EraSummaryParameters ) -import Ctl.Internal.Types.OutputDatum - ( OutputDatum(NoOutputDatum, OutputDatum, OutputDatumHash) - ) import Ctl.Internal.Types.ProtocolParameters - ( CoinsPerUtxoUnit(CoinsPerUtxoWord, CoinsPerUtxoByte) - , CostModelV1 + ( CostModelV1 , CostModelV2 + , CostModelV3 , ProtocolParameters(ProtocolParameters) , convertPlutusV1CostModel , convertPlutusV2CostModel + , convertPlutusV3CostModel ) -import Ctl.Internal.Types.PubKeyHash (StakePubKeyHash) import Ctl.Internal.Types.Rational (Rational, reduce) -import Ctl.Internal.Types.RawBytes (rawBytesToHex) -import Ctl.Internal.Types.Scripts - ( Language(PlutusV2, PlutusV1) - , StakeValidatorHash - , plutusV1Script - , plutusV2Script - ) +import Ctl.Internal.Types.StakeValidatorHash (StakeValidatorHash) import Ctl.Internal.Types.SystemStart (SystemStart(SystemStart)) -import Ctl.Internal.Types.Transaction - ( TransactionHash - , TransactionInput(TransactionInput) - ) -import Ctl.Internal.Types.TransactionMetadata - ( GeneralTransactionMetadata(GeneralTransactionMetadata) - ) +import Data.Array (catMaybes) import Data.Array (find, length) as Array import Data.Bifunctor (lmap) import Data.BigNumber (BigNumber, toFraction) import Data.BigNumber as BigNumber +import Data.ByteArray (ByteArray, byteArrayToHex) import Data.DateTime.Instant (instant, toDateTime) import Data.Either (Either(Left, Right), either, hush, note) -import Data.Foldable (fold) import Data.Generic.Rep (class Generic) import Data.HTTP.Method (Method(GET, POST)) import Data.JSDate (JSDate, now) import Data.Log.Level (LogLevel(Trace)) import Data.Log.Message (Message) import Data.Map (Map) -import Data.Map (empty, fromFoldable, isEmpty, unions) as Map +import Data.Map (empty, fromFoldable, isEmpty) as Map import Data.Maybe (Maybe(Just, Nothing), fromMaybe, maybe) import Data.MediaType (MediaType(MediaType)) import Data.MediaType.Common (applicationJSON) as MediaType import Data.Newtype (class Newtype, unwrap, wrap) import Data.Number (infinity) import Data.Show.Generic (genericShow) -import Data.String (splitAt) as String +import Data.String (Pattern(Pattern)) +import Data.String (split, splitAt) as String import Data.Time.Duration (Seconds(Seconds), convertDuration) import Data.Traversable (for, for_, traverse) import Data.Tuple (Tuple(Tuple), fst, snd) import Data.Tuple.Nested (type (/\), (/\)) import Data.UInt (UInt) +import Data.UInt (fromString) as UInt import Effect.Aff (Aff) import Effect.Aff.Class (liftAff) import Effect.Class (liftEffect) import Effect.Exception (error) import Foreign.Object (Object) import Foreign.Object as ForeignObject -import JS.BigInt (BigInt) import JS.BigInt (fromString, toNumber) as BigInt +import Prim.TypeError (class Warn, Text) -------------------------------------------------------------------------------- -- BlockfrostServiceM @@ -374,8 +360,8 @@ realizeEndpoint endpoint = case endpoint of BlockchainGenesis -> "/genesis" - DatumCbor (DataHash hashBytes) -> - "/scripts/datum/" <> byteArrayToHex hashBytes <> "/cbor" + DatumCbor hash -> + "/scripts/datum/" <> byteArrayToHex (unwrap $ encodeCbor hash) <> "/cbor" EraSummaries -> "/network/eras" EvaluateTransaction -> @@ -387,26 +373,26 @@ realizeEndpoint endpoint = LatestProtocolParameters -> "/epochs/latest/parameters" NativeScriptByHash scriptHash -> - "/scripts/" <> rawBytesToHex (scriptHashToBytes scriptHash) <> "/json" + "/scripts/" <> byteArrayToHex (unwrap $ encodeCbor scriptHash) <> "/json" PlutusScriptCborByHash scriptHash -> - "/scripts/" <> rawBytesToHex (scriptHashToBytes scriptHash) <> "/cbor" + "/scripts/" <> byteArrayToHex (unwrap $ encodeCbor scriptHash) <> "/cbor" ScriptInfo scriptHash -> - "/scripts/" <> rawBytesToHex (scriptHashToBytes scriptHash) + "/scripts/" <> byteArrayToHex (unwrap $ encodeCbor scriptHash) SubmitTransaction -> "/tx/submit" Transaction txHash -> - "/txs/" <> byteArrayToHex (unwrap txHash) + "/txs/" <> byteArrayToHex (toBytes $ unwrap txHash) TransactionMetadata txHash -> - "/txs/" <> byteArrayToHex (unwrap txHash) <> "/metadata/cbor" + "/txs/" <> byteArrayToHex (toBytes $ unwrap txHash) <> "/metadata/cbor" UtxosAtAddress address page count -> - "/addresses/" <> addressBech32 address <> "/utxos?page=" <> show page + "/addresses/" <> Address.toBech32 address <> "/utxos?page=" <> show page <> ("&count=" <> show count) UtxosOfTransaction txHash -> - "/txs/" <> byteArrayToHex (unwrap txHash) <> "/utxos" + "/txs/" <> byteArrayToHex (toBytes $ unwrap txHash) <> "/utxos" PoolIds page count -> "/pools?page=" <> show page <> "&count=" <> show count <> "&order=asc" PoolParameters poolPubKeyHash -> - "/pool/" <> poolPubKeyHashToBech32 poolPubKeyHash + "/pool/" <> PoolPubKeyHash.toBech32 poolPubKeyHash DelegationsAndRewards credential -> "/accounts/" <> blockfrostStakeCredentialToBech32 credential @@ -589,7 +575,7 @@ getOutputAddressesByTxHash txHash = runExceptT do -------------------------------------------------------------------------------- getDatumByHash - :: DataHash -> BlockfrostServiceM (Either ClientError (Maybe Datum)) + :: DataHash -> BlockfrostServiceM (Either ClientError (Maybe PlutusData)) getDatumByHash dataHash = blockfrostGetRequest (DatumCbor dataHash) <#> \response -> handle404AsNothing @@ -609,10 +595,10 @@ getScriptByHash scriptHash = runExceptT $ runMaybeT do NativeScriptRef <$> MaybeT (ExceptT getNativeScriptByHash) PlutusV1Script -> - PlutusScriptRef <<< plutusV1Script <$> + PlutusScriptRef <<< PlutusScript.plutusV1Script <$> MaybeT (ExceptT getPlutusScriptCborByHash) PlutusV2Script -> - PlutusScriptRef <<< plutusV2Script <$> + PlutusScriptRef <<< PlutusScript.plutusV2Script <$> MaybeT (ExceptT getPlutusScriptCborByHash) where getNativeScriptByHash @@ -623,11 +609,13 @@ getScriptByHash scriptHash = runExceptT $ runMaybeT do handle404AsNothing (handleBlockfrostResponse response) getPlutusScriptCborByHash - :: BlockfrostServiceM (Either ClientError (Maybe ByteArray)) + :: BlockfrostServiceM (Either ClientError (Maybe RawBytes)) getPlutusScriptCborByHash = blockfrostGetRequest (PlutusScriptCborByHash scriptHash) <#> \response -> handle404AsNothing - (unwrapBlockfrostCbor <$> handleBlockfrostResponse response) + ( map wrap <<< unwrapBlockfrostCbor <$> handleBlockfrostResponse + response + ) getScriptInfo :: ScriptHash @@ -644,15 +632,14 @@ submitTx :: Transaction -> BlockfrostServiceM (Either ClientError TransactionHash) submitTx tx = do - cslTx <- liftEffect $ Serialization.convertTransaction tx - handleBlockfrostResponse <$> request (Serialization.toBytes cslTx) + handleBlockfrostResponse <$> request (unwrap $ encodeCbor tx) where request - :: CborBytes + :: ByteArray -> BlockfrostServiceM (Either Affjax.Error (Affjax.Response String)) request cbor = blockfrostPostRequest SubmitTransaction (MediaType "application/cbor") - (Just $ Affjax.arrayView $ unwrap $ unwrap cbor) + (Just $ Affjax.arrayView $ unwrap cbor) evaluateTx :: Transaction -> AdditionalUtxoSet -> BlockfrostServiceM TxEvaluationR @@ -668,11 +655,10 @@ evaluateTx tx additionalUtxos = do where request :: BlockfrostServiceM (Either Affjax.Error (Affjax.Response String)) request = do - cslTx <- liftEffect $ Serialization.convertTransaction tx blockfrostPostRequest EvaluateTransaction MediaType.applicationJSON ( Just $ Affjax.string $ stringifyAeson $ encodeAeson - { cbor: cborBytesToHex $ Serialization.toBytes cslTx + { cbor: byteArrayToHex $ unwrap $ encodeCbor tx , additionalUtxoSet: additionalUtxos } ) @@ -692,29 +678,85 @@ doesTxExist txHash = do Left e -> Left e -------------------------------------------------------------------------------- --- Get transaction metadata --------------------------------------------------------------------------------- +-- Get transaction auxiliary data +getTxAuxiliaryData + :: TransactionHash + -> BlockfrostServiceM (Either GetTxMetadataError AuxiliaryData) +getTxAuxiliaryData txHash = runExceptT do + metadata <- ExceptT $ getMetadata + scriptRefs <- ExceptT $ getTxScripts txHash + pure $ wrap + { metadata: Just metadata + , nativeScripts: arrayToMaybe $ getNativeScripts scriptRefs + , plutusScripts: arrayToMaybe $ getPlutusScripts scriptRefs + } + + where + + getMetadata = do + response <- blockfrostGetRequest (TransactionMetadata txHash) + pure case unwrapBlockfrostMetadata <$> handleBlockfrostResponse response of + Left (ClientHttpResponseError (Affjax.StatusCode 404) _) -> + Left GetTxMetadataTxNotFoundError + Left e -> Left (GetTxMetadataClientError e) + Right metadata + | Map.isEmpty (unwrap metadata) -> + Left GetTxMetadataMetadataEmptyOrMissingError + | otherwise -> Right metadata + + getNativeScripts :: Array ScriptRef -> Array NativeScript + getNativeScripts = catMaybes <<< map isNativeScript + where + isNativeScript (NativeScriptRef script) = Just script + isNativeScript (PlutusScriptRef _) = Nothing + + getPlutusScripts :: Array ScriptRef -> Array PlutusScript + getPlutusScripts = catMaybes <<< map isPlutusScript + where + isPlutusScript (PlutusScriptRef script) = Just script + isPlutusScript (NativeScriptRef _) = Nothing + + arrayToMaybe :: forall a. Array a -> Maybe (Array a) + arrayToMaybe [] = Nothing + arrayToMaybe xs = Just xs getTxMetadata - :: TransactionHash + :: Warn + ( Text + "deprecated: getTxMetadata. use Ctl.Internal.Service.Blockfrost.getTxAuxiliaryData" + ) + => TransactionHash -> BlockfrostServiceM (Either GetTxMetadataError GeneralTransactionMetadata) getTxMetadata txHash = do - response <- blockfrostGetRequest (TransactionMetadata txHash) - pure case unwrapBlockfrostMetadata <$> handleBlockfrostResponse response of - Left (ClientHttpResponseError (Affjax.StatusCode 404) _) -> - Left GetTxMetadataTxNotFoundError - Left e -> - Left (GetTxMetadataClientError e) - Right metadata - | Map.isEmpty (unwrap metadata) -> - Left GetTxMetadataMetadataEmptyOrMissingError - | otherwise -> Right metadata + eAuxData <- getTxAuxiliaryData txHash + pure $ case eAuxData of + Left err -> Left err + Right auxiliaryData -> case (unwrap auxiliaryData).metadata of + Nothing -> Left GetTxMetadataMetadataEmptyOrMissingError + Just metadata -> Right metadata + +getTxScripts + :: TransactionHash + -> BlockfrostServiceM (Either GetTxMetadataError (Array ScriptRef)) +getTxScripts txHash = runExceptT do + (blockfrostUtxoMap :: BlockfrostUtxosOfTransaction) <- ExceptT $ + blockfrostGetRequest (UtxosOfTransaction txHash) + <#> lmap GetTxMetadataClientError <<< handle404AsMempty <<< + handleBlockfrostResponse + let + (scriptHashes :: Array ScriptHash) = catMaybes + $ map (_.scriptHash <<< unwrap <<< snd) + $ unwrap blockfrostUtxoMap + catMaybes <$> traverse (ExceptT <<< scriptByHash) scriptHashes + + where + scriptByHash t = (lmap GetTxMetadataClientError) <$> getScriptByHash t -------------------------------------------------------------------------------- -- Get current epoch information -------------------------------------------------------------------------------- -getCurrentEpoch :: BlockfrostServiceM (Either ClientError BigInt) +getCurrentEpoch :: BlockfrostServiceM (Either ClientError BigNum) getCurrentEpoch = blockfrostGetRequest LatestEpoch <#> handleBlockfrostResponse >>> map unwrapBlockfrostCurrentEpoch @@ -937,6 +979,28 @@ decodeBlockfrostTxEvaluationResult = aesonObject $ \obj -> do steps <- getField exUnitsObj "steps" pure $ redeemerPtr /\ { memory, steps } +decodeRedeemerPointer :: String -> Either JsonDecodeError RedeemerPointer +decodeRedeemerPointer redeemerPtrRaw = note redeemerPtrTypeMismatch + case String.split (Pattern ":") redeemerPtrRaw of + [ tagRaw, indexRaw ] -> + { redeemerTag: _, redeemerIndex: _ } + <$> redeemerTagFromString tagRaw + <*> UInt.fromString indexRaw + _ -> Nothing + +redeemerTagFromString :: String -> Maybe RedeemerTag +redeemerTagFromString = case _ of + "spend" -> Just RedeemerTag.Spend + "mint" -> Just RedeemerTag.Mint + "certificate" -> Just RedeemerTag.Cert + "withdrawal" -> Just RedeemerTag.Reward + _ -> Nothing + +redeemerPtrTypeMismatch :: JsonDecodeError +redeemerPtrTypeMismatch = TypeMismatch + "Expected redeemer pointer to be encoded as: \ + \^(spend|mint|certificate|withdrawal):[0-9]+$" + data OldScriptFailure = ExtraRedeemers (Array RedeemerPointer) | MissingRequiredDatums @@ -1143,7 +1207,7 @@ instance DecodeAeson BlockfrostUtxosOfTransaction where newtype BlockfrostTransactionOutput = BlockfrostTransactionOutput { address :: Address , amount :: Value - , datum :: OutputDatum + , datum :: Maybe OutputDatum , scriptHash :: Maybe ScriptHash } @@ -1165,34 +1229,39 @@ instance DecodeAeson BlockfrostTransactionOutput where decodeAddress obj = getField obj "address" >>= \address -> note (TypeMismatch "Expected bech32 encoded address") - (addressFromBech32 address) + (Address.fromBech32 address) decodeValue :: Object Aeson -> Either JsonDecodeError Value decodeValue = - flip getField "amount" >=> aesonArray (map fold <<< traverse decodeAsset) + flip getField "amount" + >=> aesonArray (traverse decodeAsset) + >=> + Value.sum >>> note (TypeMismatch "Value") where + decodeAsset :: Aeson -> Either JsonDecodeError Value decodeAsset = aesonObject \obj -> do quantity <- getField obj "quantity" >>= - BigInt.fromString >>> + BigNum.fromString >>> note (TypeMismatch "Expected string repr of BigInt") getField obj "unit" >>= case _ of "lovelace" -> pure $ Value.lovelaceValueOf quantity assetString -> do let { before: csStr, after: tnStr } = String.splitAt 56 assetString decodeAssetClass assetString csStr tnStr <#> \(cs /\ tn) -> - Value.mkValue mempty $ Value.mkSingletonNonAdaAsset cs tn quantity + Value.assetToValue (AssetClass cs tn) quantity - decodeOutputDatum :: Object Aeson -> Either JsonDecodeError OutputDatum + decodeOutputDatum + :: Object Aeson -> Either JsonDecodeError (Maybe OutputDatum) decodeOutputDatum obj = getFieldOptional' obj "inline_datum" >>= case _ of Just datum -> - note (TypeMismatch "Expected CBOR encoded inline datum") - (OutputDatum <$> deserializeData datum) + note (TypeMismatch "OutputDatum") + (Just <<< OutputDatum <$> decodeCbor datum) Nothing -> - maybe NoOutputDatum OutputDatumHash - <$> getFieldOptional' obj "data_hash" + pure $ join $ map OutputDatumHash <$> hush + (getFieldOptional' obj "data_hash") resolveBlockfrostTxOutput :: BlockfrostTransactionOutput @@ -1279,7 +1348,7 @@ instance DecodeAeson BlockfrostNativeScript where "sig" -> ScriptPubkey <$> ( getField obj "keyHash" >>= - (note (TypeMismatch "Ed25519KeyHash") <<< ed25519KeyHashFromBytes) + (note (TypeMismatch "Ed25519KeyHash") <<< decodeCbor) ) "before" -> TimelockExpiry <$> getField obj "slot" @@ -1324,7 +1393,7 @@ instance DecodeAeson BlockfrostCbor where -- BlockfrostDatum -------------------------------------------------------------------------------- -newtype BlockfrostDatum = BlockfrostDatum (Maybe Datum) +newtype BlockfrostDatum = BlockfrostDatum (Maybe PlutusData) derive instance Generic BlockfrostDatum _ derive instance Newtype BlockfrostDatum _ @@ -1332,7 +1401,7 @@ derive instance Newtype BlockfrostDatum _ instance Show BlockfrostDatum where show = genericShow -unwrapBlockfrostDatum :: BlockfrostDatum -> Maybe Datum +unwrapBlockfrostDatum :: BlockfrostDatum -> Maybe PlutusData unwrapBlockfrostDatum = unwrap instance DecodeAeson BlockfrostDatum where @@ -1340,7 +1409,7 @@ instance DecodeAeson BlockfrostDatum where | isNull aeson = pure $ BlockfrostDatum Nothing | otherwise = do cbor <- aesonObject (flip getFieldOptional "cbor") aeson - pure $ BlockfrostDatum $ deserializeData =<< cbor + pure $ BlockfrostDatum $ decodeCbor =<< cbor -------------------------------------------------------------------------------- -- BlockfrostMetadata @@ -1359,12 +1428,10 @@ instance DecodeAeson BlockfrostMetadata where decodeAeson = decodeAeson >=> \(metadatas :: Array { metadata :: CborBytes }) -> do metadatas' <- for metadatas \{ metadata } -> do - map (unwrap <<< convertGeneralTransactionMetadata) <$> flip note - (fromBytes metadata) $ - TypeMismatch "Hexadecimal encoded Metadata" - - pure $ BlockfrostMetadata $ GeneralTransactionMetadata $ Map.unions - metadatas' + decodeCbor metadata # note + (TypeMismatch "Hexadecimal encoded Metadata") + note (TypeMismatch "GeneralTransactionMetadata") $ + BlockfrostMetadata <$> GeneralTransactionMetadata.fold metadatas' unwrapBlockfrostMetadata :: BlockfrostMetadata -> GeneralTransactionMetadata unwrapBlockfrostMetadata (BlockfrostMetadata metadata) = metadata @@ -1373,7 +1440,7 @@ unwrapBlockfrostMetadata (BlockfrostMetadata metadata) = metadata -- BlockfrostCurrentEpoch -------------------------------------------------------------------------------- -newtype BlockfrostCurrentEpoch = BlockfrostCurrentEpoch BigInt +newtype BlockfrostCurrentEpoch = BlockfrostCurrentEpoch BigNum derive instance Generic BlockfrostCurrentEpoch _ derive instance Newtype BlockfrostCurrentEpoch _ @@ -1383,9 +1450,9 @@ instance Show BlockfrostCurrentEpoch where instance DecodeAeson BlockfrostCurrentEpoch where decodeAeson a = decodeAeson a <#> - \({ epoch } :: { epoch :: BigInt }) -> wrap epoch + \({ epoch } :: { epoch :: BigNum }) -> wrap epoch -unwrapBlockfrostCurrentEpoch :: BlockfrostCurrentEpoch -> BigInt +unwrapBlockfrostCurrentEpoch :: BlockfrostCurrentEpoch -> BigNum unwrapBlockfrostCurrentEpoch = unwrap data BlockfrostStakeCredential = BlockfrostStakeCredential NetworkId @@ -1402,11 +1469,15 @@ instance Show BlockfrostStakeCredential where blockfrostStakeCredentialToBech32 :: BlockfrostStakeCredential -> Bech32String blockfrostStakeCredentialToBech32 = case _ of BlockfrostStakeCredential networkId (Left stakePubKeyHash) -> - rewardAddressToBech32 $ stakePubKeyHashRewardAddress networkId - stakePubKeyHash + RewardAddress.toBech32 $ + { networkId + , stakeCredential: wrap $ PubKeyHashCredential $ unwrap stakePubKeyHash + } BlockfrostStakeCredential networkId (Right stakeValidatorHash) -> - rewardAddressToBech32 $ stakeValidatorHashRewardAddress networkId - stakeValidatorHash + RewardAddress.toBech32 $ + { networkId + , stakeCredential: wrap $ ScriptHashCredential $ unwrap stakeValidatorHash + } -------------------------------------------------------------------------------- -- BlockfrostProtocolParameters @@ -1437,31 +1508,33 @@ type BlockfrostProtocolParametersRaw = , "max_block_size" :: UInt , "max_tx_size" :: UInt , "max_block_header_size" :: UInt - , "key_deposit" :: Stringed BigInt - , "pool_deposit" :: Stringed BigInt - , "e_max" :: BigInt + , "key_deposit" :: Stringed BigNum + , "pool_deposit" :: Stringed BigNum + , "e_max" :: UInt , "n_opt" :: UInt , "a0" :: FiniteBigNumber , "rho" :: FiniteBigNumber , "tau" :: FiniteBigNumber , "protocol_major_ver" :: UInt , "protocol_minor_ver" :: UInt - , "min_pool_cost" :: Stringed BigInt + , "min_pool_cost" :: Stringed BigNum , "cost_models" :: { "PlutusV1" :: { | CostModelV1 } , "PlutusV2" :: { | CostModelV2 } + , "PlutusV3" :: CostModelV3 } , "price_mem" :: FiniteBigNumber , "price_step" :: FiniteBigNumber - , "max_tx_ex_mem" :: Stringed BigInt - , "max_tx_ex_steps" :: Stringed BigInt - , "max_block_ex_mem" :: Stringed BigInt - , "max_block_ex_steps" :: Stringed BigInt + , "max_tx_ex_mem" :: Stringed BigNum + , "max_tx_ex_steps" :: Stringed BigNum + , "max_block_ex_mem" :: Stringed BigNum + , "max_block_ex_steps" :: Stringed BigNum , "max_val_size" :: Stringed UInt , "collateral_percent" :: UInt , "max_collateral_inputs" :: UInt - , "coins_per_utxo_size" :: Maybe (Stringed BigInt) - , "coins_per_utxo_word" :: Maybe (Stringed BigInt) + , "coins_per_utxo_size" :: Maybe (Stringed BigNum) + , "gov_action_deposit" :: Stringed BigNum + , "drep_deposit" :: Stringed BigNum } toFraction' :: BigNumber -> String /\ String @@ -1481,11 +1554,11 @@ bigNumberToRational (FiniteBigNumber bn) = note (TypeMismatch "Rational") do bigNumberToPrice :: FiniteBigNumber - -> Either JsonDecodeError { numerator :: BigNum, denominator :: BigNum } + -> Either JsonDecodeError UnitInterval bigNumberToPrice (FiniteBigNumber bn) = note (TypeMismatch "Rational") do numerator <- BigNum.fromString numerator' denominator <- BigNum.fromString denominator' - pure { numerator, denominator } + pure $ UnitInterval { numerator, denominator } where (numerator' /\ denominator') = toFraction' bn @@ -1509,24 +1582,23 @@ instance DecodeAeson BlockfrostProtocolParameters where treasuryCut <- bigNumberToRational raw.tau memPrice <- bigNumberToPrice raw.price_mem stepPrice <- bigNumberToPrice raw.price_step - let prices = { memPrice, stepPrice } + let prices = ExUnitPrices { memPrice, stepPrice } - coinsPerUtxoUnit <- - maybe - (Left $ AtKey "coinsPerUtxoByte or coinsPerUtxoWord" $ MissingValue) - pure - $ (CoinsPerUtxoByte <<< Coin <<< unwrap <$> raw.coins_per_utxo_size) <|> - (CoinsPerUtxoWord <<< Coin <<< unwrap <$> raw.coins_per_utxo_word) + coinsPerUtxoByte <- + maybe (Left $ AtKey "coins_per_utxo_size" $ MissingValue) + pure $ (Coin <<< unwrap <$> raw.coins_per_utxo_size) + + plutusV3CostModel <- note (AtKey "PlutusV3" $ TypeMismatch "CostModel") $ + convertPlutusV3CostModel raw.cost_models."PlutusV3" pure $ BlockfrostProtocolParameters $ ProtocolParameters { protocolVersion: raw.protocol_major_ver /\ raw.protocol_minor_ver -- The following two parameters were removed from Babbage , decentralization: zero - , extraPraosEntropy: Nothing , maxBlockHeaderSize: raw.max_block_header_size , maxBlockBodySize: raw.max_block_size , maxTxSize: raw.max_tx_size - , txFeeFixed: raw.min_fee_b + , txFeeFixed: Coin $ BigNum.fromUInt raw.min_fee_b , txFeePerByte: raw.min_fee_a , stakeAddressDeposit: Coin $ unwrap raw.key_deposit , stakePoolDeposit: Coin $ unwrap raw.pool_deposit @@ -1536,23 +1608,28 @@ instance DecodeAeson BlockfrostProtocolParameters where , poolPledgeInfluence , monetaryExpansion , treasuryCut - , coinsPerUtxoUnit: coinsPerUtxoUnit - , costModels: Costmdls $ Map.fromFoldable + , coinsPerUtxoByte: coinsPerUtxoByte + , costModels: Map.fromFoldable [ PlutusV1 /\ convertPlutusV1CostModel raw.cost_models."PlutusV1" , PlutusV2 /\ convertPlutusV2CostModel raw.cost_models."PlutusV2" + , PlutusV3 /\ plutusV3CostModel ] , prices , maxTxExUnits: - { mem: unwrap raw.max_tx_ex_mem - , steps: unwrap raw.max_tx_ex_steps - } + ExUnits + { mem: unwrap raw.max_tx_ex_mem + , steps: unwrap raw.max_tx_ex_steps + } , maxBlockExUnits: - { mem: unwrap raw.max_block_ex_mem - , steps: unwrap raw.max_block_ex_steps - } + ExUnits + { mem: unwrap raw.max_block_ex_mem + , steps: unwrap raw.max_block_ex_steps + } , maxValueSize: unwrap raw.max_val_size , collateralPercent: raw.collateral_percent , maxCollateralInputs: raw.max_collateral_inputs + , govActionDeposit: Coin $ unwrap raw.gov_action_deposit + , drepDeposit: Coin $ unwrap raw.drep_deposit } -------------------------------------------------------------------------------- @@ -1571,7 +1648,7 @@ instance DecodeAeson BlockfrostRewards where withdrawable_amount_mb_str <- obj .:! "withdrawable_amount" withdrawable_amount <- for withdrawable_amount_mb_str \withdrawable_amount_str -> - note (TypeMismatch "BigInt") $ map Coin $ BigInt.fromString + note (TypeMismatch "BigNum") $ map Coin $ BigNum.fromString withdrawable_amount_str pure $ BlockfrostRewards { pool_id diff --git a/src/Internal/Service/Helpers.purs b/src/Internal/Service/Helpers.purs index 8e389cccba..a8fa09dab1 100644 --- a/src/Internal/Service/Helpers.purs +++ b/src/Internal/Service/Helpers.purs @@ -14,11 +14,13 @@ import Aeson , caseAesonObject , caseAesonString ) +import Cardano.AsCbor (decodeCbor) +import Cardano.Types.AssetName (AssetName, mkAssetName) +import Cardano.Types.ScriptHash (ScriptHash) import Control.Apply (lift2) -import Ctl.Internal.Cardano.Types.Value (CurrencySymbol, mkCurrencySymbol) -import Ctl.Internal.Types.ByteArray (hexToByteArray) -import Ctl.Internal.Types.TokenName (TokenName, mkTokenName) +import Data.ByteArray (hexToByteArray) import Data.Either (Either(Left), note) +import Data.Newtype (wrap) import Data.Tuple (Tuple(Tuple)) import Data.Tuple.Nested (type (/\)) import Foreign.Object (Object) @@ -48,14 +50,14 @@ decodeAssetClass :: String -> String -> String - -> Either JsonDecodeError (CurrencySymbol /\ TokenName) + -> Either JsonDecodeError (ScriptHash /\ AssetName) decodeAssetClass assetString csString tnString = lift2 Tuple ( note (assetStringTypeMismatch "CurrencySymbol" csString) - (mkCurrencySymbol =<< hexToByteArray csString) + (decodeCbor <<< wrap =<< hexToByteArray csString) ) - ( note (assetStringTypeMismatch "TokenName" tnString) - (mkTokenName =<< hexToByteArray tnString) + ( note (assetStringTypeMismatch "AssetName" tnString) + (mkAssetName =<< hexToByteArray tnString) ) where assetStringTypeMismatch :: String -> String -> JsonDecodeError diff --git a/src/Internal/Plutip/PortCheck.js b/src/Internal/Spawn.js similarity index 50% rename from src/Internal/Plutip/PortCheck.js rename to src/Internal/Spawn.js index dedb2434aa..cb5140b3af 100644 --- a/src/Internal/Plutip/PortCheck.js +++ b/src/Internal/Spawn.js @@ -1,5 +1,36 @@ +"use strict"; + +import stream from "node:stream"; import net from "net"; +export function clearLineHandler(readline) { + return () => { + readline.removeAllListeners("line"); + }; +} + +export const readableFromBuffer = buf => () => + stream.Readable.from(buf, { objectMode: false }); + +import fs from "fs"; + +export function _rmdirSync(path) { + return () => fs.rmSync(path, { recursive: true }); +} + +export function removeOnSignal({ signal, callback }) { + return () => { + process.removeListener(signal, callback); + }; +} + +export function onSignalImpl(signal) { + return callback => () => { + process.on(signal, callback); + return { signal, callback }; + }; +} + export function _isPortAvailable(port) { return () => new Promise((resolve, reject) => { diff --git a/src/Internal/Plutip/Spawn.purs b/src/Internal/Spawn.purs similarity index 53% rename from src/Internal/Plutip/Spawn.purs rename to src/Internal/Spawn.purs index c8f94c0059..7c9a08ef49 100644 --- a/src/Internal/Plutip/Spawn.purs +++ b/src/Internal/Spawn.purs @@ -1,43 +1,59 @@ -- | This module provides ability to spawn a program using `spawn` and wait -- | for some specific output that indicates that the program has started -- | successfully or failed, in which case an exception is thrown. -module Ctl.Internal.Plutip.Spawn +module Ctl.Internal.Spawn ( NewOutputAction(NoOp, Success, Cancel) , OnSignalRef , ManagedProcess(ManagedProcess) , spawn + , exec , stop , waitForStop , cleanupTmpDir , cleanupOnSigint , removeOnSignal + , waitForSignal + , isPortAvailable + , killProcessWithPort + , _rmdirSync + , FilePath ) where -import Prelude +import Contract.Prelude -import Control.Monad.Error.Class (throwError) -import Ctl.Internal.Plutip.Types (FilePath) +import Control.Monad.Error.Class (liftMaybe, throwError) +import Control.Promise (Promise, toAffE) import Data.Either (Either(Left)) import Data.Foldable (foldMap) import Data.Maybe (Maybe(Just, Nothing)) import Data.Posix.Signal (Signal(SIGINT)) import Data.Posix.Signal as Signal +import Data.Time.Duration (Milliseconds(Milliseconds)) +import Data.UInt (UInt) +import Data.UInt as UInt +import Debug (traceM) import Effect (Effect) import Effect.AVar (AVar) import Effect.AVar (empty, tryPut) as AVar import Effect.Aff (Aff, Canceler(Canceler), makeAff) +import Effect.Aff as Aff import Effect.Aff.AVar (isEmpty, read, status) as AVar +import Effect.Aff.Retry + ( RetryPolicy + , constantDelay + , limitRetriesByCumulativeDelay + , recovering + ) import Effect.Class (liftEffect) -import Effect.Exception (Error, error) +import Effect.Exception (Error, error, throw) +import Effect.Exception (message) as Error import Effect.Ref as Ref -import Node.ChildProcess - ( ChildProcess - , SpawnOptions - , kill - , stdout - ) +import Node.Buffer as Node.Buffer +import Node.ChildProcess (ChildProcess, SpawnOptions, kill, stderr, stdout) import Node.ChildProcess as ChildProcess +import Node.ChildProcess as Node.ChildProcess import Node.ReadLine (Interface, close, createInterface, setLineHandler) as RL +import Node.Stream as Node.Stream -- | Carry along an `AVar` which resolves when the process closes. -- | Necessary due to `child_process` having no way to query if a process has @@ -57,7 +73,7 @@ spawn :: String -> Array String -> SpawnOptions - -> Maybe (String -> NewOutputAction) + -> Maybe ({ output :: String, line :: String } -> Effect NewOutputAction) -> Aff ManagedProcess spawn cmd args opts mbFilter = makeAff (spawn' cmd args opts mbFilter) @@ -66,7 +82,7 @@ spawn' :: String -> Array String -> SpawnOptions - -> Maybe (String -> NewOutputAction) + -> Maybe ({ output :: String, line :: String } -> Effect NewOutputAction) -> (Either Error ManagedProcess -> Effect Unit) -> Effect Canceler spawn' cmd args opts mbFilter cont = do @@ -74,13 +90,19 @@ spawn' cmd args opts mbFilter cont = do let fullCmd = cmd <> foldMap (" " <> _) args closedAVar <- AVar.empty interface <- RL.createInterface (stdout child) mempty + stderrInterface <- RL.createInterface (stderr child) mempty + flip RL.setLineHandler stderrInterface \str -> do + traceM $ "stderr: " <> str outputRef <- Ref.new "" ChildProcess.onClose child \code -> do RL.close interface void $ AVar.tryPut code closedAVar output <- Ref.read outputRef - cont $ Left $ error $ - "Process " <> fullCmd <> " exited. Output:\n" <> output + cont $ Left $ error + $ "Process " + <> fullCmd + <> " exited. Output:\n" + <> output -- Ideally we call `RL.close interface` instead of detaching the listener -- via `clearLineHandler interface`, but it causes issues with the output @@ -93,7 +115,7 @@ spawn' cmd args opts mbFilter cont = do flip RL.setLineHandler interface \str -> do output <- Ref.modify (_ <> str <> "\n") outputRef - case filter output of + filter { output, line: str } >>= case _ of Success -> do clearLineHandler interface cont (pure mp) @@ -101,11 +123,52 @@ spawn' cmd args opts mbFilter cont = do kill SIGINT child clearLineHandler interface cont $ Left $ error - $ "Process cancelled because output received: " <> str + $ "Process cancelled because output received: " + <> str _ -> pure unit pure $ Canceler $ const $ liftEffect $ kill SIGINT child +exec + :: String + -> Aff + { channels :: + { stdout :: Node.Stream.Readable () + , stderr :: Node.Stream.Readable () + } + , process :: Node.ChildProcess.ChildProcess + } +exec cmd = Aff.makeAff \cont -> do + processRef <- Ref.new Nothing + isCanceledRef <- Ref.new false + let + isCanceled = Ref.read isCanceledRef + markCanceled = Ref.write true isCanceledRef + -- log $ show { exec: cmd } + process <- Node.ChildProcess.exec + cmd + Node.ChildProcess.defaultExecOptions + ( \{ error: err, stderr, stdout } -> isCanceled >>= flip unless do + process <- + liftMaybe (error "Couldn't find executed process" :: Error) + =<< Ref.read processRef + stderrStream <- readableFromBuffer stderr + stdoutStream <- readableFromBuffer stdout + let + result = + { channels: { stderr: stderrStream, stdout: stdoutStream } + , process + } + cont $ maybe (Right result) Left err + ) + Ref.write (Just process) processRef + pure $ Aff.Canceler \err -> liftEffect do + markCanceled + cont $ Left err + +foreign import readableFromBuffer + :: Node.Buffer.Buffer -> Effect (Node.Stream.Readable ()) + foreign import clearLineHandler :: RL.Interface -> Effect Unit stop :: ManagedProcess -> Aff Unit @@ -131,6 +194,18 @@ foreign import removeOnSignal :: OnSignalRef -> Effect Unit onSignal :: Signal -> Effect Unit -> Effect OnSignalRef onSignal sig = onSignalImpl (Signal.toString sig) +-- | Just as onSignal, but Aff. +waitForSignal :: Signal -> Aff Unit +waitForSignal signal = makeAff \cont -> do + isCanceledRef <- Ref.new false + onSignalRef <- onSignal signal + $ Ref.read isCanceledRef + >>= flip unless (cont $ Right unit) + pure $ Canceler \err -> liftEffect do + Ref.write true isCanceledRef + removeOnSignal onSignalRef + cont $ Left err + cleanupOnSigint :: FilePath -> FilePath -> Effect OnSignalRef cleanupOnSigint workingDir testClusterDir = do sig <- onSignal SIGINT do @@ -138,7 +213,35 @@ cleanupOnSigint workingDir testClusterDir = do _rmdirSync testClusterDir pure sig +killByPort :: UInt -> Effect Unit +killByPort port = + void $ Node.ChildProcess.exec + ("fuser -k " <> show (UInt.toInt port) <> "/tcp") + Node.ChildProcess.defaultExecOptions + (maybe (pure unit) (log <<< Error.message) <<< _.error) + +-- | Kill a process and wait for it to stop listening on a specific port. +killProcessWithPort :: UInt -> Aff Unit +killProcessWithPort port = do + liftEffect $ killByPort port + void $ recovering defaultRetryPolicy ([ \_ _ -> pure true ]) + \_ -> do + isAvailable <- isPortAvailable port + unless isAvailable do + liftEffect $ throw "retry" + +defaultRetryPolicy :: RetryPolicy +defaultRetryPolicy = limitRetriesByCumulativeDelay (Milliseconds 3000.00) $ + constantDelay (Milliseconds 100.0) + cleanupTmpDir :: ManagedProcess -> FilePath -> Effect Unit cleanupTmpDir (ManagedProcess _ child _) workingDir = do ChildProcess.onExit child \_ -> do _rmdirSync workingDir + +type FilePath = String + +foreign import _isPortAvailable :: Int -> Effect (Promise Boolean) + +isPortAvailable :: UInt -> Aff Boolean +isPortAvailable = toAffE <<< _isPortAvailable <<< UInt.toInt diff --git a/src/Internal/Test/ContractTest.purs b/src/Internal/Test/ContractTest.purs index 9e8c928137..581e41968e 100644 --- a/src/Internal/Test/ContractTest.purs +++ b/src/Internal/Test/ContractTest.purs @@ -1,17 +1,18 @@ module Ctl.Internal.Test.ContractTest ( ContractTest(ContractTest) - , withWallets - , noWallet , ContractTestHandler , ContractTestPlan(ContractTestPlan) , ContractTestPlanHandler + , noWallet + , sameWallets + , withWallets ) where import Prelude import Contract.Monad (Contract) -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Ctl.Internal.Test.UtxoDistribution (class UtxoDistribution) +import Mote.TestPlanM (TestPlanM) -- | Represents a `Contract` test suite that depend on *some* wallet -- | `UtxoDistribution`. @@ -43,6 +44,15 @@ withWallets distr tests = ContractTest \h -> h distr tests noWallet :: Contract Unit -> ContractTest noWallet = withWallets unit <<< const +-- | Store a wallet `UtxoDistribution` and a `TestPlanM` that depend on those wallets +sameWallets + :: forall (distr :: Type) (wallets :: Type) + . UtxoDistribution distr wallets + => distr + -> TestPlanM (wallets -> Contract Unit) Unit + -> ContractTestPlan +sameWallets distr tests = ContractTestPlan \h -> h distr tests + -- | A runner for a test suite that supports funds distribution. type ContractTestHandler :: Type -> Type -> Type -> Type type ContractTestHandler distr wallets r = diff --git a/src/Internal/Test/E2E/Feedback/Hooks.purs b/src/Internal/Test/E2E/Feedback/Hooks.purs index 01a3e38887..0bf64df34e 100644 --- a/src/Internal/Test/E2E/Feedback/Hooks.purs +++ b/src/Internal/Test/E2E/Feedback/Hooks.purs @@ -20,6 +20,7 @@ e2eFeedbackHooks = , onSuccess: Just $ pushBrowserEvent Success , onError: Just (pushBrowserEvent <<< Failure <<< show) , onSubmit: Nothing + , onClusterStartup: Nothing } addE2EFeedbackHooks :: Hooks -> Hooks diff --git a/src/Internal/Test/E2E/Feedback/Node.purs b/src/Internal/Test/E2E/Feedback/Node.purs index 6ee1692e00..e95eed1516 100644 --- a/src/Internal/Test/E2E/Feedback/Node.purs +++ b/src/Internal/Test/E2E/Feedback/Node.purs @@ -41,24 +41,31 @@ import Toppokki as Toppokki -- | React to events raised by the browser subscribeToBrowserEvents - :: Toppokki.Page + :: Boolean + -> Toppokki.Page -> (BrowserEvent -> Effect Unit) -> Aff Unit -subscribeToBrowserEvents page cont = do +subscribeToBrowserEvents passBrowserLogs page cont = do logs <- liftEffect $ Ref.new "" let addLogLine line = Ref.modify_ (flip append (line <> "\n")) logs liftEffect $ Toppokki.onConsole ( mkEffectFn1 \cm -> launchAff_ do - Toppokki.consoleMessageText cm >>= liftEffect <<< addLogLine + -- either log right now or safe for later (to log in case of an error) + if passBrowserLogs then + Toppokki.consoleMessageText cm >>= liftEffect <<< Console.log <<< + append "[chrome]: " + else + Toppokki.consoleMessageText cm >>= liftEffect <<< addLogLine ) page makeAff \f -> do liftEffect $ Toppokki.onPageError ( mkEffectFn1 ( \err -> do - allLogs <- Ref.read logs - Console.log allLogs + -- log everything if we haven't been passing the logs on the fly + when (not passBrowserLogs) do + Ref.read logs >>= Console.log f $ Left err ) ) diff --git a/src/Internal/Test/E2E/Options.purs b/src/Internal/Test/E2E/Options.purs index 3715589444..f2866c0853 100644 --- a/src/Internal/Test/E2E/Options.purs +++ b/src/Internal/Test/E2E/Options.purs @@ -3,6 +3,7 @@ module Ctl.Internal.Test.E2E.Options , BrowserOptions , ExtensionOptions , NoHeadless_ + , PassBrowserLogs_ , Tests_ , TestTimeout_ , CommonOptions_ @@ -86,7 +87,8 @@ import Type.Row (type (+)) -- | CLI options for E2E tests. type TestOptions = Record - ( NoHeadless_ + Tests_ + TestTimeout_ + ClusterPortsOptions_ + ( NoHeadless_ + Tests_ + PassBrowserLogs_ + TestTimeout_ + + ClusterPortsOptions_ + CommonOptions_ + () ) @@ -102,6 +104,8 @@ type ClusterPortsOptions = Record (ClusterPortsOptions_ ()) type NoHeadless_ (r :: Row Type) = (noHeadless :: Boolean | r) +type PassBrowserLogs_ (r :: Row Type) = (passBrowserLogs :: Boolean | r) + type Tests_ (r :: Row Type) = (tests :: Array E2ETest | r) type TestTimeout_ (r :: Row Type) = (testTimeout :: Maybe Int | r) @@ -292,6 +296,10 @@ testOptionsParser :: Parser TestOptions testOptionsParser = ado res <- browserOptionsParser tests <- testUrlsOptionParser + passBrowserLogs <- switch $ fold + [ long "pass-browser-logs" + , help "Pipe logs from the browser console to the test suite console" + ] noHeadless <- switch $ fold [ long "no-headless" , help "Show visible browser window" @@ -306,7 +314,7 @@ testOptionsParser = ado (clusterPorts :: ClusterPortsOptions) <- clusterPortsOptionsParser in build (merge clusterPorts <<< merge res) - { noHeadless, tests, testTimeout } + { noHeadless, tests, testTimeout, passBrowserLogs } testParser :: ReadM E2ETest testParser = eitherReader \str -> diff --git a/src/Internal/Test/E2E/Route.purs b/src/Internal/Test/E2E/Route.purs index 6bb113bf6d..605334baa9 100644 --- a/src/Internal/Test/E2E/Route.purs +++ b/src/Internal/Test/E2E/Route.purs @@ -9,13 +9,16 @@ module Ctl.Internal.Test.E2E.Route import Prelude +import Cardano.Types (NetworkId(TestnetId)) +import Cardano.Types.PrivateKey (PrivateKey) +import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Types.RawBytes (RawBytes(RawBytes)) import Contract.Config (ContractParams) import Contract.Monad (Contract, runContract) -import Contract.Test.Cip30Mock (WalletMock, withCip30Mock) +import Contract.Test.Cip30Mock (withCip30Mock) import Contract.Wallet ( PrivatePaymentKey(PrivatePaymentKey) , PrivateStakeKey(PrivateStakeKey) - , privateKeyFromBytes ) import Contract.Wallet.Key (privateKeysToKeyWallet) import Control.Alt ((<|>)) @@ -23,16 +26,13 @@ import Control.Monad.Error.Class (liftMaybe) import Ctl.Internal.Contract.QueryBackend (mkCtlBackendParams) import Ctl.Internal.Helpers (liftEither) import Ctl.Internal.QueryM (ClusterSetup) -import Ctl.Internal.Serialization.Address (NetworkId(MainnetId)) -import Ctl.Internal.Serialization.Types (PrivateKey) import Ctl.Internal.Test.E2E.Feedback.Browser (getClusterSetupRepeatedly) import Ctl.Internal.Test.E2E.Feedback.Hooks (addE2EFeedbackHooks) -import Ctl.Internal.Types.ByteArray (hexToByteArray) -import Ctl.Internal.Types.RawBytes (RawBytes(RawBytes)) -import Ctl.Internal.Wallet.Spec (WalletSpec(ConnectToEternl)) +import Ctl.Internal.Wallet.Spec (WalletSpec(ConnectToGenericCip30)) import Data.Array (last) import Data.Array as Array import Data.Bifunctor (lmap) +import Data.ByteArray (hexToByteArray) import Data.Either (Either(Left), note) import Data.Foldable (fold) import Data.Map (Map) @@ -88,7 +88,8 @@ parseRoute queryString = _ -> Left "Unable to decode URL" where mkPrivateKey' :: String -> Maybe PrivateKey - mkPrivateKey' str = hexToByteArray str >>= RawBytes >>> privateKeyFromBytes + mkPrivateKey' str = hexToByteArray str >>= RawBytes >>> + PrivateKey.fromRawBytes mkPrivateKey :: String -> Maybe PrivateKey mkPrivateKey str = @@ -103,7 +104,7 @@ parseRoute queryString = mkPrivateKey str <#> PrivateStakeKey addLinks - :: Map E2EConfigName (ContractParams /\ Maybe WalletMock) + :: Map E2EConfigName (ContractParams /\ Maybe String) -> Map E2ETestName (Contract Unit) -> Effect Unit addLinks configMaps testMaps = do @@ -135,7 +136,7 @@ addLinks configMaps testMaps = do -- | from the cluster should be used. If there's no local cluster, an error -- | will be thrown. route - :: Map E2EConfigName (ContractParams /\ Maybe WalletMock) + :: Map E2EConfigName (ContractParams /\ Maybe String) -> Map E2ETestName (Contract Unit) -> Effect Unit route configs tests = do @@ -161,7 +162,7 @@ route configs tests = do Nothing -> do clusterSetup@{ keys: { payment, stake } } <- getClusterSetupRepeatedly - when (config.networkId /= MainnetId) do + when (config.networkId /= TestnetId) do liftEffect $ throw wrongNetworkIdOnCluster pure $ { paymentKey: payment, stakeKey: stake } /\ Just clusterSetup let @@ -175,7 +176,7 @@ route configs tests = do do runContract configWithHooks $ withCip30Mock - (privateKeysToKeyWallet paymentKey stakeKey) + (privateKeysToKeyWallet paymentKey stakeKey Nothing) -- FIXME mock test where @@ -183,7 +184,7 @@ route configs tests = do delayIfEternl :: ContractParams -> Aff Unit delayIfEternl config = case config.walletSpec of - Just ConnectToEternl -> + Just (ConnectToGenericCip30 "eternl" _) -> delay $ wrap 3000.0 _ -> pure unit @@ -200,8 +201,9 @@ route configs tests = do wrongNetworkIdOnCluster :: String wrongNetworkIdOnCluster = "No payment keys were specified, which implies they should be retrieved " - <> "from a local cluster, however, network ID was set to TestnetId, " - <> "which is incompatible with Plutip, that always uses MainnetId." + <> "from a local cluster, however, network ID was set to MainnetId, " + <> + "which is incompatible with cardano-testnet, that always uses TestnetId." -- Override config values with parameters from cluster setup setClusterOptions diff --git a/src/Internal/Test/E2E/Runner.purs b/src/Internal/Test/E2E/Runner.purs index 26a659b9cd..ab4be97eeb 100644 --- a/src/Internal/Test/E2E/Runner.purs +++ b/src/Internal/Test/E2E/Runner.purs @@ -10,16 +10,20 @@ import Prelude import Affjax (defaultRequest) as Affjax import Affjax (printError) import Affjax.ResponseFormat as Affjax.ResponseFormat +import Cardano.Types.BigNum as BigNum +import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Wallet.Key + ( PrivateStakeKey + , getPrivatePaymentKey + , getPrivateStakeKey + ) import Control.Alt ((<|>)) import Control.Monad.Error.Class (liftMaybe) import Control.Promise (Promise, toAffE) import Ctl.Internal.Affjax (request) as Affjax import Ctl.Internal.Contract.Hooks (emptyHooks) import Ctl.Internal.Contract.QueryBackend (QueryBackend(CtlBackend)) -import Ctl.Internal.Deserialization.Keys (privateKeyFromBytes) -import Ctl.Internal.Helpers (liftedM, (<>)) -import Ctl.Internal.Plutip.Server (withPlutipContractEnv) -import Ctl.Internal.Plutip.Types (PlutipConfig) +import Ctl.Internal.Helpers (liftedM, unsafeFromJust, (<>)) import Ctl.Internal.QueryM (ClusterSetup) import Ctl.Internal.Test.E2E.Browser (withBrowser) import Ctl.Internal.Test.E2E.Feedback @@ -44,7 +48,7 @@ import Ctl.Internal.Test.E2E.Types , ChromeUserDataDir , E2ETest , E2ETestRuntime - , E2EWallet(NoWallet, PlutipCluster, WalletExtension) + , E2EWallet(NoWallet, LocalTestnet, WalletExtension) , ExtensionParams , Extensions , RunningE2ETest @@ -71,16 +75,12 @@ import Ctl.Internal.Test.E2E.Wallets , namiConfirmAccess , namiSign ) -import Ctl.Internal.Test.TestPlanM (TestPlanM, interpretWithConfig) import Ctl.Internal.Test.UtxoDistribution (withStakeKey) -import Ctl.Internal.Types.RawBytes (hexToRawBytes) -import Ctl.Internal.Wallet.Key - ( PrivateStakeKey - , keyWalletPrivatePaymentKey - , keyWalletPrivateStakeKey - ) +import Ctl.Internal.Testnet.Contract (withTestnetContractEnv) +import Ctl.Internal.Testnet.Types (Era(Babbage), TestnetConfig) import Data.Array (catMaybes, mapMaybe, nub) import Data.Array as Array +import Data.ByteArray (hexToByteArray) import Data.Either (Either(Left, Right), isLeft) import Data.Foldable (fold) import Data.HTTP.Method (Method(GET)) @@ -113,8 +113,8 @@ import Effect.Class (liftEffect) import Effect.Console (log) import Effect.Exception (Error, error, throw) import Effect.Ref as Ref -import JS.BigInt as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM, interpretWithConfig) import Node.Buffer (fromArrayBuffer) import Node.ChildProcess ( Exit(Normally, BySignal) @@ -147,6 +147,8 @@ runE2ECommand = case _ of runtime <- readTestRuntime testOptions tests <- liftEffect $ readTests testOptions.tests noHeadless <- liftEffect $ readNoHeadless testOptions.noHeadless + passBrowserLogs <- liftEffect $ readPassBrowserLogs + testOptions.passBrowserLogs testTimeout <- liftEffect $ readTestTimeout testOptions.testTimeout portOptions <- liftEffect $ readPorts testOptions extraBrowserArgs <- liftEffect $ readExtraArgs testOptions.extraBrowserArgs @@ -156,6 +158,7 @@ runE2ECommand = case _ of , testTimeout = testTimeout , tests = tests , extraBrowserArgs = extraBrowserArgs + , passBrowserLogs = passBrowserLogs } runE2ETests testOptions' runtime RunBrowser browserOptions -> do @@ -192,11 +195,9 @@ runE2ETests opts rt = do ) (testPlan opts rt) -buildPlutipConfig :: TestOptions -> PlutipConfig -buildPlutipConfig options = - { host: "127.0.0.1" - , port: fromMaybe (UInt.fromInt defaultPorts.plutip) options.plutipPort - , logLevel: Trace +buildLocalTestnetConfig :: TestOptions -> TestnetConfig +buildLocalTestnetConfig options = + { logLevel: Trace , ogmiosConfig: { port: fromMaybe (UInt.fromInt defaultPorts.ogmios) options.ogmiosPort , host: "127.0.0.1" @@ -213,10 +214,10 @@ buildPlutipConfig options = , customLogger: Just \_ _ -> pure unit , hooks: emptyHooks , clusterConfig: - { slotLength: Seconds 0.05 + { testnetMagic: 2 + , era: Babbage + , slotLength: Seconds 0.05 , epochSize: Nothing - , maxTxSize: Nothing - , raiseExUnitsToMax: false } } @@ -224,8 +225,10 @@ buildPlutipConfig options = -- | fund it manually to get a usable base address. privateStakeKey :: PrivateStakeKey privateStakeKey = wrap $ unsafePartial $ fromJust - $ privateKeyFromBytes =<< hexToRawBytes - "633b1c4c4a075a538d37e062c1ed0706d3f0a94b013708e8f5ab0a0ca1df163d" + $ PrivateKey.fromRawBytes =<< map wrap + ( hexToByteArray + "633b1c4c4a075a538d37e062c1ed0706d3f0a94b013708e8f5ab0a0ca1df163d" + ) -- | Constructs a test plan given an array of tests. testPlan @@ -240,28 +243,30 @@ testPlan opts@{ tests } rt@{ wallets } = withBrowser opts.noHeadless opts.extraBrowserArgs rt Nothing \browser -> do withE2ETest true (wrap url) browser \{ page } -> do - subscribeToTestStatusUpdates page - -- Plutip in E2E tests - { url, wallet: PlutipCluster } -> do + subscribeToTestStatusUpdates opts.passBrowserLogs page + -- cardano-testnet in E2E tests + { url, wallet: LocalTestnet } -> do let + amount = unsafeFromJust "testPlan: integer overflow" $ + BigNum.fromString "5000000000" -- 5k ADA distr = withStakeKey privateStakeKey - [ BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 + [ amount + , amount + , amount + , amount + , amount ] - -- TODO: don't connect to services in ContractEnv, just start them - -- https://github.com/Plutonomicon/cardano-transaction-lib/issues/1197 - liftAff $ withPlutipContractEnv (buildPlutipConfig opts) distr + liftAff $ withTestnetContractEnv (buildLocalTestnetConfig opts) distr \env wallet -> do + kwPaymentKey <- liftAff $ getPrivatePaymentKey wallet + kwMStakeKey <- liftAff $ getPrivateStakeKey wallet (clusterSetup :: ClusterSetup) <- case env.backend of CtlBackend backend _ -> pure { ogmiosConfig: backend.ogmios.config , kupoConfig: backend.kupoConfig , keys: - { payment: keyWalletPrivatePaymentKey wallet - , stake: keyWalletPrivateStakeKey wallet + { payment: kwPaymentKey + , stake: kwMStakeKey } } _ -> liftEffect $ throw "Unsupported backend" @@ -269,7 +274,7 @@ testPlan opts@{ tests } rt@{ wallets } = \browser -> do withE2ETest true (wrap url) browser \{ page } -> do setClusterSetup page clusterSetup - subscribeToTestStatusUpdates page + subscribeToTestStatusUpdates opts.passBrowserLogs page -- E2E tests with a light wallet { url, wallet: WalletExtension wallet } -> do { password, extensionId } <- liftEffect @@ -309,7 +314,7 @@ testPlan opts@{ tests } rt@{ wallets } = res <- try aff when (isLeft res) $ liftEffect $ k res map fiberCanceler $ launchAff $ (try >=> k >>> liftEffect) $ - subscribeToBrowserEvents page + subscribeToBrowserEvents opts.passBrowserLogs page case _ of ConfirmAccess -> rethrow someWallet.confirmAccess Sign -> rethrow someWallet.sign @@ -319,9 +324,9 @@ testPlan opts@{ tests } rt@{ wallets } = Failure _ -> pure unit where -- A specialized version that does not deal with wallet automation - subscribeToTestStatusUpdates :: Toppokki.Page -> Aff Unit - subscribeToTestStatusUpdates page = - subscribeToBrowserEvents page + subscribeToTestStatusUpdates :: Boolean -> Toppokki.Page -> Aff Unit + subscribeToTestStatusUpdates passBrowserLogs page = + subscribeToBrowserEvents passBrowserLogs page case _ of Success -> pure unit Failure err -> throw err @@ -360,6 +365,7 @@ readTestRuntime testOptions = do <<< delete (Proxy :: Proxy "plutipPort") <<< delete (Proxy :: Proxy "ogmiosPort") <<< delete (Proxy :: Proxy "kupoPort") + <<< delete (Proxy :: Proxy "passBrowserLogs") ) readBrowserRuntime Nothing $ removeUnneeded testOptions @@ -589,6 +595,16 @@ readNoHeadless false = do liftMaybe (error $ "Failed to read E2E_NO_HEADLESS: " <> str) $ readBoolean str +readPassBrowserLogs :: Boolean -> Effect Boolean +readPassBrowserLogs true = pure true +readPassBrowserLogs false = do + mbStr <- lookupEnv "E2E_PASS_BROWSER_LOGS" + case mbStr of + Nothing -> pure false + Just str -> do + liftMaybe (error $ "Failed to read E2E_PASS_BROWSER_LOGS: " <> str) $ + readBoolean str + readBoolean :: String -> Maybe Boolean readBoolean = case _ of "true" -> Just true diff --git a/src/Internal/Test/E2E/Types.purs b/src/Internal/Test/E2E/Types.purs index bbb3594acc..f4b0c82825 100644 --- a/src/Internal/Test/E2E/Types.purs +++ b/src/Internal/Test/E2E/Types.purs @@ -20,7 +20,7 @@ module Ctl.Internal.Test.E2E.Types , mkE2ETest , RunningE2ETest , SomeWallet - , E2EWallet(NoWallet, PlutipCluster, WalletExtension) + , E2EWallet(NoWallet, LocalTestnet, WalletExtension) , getE2EWalletExtension ) where @@ -120,7 +120,7 @@ type SettingsRuntime = , settingsArchive :: SettingsArchive } -data E2EWallet = NoWallet | PlutipCluster | WalletExtension WalletExt +data E2EWallet = NoWallet | LocalTestnet | WalletExtension WalletExt derive instance Generic E2EWallet _ derive instance Eq E2EWallet @@ -149,7 +149,7 @@ mkE2ETest str = <|> (tryWalletPrefix "lode" <#> mkTestEntry (WalletExtension LodeExt)) <|> (tryWalletPrefix "nami" <#> mkTestEntry (WalletExtension NamiExt)) <|> (tryWalletPrefix "lace" <#> mkTestEntry (WalletExtension LaceExt)) - <|> (tryWalletPrefix "plutip" <#> mkTestEntry PlutipCluster) + <|> (tryWalletPrefix "plutip" <#> mkTestEntry LocalTestnet) <|> (pure $ mkTestEntry NoWallet str) where tryWalletPrefix :: String -> Maybe String diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index 3716fabc31..5a9cecba9a 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -4,11 +4,15 @@ module Ctl.Internal.Test.KeyDir import Prelude -import Contract.Address - ( addressToBech32 - ) +import Cardano.Types (BigNum, Value, _amount) +import Cardano.Types.Address (toBech32) as Address +import Cardano.Types.BigNum as BigNum +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Types.PublicKey as PublicKey +import Cardano.Types.Value as Value +import Cardano.Wallet.Key (KeyWallet) import Contract.Config (ContractParams) -import Contract.Hashing (publicKeyHash) import Contract.Log (logError', logTrace') import Contract.Monad ( Contract @@ -27,7 +31,6 @@ import Contract.Transaction , submitTxFromConstraints ) import Contract.Utxos (utxosAt) -import Contract.Value (valueToCoin') import Contract.Wallet ( getWalletAddresses , getWalletBalance @@ -36,9 +39,8 @@ import Contract.Wallet , withKeyWallet ) import Contract.Wallet.Key - ( keyWalletPrivatePaymentKey - , keyWalletPrivateStakeKey - , publicKeyFromPrivateKey + ( getPrivatePaymentKey + , getPrivateStakeKey ) import Contract.Wallet.KeyFile ( privatePaymentKeyFromTextEnvelope @@ -50,14 +52,9 @@ import Control.Monad.Error.Class (liftMaybe) import Control.Monad.Except (throwError) import Control.Monad.Reader (asks, local) import Control.Parallel (parTraverse, parTraverse_) -import Ctl.Internal.Deserialization.Keys (freshPrivateKey) -import Ctl.Internal.Helpers (logWithLevel) -import Ctl.Internal.Plutus.Types.Transaction (_amount, _output) -import Ctl.Internal.Plutus.Types.Value (Value, lovelaceValueOf) +import Ctl.Internal.Helpers (logWithLevel, unsafeFromJust) import Ctl.Internal.ProcessConstraints (mkUnbalancedTxImpl) -import Ctl.Internal.Serialization.Address (addressBech32) import Ctl.Internal.Test.ContractTest (ContractTest(ContractTest)) -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Ctl.Internal.Test.UtxoDistribution ( UtxoAmount , decodeWallets @@ -71,10 +68,8 @@ import Ctl.Internal.Types.TxConstraints , mustBeSignedBy , mustPayToPubKeyAddress , mustSpendPubKeyOutput - , singleton ) -import Ctl.Internal.Wallet.Key (KeyWallet) -import Data.Array (catMaybes) +import Data.Array (catMaybes, singleton) import Data.Array as Array import Data.Either (Either(Right, Left), hush) import Data.Foldable (fold, sum) @@ -82,7 +77,7 @@ import Data.Lens ((^.)) import Data.List (List(Cons, Nil)) import Data.List as List import Data.Map as Map -import Data.Maybe (Maybe(Just, Nothing), isNothing, maybe) +import Data.Maybe (Maybe(Nothing, Just), isNothing, maybe) import Data.Newtype (over, unwrap, wrap) import Data.String (joinWith) import Data.String.Utils (startsWith) as String @@ -105,11 +100,13 @@ import Effect.Ref as Ref import JS.BigInt (BigInt) import JS.BigInt as BigInt import Mote.Monad (mapTest) +import Mote.TestPlanM (TestPlanM) import Node.Encoding (Encoding(UTF8)) import Node.FS.Aff (mkdir, readTextFile, readdir, writeTextFile) import Node.FS.Sync (exists) import Node.Path (FilePath) import Node.Path (concat) as Path +import Partial.Unsafe (unsafePartial) import Type.Prelude (Proxy(Proxy)) -- | Runs `ContractTest`s given a `ContractParams` value. @@ -140,9 +137,8 @@ runContractTestsWithKeyDir params backup = do ( error "Impossible happened: unable to get own address" ) =<< (getWalletAddresses <#> Array.head) - addressStr <- addressToBech32 address - balance <- getWalletBalance <#> fold - pure $ addressStr /\ balance + balance <- unsafePartial $ getWalletBalance <#> fold + pure $ Address.toBech32 address /\ balance let distrArray :: Array (Array UtxoAmount) distrArray = encodeDistribution distr @@ -152,7 +148,7 @@ runContractTestsWithKeyDir params backup = do -- because it is expected that test wallets have thousands of ADA. let distrTotalAmount :: BigInt - distrTotalAmount = sum $ map sum distrArray + distrTotalAmount = sum $ map (sum <<< map BigNum.toBigInt) distrArray minAdaRoughEstimation :: BigInt minAdaRoughEstimation = BigInt.fromInt 1_000_000 @@ -165,21 +161,25 @@ runContractTestsWithKeyDir params backup = do (sum (Array.length <$> distrArray)) -- check if we have enough funds - when (valueToCoin' balance <= distrTotalAmount + feesToDistribute) do - liftEffect $ throw $ - "The test engine cannot satisfy the requested ADA distribution " - <> "because there are not enough funds left. \n\n" - <> "Total required value is: " - <> showLovelace distrTotalAmount - <> " (estimated)\n" - <> "Total available value is: " - <> BigInt.toString (valueToCoin' balance) - <> "\nThe test suite is using this address: " - <> addressStr - <> "\nFund it to continue." + when + ( BigNum.toBigInt (unwrap $ Value.getCoin balance) <= distrTotalAmount + + feesToDistribute + ) + do + liftEffect $ throw $ + "The test engine cannot satisfy the requested ADA distribution " + <> "because there are not enough funds left. \n\n" + <> "Total required value is: " + <> showLovelace distrTotalAmount + <> " (estimated)\n" + <> "Total available value is: " + <> BigNum.toString (unwrap $ Value.getCoin balance) + <> "\nThe test suite is using this address: " + <> addressStr + <> "\nFund it to continue." -- generate wallets - privateKeys <- liftEffect $ for distrArray \_ -> freshPrivateKey + privateKeys <- liftEffect $ for distrArray \_ -> PrivateKey.generate wallets <- liftMaybe ( error @@ -233,8 +233,8 @@ markAsInactive :: FilePath -> Array KeyWallet -> Contract Unit markAsInactive backup wallets = do flip parTraverse_ wallets \wallet -> do networkId <- asks _.networkId + address <- liftAff $ Address.toBech32 <$> (unwrap wallet).address networkId let - address = addressBech32 $ (unwrap wallet).address networkId inactiveFlagFile = Path.concat [ backup, address, "inactive" ] liftAff $ writeTextFile UTF8 inactiveFlagFile $ "This address was marked as inactive. " @@ -276,19 +276,19 @@ restoreWallets backup = do ) $ privateStakeKeyFromTextEnvelope =<< decodeTextEnvelope stakeKeyEnvelope - pure $ Just $ privateKeysToKeyWallet paymentKey mbStakeKey + pure $ Just $ privateKeysToKeyWallet paymentKey mbStakeKey Nothing -- | Save wallets to files in the backup directory for private keys backupWallets :: FilePath -> ContractEnv -> Array KeyWallet -> Aff Unit backupWallets backup env walletsArray = liftAff $ flip parTraverse_ walletsArray \wallet -> do + payment <- getPrivatePaymentKey wallet + mbStake <- getPrivateStakeKey wallet + address <- liftAff $ Address.toBech32 <$> (unwrap wallet).address + env.networkId let - address = addressBech32 $ (unwrap wallet).address env.networkId - payment = keyWalletPrivatePaymentKey wallet - mbStake = keyWalletPrivateStakeKey wallet folder = Path.concat [ backup, address ] - mkdir folder privatePaymentKeyToFile (Path.concat [ folder, "payment_signing_key" ]) payment @@ -297,21 +297,25 @@ backupWallets backup env walletsArray = -- | Create a transaction that builds a specific UTxO distribution on the wallets. fundWallets - :: ContractEnv -> Array KeyWallet -> Array (Array UtxoAmount) -> Aff BigInt + :: ContractEnv -> Array KeyWallet -> Array (Array UtxoAmount) -> Aff BigNum fundWallets env walletsArray distrArray = runContractInEnv env $ noLogs do logTrace' "Funding wallets" - let - constraints = flip foldMap (Array.zip walletsArray distrArray) - \(wallet /\ walletDistr) -> flip foldMap walletDistr - \value -> mustPayToKeyWallet wallet $ lovelaceValueOf value - + constraints <- liftAff $ flip foldMap (Array.zip walletsArray distrArray) + \(wallet /\ walletDistr) -> flip foldMap walletDistr + \value -> mustPayToKeyWallet wallet $ + Value.mkValue + (wrap value) + MultiAsset.empty txHash <- submitTxFromConstraints mempty constraints awaitTxConfirmed txHash - let fundTotal = Array.foldl (+) zero $ join distrArray + let + fundTotal = + Array.foldl (\x y -> unsafeFromJust "fundWallets" $ BigNum.add x y) + BigNum.zero $ join distrArray -- Use log so we can see, regardless of suppression info $ joinWith " " [ "Sent" - , showLovelace fundTotal + , showLovelace $ BigNum.toBigInt fundTotal , "to test wallets" ] pure fundTotal @@ -354,7 +358,7 @@ returnFunds :: FilePath -> ContractEnv -> Array KeyWallet - -> Maybe BigInt + -> Maybe BigNum -> Boolean -> Aff Unit returnFunds backup env allWalletsArray mbFundTotal hasRun = @@ -387,8 +391,9 @@ returnFunds backup env allWalletsArray mbFundTotal hasRun = <> foldMap mustBeSignedBy pkhs lookups = unspentOutputs utxos - unbalancedTx <- liftedE $ mkUnbalancedTxImpl lookups constraints - balancedTx <- balanceTx unbalancedTx + unbalancedTx /\ usedUtxos <- liftedE $ mkUnbalancedTxImpl lookups + constraints + balancedTx <- balanceTx unbalancedTx usedUtxos mempty balancedSignedTx <- Array.foldM (\tx wallet -> withKeyWallet wallet $ signTransaction tx) (wrap $ unwrap balancedTx) @@ -399,7 +404,9 @@ returnFunds backup env allWalletsArray mbFundTotal hasRun = let (refundTotal :: BigInt) = Array.foldl - (\acc txorf -> acc + valueToCoin' (txorf ^. _output ^. _amount)) + ( \acc txorf -> acc + BigNum.toBigInt + (unwrap $ Value.getCoin (txorf ^. _amount)) + ) zero (Array.fromFoldable $ Map.values utxos) @@ -409,13 +416,13 @@ returnFunds backup env allWalletsArray mbFundTotal hasRun = ] <> maybe [] ( \fundTotal -> [ "of" - , showLovelace fundTotal + , showLovelace $ BigNum.toBigInt fundTotal , "from test wallets" ] ) mbFundTotal for_ mbFundTotal \fundTotal -> do - when (fundTotal == refundTotal && hasRun) do + when (BigNum.toBigInt fundTotal == refundTotal && hasRun) do info $ "The test below didn't spend any ADA. Perhaps it does not " <> "need any funds to succeed. Consider using `noWallet` to " <> "skip funds distribution step" @@ -435,18 +442,20 @@ mustPayToKeyWallet :: forall (i :: Type) (o :: Type) . KeyWallet -> Value - -> TxConstraints -mustPayToKeyWallet wallet value = + -> Aff TxConstraints +mustPayToKeyWallet wallet value = do + kwPaymentKey <- getPrivatePaymentKey wallet + kwMStakeKey <- getPrivateStakeKey wallet + let - convert = publicKeyHash <<< publicKeyFromPrivateKey - payment = over wrap convert $ keyWalletPrivatePaymentKey wallet - mbStake = over wrap convert <$> keyWalletPrivateStakeKey wallet - in - maybe - -- We don't use `mustPayToPubKey payment` to avoid the compile-time - -- warning that is tied to it (it should not be propagated to - -- `runContractTestWithKeyDir`) - (singleton <<< MustPayToPubKeyAddress payment Nothing Nothing Nothing) - (mustPayToPubKeyAddress payment) - mbStake - value + convert = PublicKey.hash <<< PrivateKey.toPublicKey + payment = over wrap convert $ kwPaymentKey + mbStake = over wrap convert <$> kwMStakeKey + pure $ maybe + -- We don't use `mustPayToPubKey payment` to avoid the compile-time + -- warning that is tied to it (it should not be propagated to + -- `runContractTestWithKeyDir`) + (singleton <<< MustPayToPubKeyAddress payment Nothing Nothing Nothing) + (mustPayToPubKeyAddress payment) + mbStake + value diff --git a/src/Internal/Test/TestPlanM.purs b/src/Internal/Test/TestPlanM.purs deleted file mode 100644 index db4a50f5db..0000000000 --- a/src/Internal/Test/TestPlanM.purs +++ /dev/null @@ -1,56 +0,0 @@ -module Ctl.Internal.Test.TestPlanM - ( TestPlanM - , interpret - , interpretWithConfig - ) where - -import Prelude - -import Ctl.Internal.Test.ConsoleReporter (consoleReporter) -import Data.Foldable (sequence_) -import Data.Maybe (Maybe(Just), maybe) -import Data.Newtype (wrap) -import Effect.Aff (Aff, bracket) -import Mote (MoteT, Plan, foldPlan, planT) -import Mote.Entry (Bracket, unBracket) -import Test.Spec (SpecT, afterAll, beforeAll, beforeWith, describe, it, pending) -import Test.Spec.Runner (defaultConfig, runSpecT) -import Test.Spec.Runner as SpecRunner - -type TestPlanM :: Type -> Type -> Type -type TestPlanM test a = MoteT Aff test Aff a - -type AffSpec :: Type -> Type -type AffSpec a = SpecT Aff Unit Aff a - --- | We use `mote` here so that we can use effects to build up a test tree, which --- | is then interpreted here in a pure context, mainly due to some painful types --- | in Test.Spec which prohibit effects. --- | https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/doc/plutip-testing.md#testing-with-mote -interpret :: TestPlanM (Aff Unit) Unit -> Aff Unit -interpret = interpretWithConfig defaultConfig { timeout = Just (wrap 50000.0) } - -interpretWithConfig - :: SpecRunner.Config -> TestPlanM (Aff Unit) Unit -> Aff Unit -interpretWithConfig config spif = do - plan <- planT spif - void $ join $ runSpecT config [ consoleReporter ] $ planToSpec plan - -planToSpec :: Plan Aff (Aff Unit) -> AffSpec Unit -planToSpec = - foldPlan - (\x -> it x.label $ runBracket x.value x.bracket) - pending - (\x -> describe x.label $ runBracketSpec (planToSpec x.value) x.bracket) - sequence_ - where - runBracketSpec :: AffSpec Unit -> Maybe (Bracket Aff) -> AffSpec Unit - runBracketSpec action = maybe action - $ unBracket \before after -> do - -- Use beforeWith to ignore the existential argument and supply the expected unit - beforeAll before - (afterAll after (beforeWith (const $ pure unit) action)) - - runBracket :: Aff Unit -> Maybe (Bracket Aff) -> Aff Unit - runBracket action = maybe action - $ unBracket \before after -> bracket before after (const action) diff --git a/src/Internal/Test/UtxoDistribution.purs b/src/Internal/Test/UtxoDistribution.purs index d4e3476b44..932844cd06 100644 --- a/src/Internal/Test/UtxoDistribution.purs +++ b/src/Internal/Test/UtxoDistribution.purs @@ -9,23 +9,36 @@ module Ctl.Internal.Test.UtxoDistribution , InitialUTxOs , InitialUTxODistribution , InitialUTxOsWithStakeKey(InitialUTxOsWithStakeKey) + , TestWalletSpec(TestWalletSpec) , UtxoAmount ) where import Prelude -import Contract.Address - ( PaymentPubKeyHash +import Cardano.Types + ( BigNum + , Credential(PubKeyHashCredential) + , PaymentCredential(PaymentCredential) + , PaymentPubKeyHash , StakePubKeyHash - , getNetworkId - , payPubKeyHashEnterpriseAddress + , TransactionOutput(TransactionOutput) ) -import Contract.Monad (Contract, liftContractM, liftedM) +import Cardano.Types.Address (Address(EnterpriseAddress)) +import Cardano.Types.PrivateKey (PrivateKey) +import Cardano.Types.UtxoMap (UtxoMap) +import Cardano.Wallet.Key + ( KeyWallet + , PrivateDrepKey + , PrivatePaymentKey(PrivatePaymentKey) + , PrivateStakeKey + , privateKeysToKeyWallet + ) +import Contract.Address (getNetworkId) +import Contract.Monad (Contract, liftedM) import Contract.Prelude (foldM, foldMap, null) import Contract.ScriptLookups as Lookups import Contract.Transaction - ( TransactionOutputWithRefScript(TransactionOutputWithRefScript) - , awaitTxConfirmed + ( awaitTxConfirmed , balanceTx , signTransaction , submit @@ -43,31 +56,24 @@ import Contract.Wallet import Control.Alternative (guard) import Control.Monad.Reader (asks) import Control.Monad.State.Trans (StateT(StateT), runStateT) -import Ctl.Internal.Plutus.Types.Transaction (UtxoMap) -import Ctl.Internal.Serialization.Types (PrivateKey) -import Ctl.Internal.Wallet.Key - ( KeyWallet - , PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey - , privateKeysToKeyWallet - ) import Data.Array (head) import Data.Array as Array import Data.FoldableWithIndex (foldMapWithIndex) +import Data.Generic.Rep (class Generic) import Data.List (List, (:)) import Data.Map as Map import Data.Maybe (Maybe(Nothing, Just)) -import Data.Newtype (unwrap, wrap) +import Data.Newtype (class Newtype, unwrap, wrap) +import Data.Show.Generic (genericShow) import Data.Traversable (traverse) import Data.Tuple (Tuple) import Data.Tuple.Nested (type (/\), (/\)) import Effect.Class (liftEffect) import Effect.Ref as Ref -import JS.BigInt (BigInt) import Type.Prelude (Proxy(Proxy)) -- | UTxO amount in Lovelaces -type UtxoAmount = BigInt +type UtxoAmount = BigNum -- | A list of UTxOs for a single wallet type InitialUTxOs = Array UtxoAmount @@ -77,6 +83,18 @@ type InitialUTxOs = Array UtxoAmount data InitialUTxOsWithStakeKey = InitialUTxOsWithStakeKey PrivateStakeKey InitialUTxOs +newtype TestWalletSpec = TestWalletSpec + { utxos :: Array UtxoAmount + , stakeKey :: Maybe PrivateStakeKey + , drepKey :: Maybe PrivateDrepKey + } + +derive instance Generic TestWalletSpec _ +derive instance Newtype TestWalletSpec _ + +instance Show TestWalletSpec where + show = genericShow + -- | A spec for distribution of UTxOs between wallets. type InitialUTxODistribution = Array InitialUTxOs @@ -104,7 +122,7 @@ instance UtxoDistribution InitialUTxOs KeyWallet where decodeWallets d p = decodeWalletsDefault d p decodeWallets' _ pks = Array.uncons pks <#> \{ head: key, tail } -> - (privateKeysToKeyWallet (PrivatePaymentKey key) Nothing) /\ tail + (privateKeysToKeyWallet (PrivatePaymentKey key) Nothing Nothing) /\ tail keyWallets _ wallet = [ wallet ] instance UtxoDistribution InitialUTxOsWithStakeKey KeyWallet where @@ -112,7 +130,16 @@ instance UtxoDistribution InitialUTxOsWithStakeKey KeyWallet where decodeWallets d p = decodeWalletsDefault d p decodeWallets' (InitialUTxOsWithStakeKey stake _) pks = Array.uncons pks <#> \{ head: key, tail } -> - privateKeysToKeyWallet (PrivatePaymentKey key) (Just stake) /\ + privateKeysToKeyWallet (PrivatePaymentKey key) (Just stake) Nothing /\ + tail + keyWallets _ wallet = [ wallet ] + +instance UtxoDistribution TestWalletSpec KeyWallet where + encodeDistribution (TestWalletSpec { utxos }) = [ utxos ] + decodeWallets distr privateKeys = decodeWalletsDefault distr privateKeys + decodeWallets' (TestWalletSpec { stakeKey, drepKey }) privateKeys = + Array.uncons privateKeys <#> \{ head: key, tail } -> + privateKeysToKeyWallet (PrivatePaymentKey key) stakeKey drepKey /\ tail keyWallets _ wallet = [ wallet ] @@ -128,6 +155,12 @@ instance UtxoDistribution (Array InitialUTxOsWithStakeKey) (Array KeyWallet) whe decodeWallets' = decodeWallets'Array keyWallets = keyWalletsArray +instance UtxoDistribution (Array TestWalletSpec) (Array KeyWallet) where + encodeDistribution = encodeDistributionArray + decodeWallets d = decodeWalletsDefault d + decodeWallets' = decodeWallets'Array + keyWallets = keyWalletsArray + encodeDistributionArray :: forall (distr :: Type) . UtxoDistribution distr KeyWallet @@ -199,7 +232,7 @@ transferFundsFromEnterpriseToBase ourKey wallets = do -- Get all utxos and key hashes at all wallets containing a stake key walletsInfo <- foldM addStakeKeyWalletInfo mempty wallets unless (null walletsInfo) do - let ourWallet = mkKeyWalletFromPrivateKeys ourKey Nothing + let ourWallet = mkKeyWalletFromPrivateKeys ourKey Nothing Nothing ourAddr <- liftedM "Could not get our address" $ head <$> withKeyWallet ourWallet getWalletAddresses ourUtxos <- utxosAt ourAddr @@ -209,14 +242,15 @@ transferFundsFromEnterpriseToBase ourKey wallets = do lookups :: Lookups.ScriptLookups lookups = Lookups.unspentOutputs ourUtxos <> foldMap (_.utxos >>> Lookups.unspentOutputs) walletsInfo + <> Lookups.ownPaymentPubKeyHash ourPkh constraints :: Constraints.TxConstraints constraints = Constraints.mustBeSignedBy ourPkh <> foldMap constraintsForWallet walletsInfo - unbalancedTx <- mkUnbalancedTx lookups constraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints signedTx <- withKeyWallet ourWallet $ - signTransaction =<< balanceTx unbalancedTx + signTransaction =<< balanceTx unbalancedTx usedUtxos mempty signedTx' <- foldM (\tx { wallet } -> withKeyWallet wallet $ signTransaction tx) signedTx @@ -237,9 +271,8 @@ transferFundsFromEnterpriseToBase ourKey wallets = do Constraints.mustBeSignedBy payPkh <> Constraints.mustBeSignedBy (wrap $ unwrap stakePkh) <> foldMapWithIndex - ( \input (TransactionOutputWithRefScript { output }) -> - Constraints.mustPayToPubKeyAddress payPkh stakePkh - (unwrap output).amount + ( \input (TransactionOutput { amount }) -> + Constraints.mustPayToPubKeyAddress payPkh stakePkh amount <> Constraints.mustSpendPubKeyOutput input ) utxos @@ -255,9 +288,11 @@ transferFundsFromEnterpriseToBase ourKey wallets = do payPkh <- liftedM "Could not get payment pubkeyhash" $ head <$> ownPaymentPubKeyHashes networkId <- getNetworkId - addr <- liftContractM "Could not get wallet address" $ - payPubKeyHashEnterpriseAddress networkId payPkh - utxos' <- utxosAt addr + utxos' <- utxosAt $ EnterpriseAddress + { networkId + , paymentCredential: PaymentCredential $ PubKeyHashCredential $ unwrap + payPkh + } pure $ { utxos: utxos', payPkh, stakePkh, wallet } : walletsInfo withStakeKey :: PrivateStakeKey -> InitialUTxOs -> InitialUTxOsWithStakeKey diff --git a/src/Internal/Testnet/Contract.purs b/src/Internal/Testnet/Contract.purs new file mode 100644 index 0000000000..692e07067a --- /dev/null +++ b/src/Internal/Testnet/Contract.purs @@ -0,0 +1,375 @@ +module Ctl.Internal.Testnet.Contract + ( runTestnetContract + , runTestnetTestPlan + , testTestnetContracts + , withTestnetContractEnv + , execDistribution + ) where + +import Contract.Prelude + +import Cardano.Serialization.Lib (privateKey_generateEd25519) as Csl +import Cardano.Types (NetworkId(TestnetId)) +import Cardano.Types.Address (Address, getPaymentCredential, getStakeCredential) +import Cardano.Types.BigInt (BigInt) +import Cardano.Types.BigInt (fromInt) as BigInt +import Cardano.Types.BigNum (fromBigInt, toBigInt) as BigNum +import Cardano.Types.Credential (Credential(PubKeyHashCredential)) +import Cardano.Types.PaymentCredential (PaymentCredential(PaymentCredential)) +import Cardano.Types.StakeCredential (StakeCredential(StakeCredential)) +import Cardano.Types.StakePubKeyHash (StakePubKeyHash(StakePubKeyHash)) +import Cardano.Wallet.Key (KeyWallet) +import Contract.Address (getNetworkId) +import Contract.Log (logInfo') +import Contract.Monad + ( Contract + , ContractEnv + , liftContractE + , liftContractM + , liftedM + , runContractInEnv + ) +import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) +import Contract.TxConstraints (TxConstraints) +import Contract.TxConstraints (mustPayToPubKey, mustPayToPubKeyAddress) as Constraints +import Contract.Value (Value) +import Contract.Value (getCoin, lovelaceValueOf) as Value +import Contract.Wallet + ( getWalletAddress + , getWalletUtxos + , mkKeyWalletFromPrivateKeys + , withKeyWallet + ) +import Control.Monad.State (State, execState, modify_) +import Control.Monad.Trans.Class (lift) +import Control.Monad.Writer (censor, execWriterT, tell) +import Control.Parallel (parTraverse) +import Ctl.Internal.Test.ContractTest + ( ContractTest(ContractTest) + , ContractTestPlan(ContractTestPlan) + , ContractTestPlanHandler + ) +import Ctl.Internal.Test.UtxoDistribution + ( class UtxoDistribution + , decodeWallets + , encodeDistribution + , keyWallets + ) +import Ctl.Internal.Testnet.DistributeFundsV2 (DistrFundsParams) +import Ctl.Internal.Testnet.DistributeFundsV2 (Tx(Tx), makeDistributionPlan) as DistrFunds +import Ctl.Internal.Testnet.Server + ( StartedTestnetCluster + , makeClusterContractEnv + , startTestnetCluster + ) +import Ctl.Internal.Testnet.Types (TestnetConfig) +import Ctl.Internal.Testnet.Utils + ( cleanupOnExit + , read872GenesisKey + , runCleanup + , whenError + ) +import Data.Array (concat, fromFoldable, zip) as Array +import Data.Map (values) as Map +import Effect.Aff (bracket) as Aff +import Effect.Aff (try) +import Effect.Exception (error) +import Effect.Ref (Ref) +import Effect.Ref (new, read, write) as Ref +import Internal.CardanoCli.QueryHandler (withCardanoCliCompletion) +import Mote (bracket) as Mote +import Mote.Description (Description(Group, Test)) +import Mote.Monad (MoteT(MoteT), mapTest) +import Mote.TestPlanM (TestPlanM) +import Type.Proxy (Proxy(Proxy)) + +-- | Run a single `Contract` in cardano-testnet environment. +runTestnetContract + :: forall (distr :: Type) (wallets :: Type) (a :: Type) + . UtxoDistribution distr wallets + => TestnetConfig + -> distr + -> (wallets -> Contract a) + -> Aff a +runTestnetContract cfg distr cont = + withTestnetContractEnv cfg distr \env wallets -> + runContractInEnv env (cont wallets) + +-- | Provide a `ContractEnv` connected to cardano-testnet. +-- | Can be used to run multiple `Contract`s using `runContractInEnv`. +withTestnetContractEnv + :: forall (distr :: Type) (wallets :: Type) (a :: Type) + . UtxoDistribution distr wallets + => TestnetConfig + -> distr + -> (ContractEnv -> wallets -> Aff a) + -> Aff a +withTestnetContractEnv cfg distr cont = do + cleanupRef <- liftEffect $ Ref.new mempty + Aff.bracket + (try $ startTestnetContractEnv cfg distr cleanupRef) + (const $ runCleanup cleanupRef) + $ liftEither + >=> \{ env, wallets, printLogs } -> + whenError printLogs (cont env wallets) + +-- | Run several `Contract`s in tests in a (single) cardano-testnet environment (cardano-testnet, ogmios, kupo, etc.). +-- | NOTE: This uses `MoteT`s bracketing, and thus has the same caveats. +-- | Namely, brackets are run for each of the top-level groups and tests +-- | inside the bracket. +-- | If you wish to only set up Testnet once, ensure all tests that are passed +-- | to `testTestnetContracts` are wrapped in a single group. +-- | https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/doc/cardano-testnet-testing.md#testing-with-mote FIXME +testTestnetContracts + :: TestnetConfig + -> TestPlanM ContractTest Unit + -> TestPlanM (Aff Unit) Unit +testTestnetContracts cfg tp = do + testnetTestPlan <- lift $ execDistribution tp + runTestnetTestPlan cfg testnetTestPlan + +-- | Run a `ContractTestPlan` in a (single) cardano-testnet environment. +-- | Supports wallet reuse - see docs on sharing wallet state between +-- | wallets in `doc/cardano-testnet-testing.md`. FIXME +runTestnetTestPlan + :: TestnetConfig + -> ContractTestPlan + -> TestPlanM (Aff Unit) Unit +runTestnetTestPlan cfg (ContractTestPlan runContractTestPlan) = do + -- Modify tests to pluck out parts of a single combined distribution + runContractTestPlan \distr tests -> do + cleanupRef <- liftEffect $ Ref.new mempty + -- Sets a single Mote bracket at the top level, it will be run for all + -- immediate tests and groups + bracket (startTestnetContractEnv cfg distr cleanupRef) + (runCleanup cleanupRef) + $ flip mapTest tests \test { env, wallets, printLogs, clearLogs } -> do + whenError printLogs (runContractInEnv env (test wallets)) + clearLogs + where + -- `MoteT`'s bracket doesn't support supplying the constructed resource into + -- the main action, so we use a `Ref` to store and read the result. + bracket + :: forall (a :: Type) (b :: Type) + . Aff a + -> Aff Unit + -> TestPlanM (a -> Aff b) Unit + -> TestPlanM (Aff b) Unit + bracket before' after' act = do + resultRef <- liftEffect $ Ref.new + (Left $ error "cardano-testnet not initialized") + let + before = do + res <- try $ before' + liftEffect $ Ref.write res resultRef + pure res + after = const $ after' + Mote.bracket { before, after } $ flip mapTest act \t -> do + result <- liftEffect $ Ref.read resultRef >>= liftEither + t result + +-- | Lifts the UTxO distributions of each test out of Mote, into a combined +-- | distribution. Adapts the tests to pick their distribution out of the +-- | combined distribution. +-- | NOTE: Skipped tests still have their distribution generated. +-- | This is the current method of constructing all the wallets with required distributions +-- | in one go during TestNet startup. +execDistribution :: TestPlanM ContractTest Unit -> Aff ContractTestPlan +execDistribution (MoteT mote) = execWriterT mote <#> go + where + -- Recursively go over the tree of test `Description`s and construct a `ContractTestPlan` callback. + -- When run the `ContractTestPlan` will reconstruct the whole `MoteT` value passed to `execDistribution` + -- via similar writer effects (plus combining distributions) which append test descriptions + -- or wrap them in a group. + go :: Array (Description Aff ContractTest) -> ContractTestPlan + go = flip execState emptyContractTestPlan <<< traverse_ case _ of + Test rm { bracket, label, value: ContractTest runTest } -> + runTest \distr test -> do + addTests distr $ MoteT + (tell [ Test rm { bracket, label, value: test } ]) + Group rm { bracket, label, value } -> do + let ContractTestPlan runGroupPlan = go value + runGroupPlan \distr tests -> + addTests distr $ over MoteT + (censor (pure <<< Group rm <<< { bracket, label, value: _ })) + tests + + -- This function is used by `go` for iteratively adding Mote tests (internally Writer monad actions) + -- to the `ContractTestPlan` in the State monad _and_ for combining UTxO distributions used by tests. + -- Given a distribution and tests (a MoteT value) this runs a `ContractTestPlan`, i.e. passes its + -- stored distribution and tests to our handler, and then makes a new `ContractTestPlan`, but this time + -- storing a tuple of stored and passed distributions and also storing a pair of Mote tests, modifying + -- the previously stored tests to use the first distribution, and the passed tests the second distribution + -- + -- `go` starts at the top of the test tree and step-by-step constructs a big `ContractTestPlan` which + -- stores distributions of all inner tests tupled together and tests from the original test tree, which + -- know how to get their distribution out of the big tuple. + addTests + :: forall (distr :: Type) (wallets :: Type) + . ContractTestPlanHandler distr wallets (State ContractTestPlan Unit) + addTests distr tests = do + modify_ \(ContractTestPlan runContractTestPlan) -> runContractTestPlan + \distr' tests' -> ContractTestPlan \h -> h (distr' /\ distr) do + mapTest (_ <<< fst) tests' + mapTest (_ <<< snd) tests + + -- Start with an empty plan, which passes an empty distribution + -- and an empty array of test `Description`s to the function that + -- will run tests. + emptyContractTestPlan :: ContractTestPlan + emptyContractTestPlan = ContractTestPlan \h -> h unit (pure unit) + +-- | Provide a `ContractEnv` connected to cardano-testnet. +-- | can be used to run multiple `Contract`s using `runContractInEnv`. +startTestnetContractEnv + :: forall (distr :: Type) (wallets :: Type) + . UtxoDistribution distr wallets + => TestnetConfig + -> distr + -> Ref (Array (Aff Unit)) + -> Aff + { cluster :: StartedTestnetCluster + , env :: ContractEnv + , wallets :: wallets + , printLogs :: Aff Unit + , clearLogs :: Aff Unit + } +startTestnetContractEnv cfg distr cleanupRef = do + _ <- cleanupOnExit cleanupRef + cluster <- startTestnetCluster cfg cleanupRef + { env, printLogs, clearLogs } <- makeClusterContractEnv cleanupRef cfg + let env' = env { networkId = TestnetId } + wallets <- mkWallets env' cluster + pure + { cluster + , env: env' + , wallets + , printLogs + , clearLogs + } + where + mkWallets :: ContractEnv -> StartedTestnetCluster -> Aff wallets + mkWallets env cluster = + runContractInEnv env do + genesisWallets <- liftEffect readGenesisWallets + let + nodeCfg = + { socketPath: (unwrap cluster).paths.nodeSocketPath + , testnetMagic: cfg.clusterConfig.testnetMagic + } + wallets /\ distrPlan <- makeDistrFundsPlan + (withCardanoCliCompletion nodeCfg) + genesisWallets + distr + execDistrFundsPlan (withCardanoCliCompletion nodeCfg) distrPlan + pure wallets + where + readGenesisWallets :: Effect (Array KeyWallet) + readGenesisWallets = + traverse + ( \location -> do + paymentKey <- read872GenesisKey location + pure $ mkKeyWalletFromPrivateKeys paymentKey Nothing Nothing + ) + (unwrap cluster).paths.genesisKeys + +execDistrFundsPlan + :: (forall a. Address -> Contract a -> Contract a) + -> Array (Array (DistrFunds.Tx KeyWallet BigInt)) + -> Contract Unit +execDistrFundsPlan withCardanoCliUtxos rounds = do + network <- getNetworkId + roundsFixed <- + liftContractM "Could not convert target amounts to BigNum's" $ + traverse (traverse (traverse BigNum.fromBigInt)) rounds + traverse_ + ( parTraverse + ( \(DistrFunds.Tx { srcWallet: genesisWallet, utxos }) -> do + withKeyWallet genesisWallet do + genesisAddr <- liftedM "Could not get genesis address" + getWalletAddress + withCardanoCliUtxos genesisAddr do + constraints <- liftAff $ fold <$> traverse + ( \{ wallet, amount } -> do + addrs <- (unwrap wallet).address network + pure $ mustPayToAddress addrs $ Value.lovelaceValueOf + amount + ) + utxos + + txHash <- submitTxFromConstraints mempty constraints + logInfo' $ "FundWalletsFromGenesis txHash: " <> show txHash + awaitTxConfirmed txHash + ) + ) + roundsFixed + +makeDistrFundsPlan + :: forall (distr :: Type) (wallets :: Type) + . UtxoDistribution distr wallets + => (forall a. Address -> Contract a -> Contract a) + -> Array KeyWallet + -> distr + -> Contract (wallets /\ Array (Array (DistrFunds.Tx KeyWallet BigInt))) +makeDistrFundsPlan withCardanoCliUtxos genesisWallets distr = do + let distrArray = map BigNum.toBigInt <$> encodeDistribution distr + privateKeys <- + for (encodeDistribution distr) \_ -> + liftEffect $ wrap <$> Csl.privateKey_generateEd25519 + wallets <- + liftContractM + "Impossible happened: could not decode wallets. Please report as bug" + $ decodeWallets distr privateKeys + let + kws = keyWallets (Proxy :: _ distr) wallets + targets = Array.concat $ sequence <$> Array.zip kws distrArray + sources <- Array.concat <$> + parTraverse (\kw -> map (Tuple kw) <$> getGenesisUtxos kw) + genesisWallets + distrPlan <- + liftContractE $ + DistrFunds.makeDistributionPlan distrFundsParams sources targets + pure $ wallets /\ distrPlan + where + getGenesisUtxos :: KeyWallet -> Contract (Array BigInt) + getGenesisUtxos genesisWallet = + withKeyWallet genesisWallet do + genesisAddr <- liftedM "Could not get genesis address" getWalletAddress + withCardanoCliUtxos genesisAddr do + liftedM "Could not get genesis wallet utxos" getWalletUtxos + <#> map + ( BigNum.toBigInt + <<< unwrap + <<< Value.getCoin + <<< _.amount + <<< unwrap + ) + <<< Array.fromFoldable + <<< Map.values + +-- FIXME: adjust values +distrFundsParams :: DistrFundsParams KeyWallet BigInt +distrFundsParams = + { maxRounds: 3 + , maxUtxosPerTx: 100 + , getUtxoMinAdaForWallet: const zero + , feePerTx: BigInt.fromInt 2_000_000 + } + +-- FIXME: move to helpers +mustPayToAddress :: Address -> Value -> TxConstraints +mustPayToAddress addr = + let + mSkh = case getStakeCredential addr of + Just (StakeCredential (PubKeyHashCredential skh')) -> Just $ + StakePubKeyHash skh' + _ -> Nothing + in + case getPaymentCredential addr of + Just (PaymentCredential (PubKeyHashCredential pkh)) -> + case mSkh of + Nothing -> + Constraints.mustPayToPubKey $ wrap pkh + Just skh -> + Constraints.mustPayToPubKeyAddress (wrap pkh) skh + _ -> mempty diff --git a/src/Internal/Testnet/DistributeFunds.purs b/src/Internal/Testnet/DistributeFunds.purs new file mode 100644 index 0000000000..c2f801c191 --- /dev/null +++ b/src/Internal/Testnet/DistributeFunds.purs @@ -0,0 +1,252 @@ +module Ctl.Internal.Testnet.DistributeFunds + ( makeDistributionPlan + , parallelizedDistributionPlan + , SourceState(SourceState) + , Tx(Tx) + , _completeTxs + , _leftover + , _source + , _total + , _totalUtxos + , _tx + , _utxos + -- * Exported for testing purposes + , assignUtxo + , emptyTx + , initialSourceState + ) where + +import Contract.Prelude + +import Control.Alt ((<|>)) +import Data.Array as Array +import Data.Bifunctor (class Bifunctor, bimap) +import Data.Lens (Lens', view, (%~), (+~), (-~), (.~), (^.)) +import Data.Lens.Iso.Newtype (_Newtype) +import Data.Lens.Record (prop) +import Data.List (List(Cons, Nil)) +import Data.List as List +import Data.Map (Map) +import Data.Map as Map +import Effect.Exception.Unsafe (unsafeThrow) +import Type.Proxy (Proxy(Proxy)) + +newtype Tx src target amount = Tx + { source :: { key :: src } + , total :: amount + , totalUtxos :: Int + , utxos :: List { key :: target, amount :: amount } + } + +derive instance Newtype (Tx s t a) _ +derive instance Generic (Tx s t a) _ +derive instance (Eq s, Eq t, Eq a) => Eq (Tx s t a) +derive instance (Ord s, Ord t, Ord a) => Ord (Tx s t a) +instance (Show s, Show t, Show a) => Show (Tx s t a) where + show = genericShow + +emptyTx + :: forall target amount + . amount + -> Tx Unit target amount +emptyTx total = Tx + { source: { key: unit } + , total + , totalUtxos: 0 + , utxos: Nil + } + +newtype SourceState src target amount = SourceState + { source :: src + , leftover :: amount + , tx :: Tx Unit target amount + , completeTxs :: List (Tx Unit target amount) + } + +derive instance Newtype (SourceState s t a) _ +derive instance Generic (SourceState s t a) _ +derive instance (Eq s, Eq t, Eq a) => Eq (SourceState s t a) +derive instance (Ord s, Ord t, Ord a) => Ord (SourceState s t a) +instance (Show s, Show t, Show a) => Show (SourceState s t a) where + show = genericShow + +initialSourceState + :: forall src target amount + . Semiring amount + => { initialFunds :: amount, key :: src } + -> SourceState src target amount +initialSourceState { initialFunds, key } = SourceState + { source: key + , leftover: initialFunds + , tx: emptyTx zero + , completeTxs: Nil + } + +parallelizedDistributionPlan + :: forall src target amount + . Map src (Array (Tx Unit target amount)) + -> Array (Map src (Tx Unit target amount)) +parallelizedDistributionPlan _ = unsafeThrow "hello" + +makeDistributionPlan + :: forall src target amount + . Ord src + => Ord amount + => Ord target + => Ring amount + => Map src amount + -> Map target (Array amount) + -> { maxCoinPerTx :: amount + , maxTargetUtxosPerTx :: Int + } + -> Either + { err :: String + , acc :: List (SourceState src target amount) + } + (Map src (Array (Tx Unit target amount))) +makeDistributionPlan sources targets thresholds = do + let + targetsUtxosAsc :: List { key :: target, amount :: amount } + targetsUtxosAsc = List.sortBy (flip compare) + $ Map.toUnfoldable targets + >>= \(key /\ utxos) -> + { key, amount: _ } <$> List.fromFoldable utxos + + assigned :: Either _ (Map src (Array (Tx Unit target amount))) + assigned = do + sourcesTxs <- foldM + (flip $ assignUtxo thresholds) + ( initialSourceState <<< uncurry { key: _, initialFunds: _ } <$> + Map.toUnfoldable sources + ) + targetsUtxosAsc + let + finish src = + src + # (_tx .~ emptyTx zero) + # (_completeTxs %~ Cons (src ^. _tx)) + sourceToTxs = Map.fromFoldable + $ Tuple + <<< view _source + <*> Array.fromFoldable + <<< view _completeTxs + <<< finish + <$> sourcesTxs + pure sourceToTxs + assigned + +assignUtxo + :: forall target src amount + . Ord amount + => Ring amount + => { maxCoinPerTx :: amount + , maxTargetUtxosPerTx :: Int + } + -> { amount :: amount, key :: target } + -> List (SourceState src target amount) + -> Either + { err :: String + , acc :: List (SourceState src target amount) + } + (List (SourceState src target amount)) +assignUtxo _ _ Nil = Left + { err: "Ran out of sources", acc: Nil } +assignUtxo thresholds utxo acc@(Cons source sources) + | 0 >= thresholds.maxTargetUtxosPerTx = + Left { err: "maxTargetUtxosPerTx must be greater than 1", acc } + | utxo.amount >= thresholds.maxCoinPerTx = + Left + { err: "UTxO required amount is higher than the maxCoinPerTx threshold" + , acc + } + | (source ^. _tx <<< _totalUtxos) + >= thresholds.maxTargetUtxosPerTx = + -- means that this Tx is complete + assignUtxo thresholds utxo + $ startNewTx source sources -- be careful: infinite loop + -- it will terminate because new tx has 0 utxos which is higher than 'maxTargetUtxosPerTx' + | (source ^. _tx <<< _total) + utxo.amount + > thresholds.maxCoinPerTx = + -- means that utxo cannot be fit in this Tx + let + -- try fit this utxo in any source + tryAnother = tryWithAnotherSource + "Cannot fit UTxO amount into the Tx" + (assignUtxo thresholds utxo) + source + sources + -- if no source can fit this utxo, create a new tx + startNew = assignUtxo thresholds utxo + $ startNewTx source sources -- be careful: infinite loop + -- it will terminate because either new Tx starting with 0 total can fit it + -- or the condition above will throw Left + in + tryAnother <|> startNew + | source ^. _leftover < utxo.amount = + -- means that this source cannot fit this tx + -- should try with the rest of sources and fail otherwise + tryWithAnotherSource + "Not enough funds on sources" + (assignUtxo thresholds utxo) + source + sources + | otherwise = + -- means that utxo can be fit into the current tx + let + source' = source + # (_leftover -~ utxo.amount) + # (_tx <<< _total +~ utxo.amount) + # (_tx <<< _totalUtxos +~ 1) + # (_tx <<< _utxos %~ Cons utxo) + in + Right $ Cons source' sources + +-- * Helpers + +-- helper for assignUtxo +tryWithAnotherSource + :: forall s f + . Bifunctor f + => String + -> (List s -> f { err :: String, acc :: List s } (List s)) + -> s + -> List s + -> f { err :: String, acc :: List s } (List s) +tryWithAnotherSource err self source sources = + bimap (\e -> e { err = err <> "/" <> e.err, acc = Cons source e.acc }) + (Cons source) + $ self sources + +-- helper for assignUtxo +startNewTx + :: forall src target amount + . Semiring amount + => SourceState src target amount + -> List (SourceState src target amount) + -> List (SourceState src target amount) +startNewTx source sources = + List.snoc sources + $ (_tx .~ emptyTx zero) + $ (_completeTxs %~ Cons (source ^. _tx)) + $ source + +_totalUtxos :: forall s t a. Lens' (Tx s t a) Int +_totalUtxos = _Newtype <<< prop (Proxy :: _ "totalUtxos") + +_utxos :: forall s t a. Lens' (Tx s t a) (List { key :: t, amount :: a }) +_utxos = _Newtype <<< prop (Proxy :: _ "utxos") + +_total :: forall s t a. Lens' (Tx s t a) a +_total = _Newtype <<< prop (Proxy :: _ "total") + +_tx :: forall s t a. Lens' (SourceState s t a) (Tx Unit t a) +_tx = _Newtype <<< prop (Proxy :: _ "tx") + +_leftover :: forall s t a. Lens' (SourceState s t a) a +_leftover = _Newtype <<< prop (Proxy :: _ "leftover") + +_source :: forall s t a. Lens' (SourceState s t a) s +_source = _Newtype <<< prop (Proxy :: _ "source") + +_completeTxs :: forall s t a. Lens' (SourceState s t a) (List (Tx Unit t a)) +_completeTxs = _Newtype <<< prop (Proxy :: _ "completeTxs") diff --git a/src/Internal/Testnet/DistributeFundsV2.purs b/src/Internal/Testnet/DistributeFundsV2.purs new file mode 100644 index 0000000000..4476cc86f6 --- /dev/null +++ b/src/Internal/Testnet/DistributeFundsV2.purs @@ -0,0 +1,266 @@ +module Ctl.Internal.Testnet.DistributeFundsV2 where + +import Prelude + +import Control.Monad.Rec.Class (Step(Done, Loop), tailRecM) +import Control.Safely (foldM) +import Data.Array (fromFoldable, snoc) as Array +import Data.Bifunctor (class Bifunctor) +import Data.Either (Either(Left, Right)) +import Data.Foldable + ( class Foldable + , foldMap + , foldlDefault + , foldr + , foldrDefault + ) +import Data.Generic.Rep (class Generic) +import Data.List (List(Cons, Nil)) +import Data.List (filter, fromFoldable) as List +import Data.Newtype (class Newtype, modify, unwrap, wrap) +import Data.Show.Generic (genericShow) +import Data.Traversable (class Traversable, sequenceDefault, traverse) +import Data.Tuple (uncurry) +import Data.Tuple.Nested (type (/\), (/\)) + +type DistrFundsParams wallet amount = + { maxRounds :: Int + , maxUtxosPerTx :: Int + , getUtxoMinAdaForWallet :: wallet -> amount + , feePerTx :: amount + } + +-- + +newtype Tx wallet amount = Tx + { srcWallet :: wallet + , numUtxos :: Int + , utxos :: List { wallet :: wallet, amount :: amount } + } + +derive instance Generic (Tx wallet amount) _ +derive instance Newtype (Tx wallet amount) _ +derive instance (Eq wallet, Eq amount) => Eq (Tx wallet amount) + +instance (Show wallet, Show amount) => Show (Tx wallet amount) where + show = genericShow + +instance Functor (Tx wallet) where + map f (Tx tx) = + wrap $ tx + { utxos = + map (\utxo -> utxo { amount = f utxo.amount }) + tx.utxos + } + +instance Bifunctor Tx where + bimap f g (Tx tx) = + wrap $ tx + { srcWallet = f tx.srcWallet + , utxos = map (\utxo -> { wallet: f utxo.wallet, amount: g utxo.amount }) + tx.utxos + } + +instance Foldable (Tx wallet) where + foldl f a = foldlDefault f a + foldr f a = foldrDefault f a + foldMap f = foldMap (f <<< _.amount) <<< _.utxos <<< unwrap + +instance Traversable (Tx wallet) where + sequence = sequenceDefault + traverse f (Tx tx) = ado + utxos <- traverse + (\{ wallet, amount } -> { wallet, amount: _ } <$> f amount) + tx.utxos + in wrap $ tx { utxos = utxos } + +emptyTx :: forall wallet amount. wallet -> Tx wallet amount +emptyTx srcWallet = wrap + { srcWallet + , numUtxos: zero + , utxos: Nil + } + +isTxNonEmpty :: forall wallet amount. Tx wallet amount -> Boolean +isTxNonEmpty (Tx { numUtxos }) = numUtxos > zero + +-- + +type SourceState wallet amount = + { srcWallet :: wallet + , leftover :: amount + , currentTx :: Tx wallet amount + } + +initSourceState + :: forall wallet amount + . wallet + -> amount + -> SourceState wallet amount +initSourceState srcWallet initFunds = + { srcWallet + , leftover: initFunds + , currentTx: emptyTx srcWallet + } + +resetSourceTx + :: forall wallet amount + . SourceState wallet amount + -> SourceState wallet amount +resetSourceTx src = src { currentTx = emptyTx src.srcWallet } + +-- + +data DistrFundsError + = DistrFunds_MaxUtxosPerTxLowerLimitError + | DistrFunds_AssignUtxoError + | DistrFunds_MaxRoundsExceededError + +derive instance Generic DistrFundsError _ +derive instance Eq DistrFundsError + +instance Show DistrFundsError where + show = genericShow + +type DistrFundsRoundResult wallet amount = + { sources :: List (SourceState wallet amount) + , deferredTargets :: List (wallet /\ amount) + } + +data AssignUtxoResult wallet amount + = AssignUtxo_Unassigned + | AssignUtxo_Deferred + | AssignUtxo_AssignedToSource (SourceState wallet amount) + +derive instance Generic (AssignUtxoResult wallet amount) _ +derive instance (Eq wallet, Eq amount) => Eq (AssignUtxoResult wallet amount) + +instance (Show wallet, Show amount) => Show (AssignUtxoResult wallet amount) where + show = genericShow + +makeDistributionPlan + :: forall wallet amount + . Ord amount + => Ring amount + => DistrFundsParams wallet amount + -> Array (wallet /\ amount) + -> Array (wallet /\ amount) + -> Either DistrFundsError (Array (Array (Tx wallet amount))) +makeDistributionPlan params initSources initTargets + | params.maxUtxosPerTx < one = Left DistrFunds_MaxUtxosPerTxLowerLimitError + | otherwise = + tailRecM worker + { sources: List.fromFoldable $ uncurry initSourceState <$> initSources + , targets: List.fromFoldable initTargets + , rounds: mempty + , roundIdx: zero + } + where + worker { sources, targets, rounds, roundIdx } + | roundIdx == params.maxRounds = + Left DistrFunds_MaxRoundsExceededError + | otherwise = + runDistrFundsRound params sources targets <#> \res -> + let + completedTxs = List.filter isTxNonEmpty $ _.currentTx <$> + res.sources + rounds' = Array.snoc rounds $ Array.fromFoldable completedTxs + in + case res.deferredTargets of + Nil -> Done rounds' + _ -> Loop + { sources: resetSourceTx <$> res.sources + , targets: res.deferredTargets + , rounds: rounds' + , roundIdx: roundIdx + one + } + +runDistrFundsRound + :: forall wallet amount + . Ord amount + => Ring amount + => DistrFundsParams wallet amount + -> List (SourceState wallet amount) + -> List (wallet /\ amount) + -> Either DistrFundsError (DistrFundsRoundResult wallet amount) +runDistrFundsRound params initSources targets = + foldM + ( \distrFundsAcc target -> + let + assignUtxoRes /\ sourcesUpdated = + foldr (tryNextSource params target) (AssignUtxo_Unassigned /\ Nil) + distrFundsAcc.sources + in + case assignUtxoRes of + AssignUtxo_Unassigned -> + Left DistrFunds_AssignUtxoError + AssignUtxo_Deferred -> + Right $ distrFundsAcc + { deferredTargets = Cons target distrFundsAcc.deferredTargets + } + AssignUtxo_AssignedToSource _ -> + Right $ distrFundsAcc + { sources = sourcesUpdated + } + ) + { sources: initSources + , deferredTargets: Nil + } + targets + +tryNextSource + :: forall wallet amount + . Ord amount + => Ring amount + => DistrFundsParams wallet amount + -> wallet /\ amount + -> SourceState wallet amount + -> AssignUtxoResult wallet amount /\ List (SourceState wallet amount) + -> AssignUtxoResult wallet amount /\ List (SourceState wallet amount) +tryNextSource params (targetWallet /\ amount) source (acc /\ sources) = + case acc of + AssignUtxo_AssignedToSource _ -> + -- utxo already assigned, skip other sources + acc /\ Cons source sources + _ -> + let + targetNormalized = + targetWallet /\ max (params.getUtxoMinAdaForWallet targetWallet) + amount + in + case acc, assignUtxoToSource params source targetNormalized of + AssignUtxo_Deferred, AssignUtxo_Unassigned -> + -- utxo marked as deferred that cannot fit into the current tx + -- should remain deferred + AssignUtxo_Deferred /\ Cons source sources + _, new@(AssignUtxo_AssignedToSource sourceUpdated) -> + new /\ Cons sourceUpdated sources + _, new -> + new /\ Cons source sources + +assignUtxoToSource + :: forall wallet amount + . Ord amount + => Ring amount + => DistrFundsParams wallet amount + -> SourceState wallet amount + -> wallet /\ amount + -> AssignUtxoResult wallet amount +assignUtxoToSource params source (targetWallet /\ amountNormalized) + | (source.leftover - params.feePerTx) < amountNormalized = + AssignUtxo_Unassigned + | (unwrap source.currentTx).numUtxos + one > params.maxUtxosPerTx = + AssignUtxo_Deferred + | otherwise = + AssignUtxo_AssignedToSource $ source + { leftover = source.leftover - amountNormalized + , currentTx = modify + ( \tx -> tx + { numUtxos = tx.numUtxos + one + , utxos = Cons + { wallet: targetWallet, amount: amountNormalized } + tx.utxos + } + ) + source.currentTx + } diff --git a/src/Internal/Testnet/Server.purs b/src/Internal/Testnet/Server.purs new file mode 100644 index 0000000000..63e09f5b4a --- /dev/null +++ b/src/Internal/Testnet/Server.purs @@ -0,0 +1,604 @@ +module Ctl.Internal.Testnet.Server + ( Channels + , StartedTestnetCluster(MkStartedTestnetCluster) + , startKupo + , startOgmios + , startTestnetCluster + , makeClusterContractEnv + ) where + +import Contract.Prelude hiding (log) + +import Cardano.Types (NetworkId(MainnetId)) +import Contract.Config (Hooks, defaultSynchronizationParams, defaultTimeParams) +import Contract.Monad (ContractEnv) +import Control.Alt ((<|>)) +import Control.Apply (applySecond) +import Control.Monad.Error.Class (throwError) +import Control.Monad.Rec.Class (Step(Loop), tailRecM) +import Ctl.Internal.Contract.Monad + ( buildBackend + , getLedgerConstants + , mkQueryHandle + , stopContractEnv + ) +import Ctl.Internal.Contract.QueryBackend (mkCtlBackendParams) +import Ctl.Internal.Helpers ((<>)) +import Ctl.Internal.Logging (Logger, mkLogger, setupLogs) +import Ctl.Internal.QueryM.UniqueId (uniqueId) +import Ctl.Internal.ServerConfig (ServerConfig) +import Ctl.Internal.Spawn + ( ManagedProcess(ManagedProcess) + , NewOutputAction(NoOp, Success) + , _rmdirSync + , isPortAvailable + , killProcessWithPort + , spawn + , stop + ) +import Ctl.Internal.Testnet.Types + ( Node + , TestnetClusterConfig + , TestnetConfig + , TestnetPaths + ) +import Ctl.Internal.Testnet.Utils + ( EventSource + , addCleanup + , after + , annotateError + , findNodeDirs + , findTestnetPaths + , getRuntime + , onLine + , readNodes + , runCleanup + , scheduleCleanup + , suppressAndLogErrors + , tmpdir + , tryAndLogErrors + , waitForClose + , waitForError + , waitForEvent + , waitUntil + ) +import Ctl.Internal.Types.UsedTxOuts (newUsedTxOuts) +import Data.Log.Message (Message) +import Data.Maybe (Maybe(Nothing, Just)) +import Data.Set as Set +import Data.String (stripPrefix, trim) as String +import Data.String.CodeUnits (indexOf) as String +import Data.String.Pattern (Pattern(Pattern)) +import Data.Time.Duration (Milliseconds(Milliseconds)) +import Data.UInt (UInt) +import Data.UInt (toString) as UInt +import Effect.Aff (Aff, launchAff_) +import Effect.Aff as Aff +import Effect.Aff.Retry + ( RetryPolicy + , constantDelay + , limitRetriesByCumulativeDelay + , recovering + ) +import Effect.Exception (Error, error, throw) +import Effect.Ref (Ref) +import Effect.Ref (modify_, new, read, write) as Ref +import Foreign.Object as Object +import Node.ChildProcess (defaultSpawnOptions) +import Node.ChildProcess as Node.ChildProcess +import Node.Encoding (Encoding(UTF8)) +import Node.FS.Sync (exists, mkdir) as FSSync +import Node.FS.Sync as Node.FS +import Node.Path (FilePath) +import Node.Process as Node.Process + +type Channels a = + { stderr :: EventSource a + , stdout :: EventSource a + } + +newtype StartedTestnetCluster = MkStartedTestnetCluster + { ogmios :: + { process :: ManagedProcess + , channels :: Channels String + } + , kupo :: + { process :: ManagedProcess + , channels :: Channels String + , workdir :: FilePath + } + , testnet :: + { process :: ManagedProcess + , channels :: Channels String + } + , paths :: TestnetPaths + } + +derive instance Newtype StartedTestnetCluster _ + +startOgmios + :: forall r r' + . { ogmiosConfig :: ServerConfig | r } + -> { nodeSocketPath :: FilePath + , nodeConfigPath :: FilePath + | r' + } + -> Aff ManagedProcess +startOgmios cfg params = do + spawn "ogmios" ogmiosArgs defaultSpawnOptions + $ Just + $ _.output + >>> String.indexOf (Pattern "networkParameters") + >>> maybe NoOp (const Success) + >>> pure + where + ogmiosArgs :: Array String + ogmiosArgs = + [ "--host" + , cfg.ogmiosConfig.host + , "--port" + , UInt.toString cfg.ogmiosConfig.port + , "--node-socket" + , params.nodeSocketPath + , "--node-config" + , params.nodeConfigPath + , "--include-transaction-cbor" + ] + +startKupo + :: forall r r' + . { kupoConfig :: ServerConfig | r } + -> { nodeSocketPath :: FilePath + , nodeConfigPath :: FilePath + | r' + } + -> Ref (Array (Aff Unit)) + -> Aff (ManagedProcess /\ String) +startKupo cfg params cleanupRef = do + tmpDir <- liftEffect tmpdir + randomStr <- liftEffect $ uniqueId "" + let + workdir = tmpDir <> randomStr <> "-kupo-db" + liftEffect do + workdirExists <- FSSync.exists workdir + unless workdirExists (FSSync.mkdir workdir) + childProcess <- + after + (spawnKupoProcess workdir) + -- set up cleanup + $ const + $ liftEffect + $ addCleanup cleanupRef + $ liftEffect + $ _rmdirSync workdir + pure (childProcess /\ workdir) + where + spawnKupoProcess :: FilePath -> Aff ManagedProcess + spawnKupoProcess workdir = + spawn "kupo" (kupoArgs workdir) defaultSpawnOptions $ + Just + ( _.output >>> String.indexOf outputString + >>> maybe NoOp (const Success) + >>> pure + ) + where + outputString :: Pattern + outputString = Pattern "ConfigurationCheckpointsForIntersection" + + kupoArgs :: FilePath -> Array String + kupoArgs workdir = + [ "--match" + , "*/*" + , "--since" + , "origin" + , "--workdir" + , workdir + , "--host" + , cfg.kupoConfig.host + , "--port" + , UInt.toString cfg.kupoConfig.port + , "--node-socket" + , params.nodeSocketPath + , "--node-config" + , params.nodeConfigPath + ] + +-- | Start the testnet cluster, initializing the state with the given +-- | UTxO distribution. Also initializes an extra payment key (aka +-- | `ourKey`) with some UTxOs for use with further testnet +-- | setup. `ourKey` has funds proportional to the total amount of the +-- | UTxOs in the passed distribution, so it can be used to handle +-- | transaction fees. +startTestnetCluster + :: TestnetConfig + -> Ref (Array (Aff Unit)) + -> Aff StartedTestnetCluster +startTestnetCluster cfg cleanupRef = do + { testnet, channels, workdirAbsolute } <- + annotateError "Could not start cardano-testnet" $ + startCardanoTestnet cfg.clusterConfig cleanupRef + + { paths } <- waitUntil (Milliseconds 4000.0) + $ map hush + $ tryAndLogErrors "Waiting for ready state" + $ liftEffect do + + paths <- liftEither =<< findTestnetPaths { workdir: workdirAbsolute } + runtime <- getRuntime paths + pure { runtime, paths } + + ogmios <- annotateError "Could not start ogmios" + $ startOgmios' { paths, workdir: workdirAbsolute } + kupo <- annotateError "Could not start kupo" + $ startKupo' { paths, workdir: workdirAbsolute } + + pure $ MkStartedTestnetCluster + { paths + , ogmios + , kupo + , testnet: { process: testnet, channels } + } + where + startKupo' { paths, workdir } = do + kupo /\ kupoWorkdir <- + scheduleCleanup + cleanupRef + (startKupo cfg paths cleanupRef) + (stopChildProcessWithPort cfg.kupoConfig.port <<< fst) + + void $ Aff.forkAff (waitForClose kupo *> runCleanup cleanupRef) + + kupoChannels <- liftEffect $ getChannels kupo + _ <- redirectChannels + kupoChannels + { stderrTo: + { log: Just $ workdir <> "kupo.stderr.log" + , console: Just "[kupo][error]: " + } + , stdoutTo: + { log: Just $ workdir <> "kupo.stdout.log", console: Nothing } + } + pure { process: kupo, workdir: kupoWorkdir, channels: kupoChannels } + + startOgmios' { paths, workdir } = do + ogmios <- + scheduleCleanup + cleanupRef + (startOgmios cfg paths) + (stopChildProcessWithPort cfg.ogmiosConfig.port) + + void $ Aff.forkAff (waitForClose ogmios *> runCleanup cleanupRef) + + ogmiosChannels <- liftEffect $ getChannels ogmios + _ <- redirectChannels + ogmiosChannels + { stderrTo: + { log: Just $ workdir <> "ogmios.stderr.log" + , console: Just "[ogmios][error]: " + } + , stdoutTo: + { log: Just $ workdir <> "ogmios.stdout.log", console: Nothing } + } + pure { process: ogmios, channels: ogmiosChannels } + +-- | Runs cardano-testnet executable with provided params. +spawnCardanoTestnet + :: { cwd :: FilePath } + -> TestnetClusterConfig + -> Aff { testnet :: ManagedProcess, workspace :: FilePath } +spawnCardanoTestnet { cwd } params = do + env <- liftEffect Node.Process.getEnv + -- initCwd <- liftMaybe (error "Couldn't find INIT_CWD env variable") + -- $ Object.lookup "INIT_CWD" env + let + env' = Object.fromFoldable + [ "TMPDIR" /\ cwd -- only for 8.1.1; 8.7.2 puts it's testnet directory into cwd instead + -- , "CARDANO_NODE_SRC" /\ (initCwd <> "cardano-testnet-files") + , "CARDANO_CLI" /\ "cardano-cli" + , "CREATE_SCRIPT_CONTEXT" /\ "create-script-context" + , "CARDANO_NODE" /\ "cardano-node" + , "CARDANO_SUBMIT_API" /\ "cardano-submit-api" + , "CARDANO_NODE_CHAIRMAN" /\ "cardano-node-chairman" + ] + opts = defaultSpawnOptions + { cwd = Just cwd, env = Just $ Object.union env' env } + workspaceRef <- liftEffect $ Ref.new mempty + ps <- spawn "cardano-testnet" options opts $ + Just + ( \{ line } -> + case String.stripPrefix (Pattern "Workspace: ") (String.trim line) of + Nothing -> pure NoOp + Just workspace -> do + void $ Ref.write workspace workspaceRef + pure Success + ) + workspace <- liftEffect $ Ref.read workspaceRef + pure { testnet: ps, workspace } + where + flag :: String -> String + flag name = "--" <> name + + option :: forall a. Show a => String -> a -> Array String + option name value = [ flag name, show value ] + + options :: Array String + options = join + [ [ "cardano" ] + , option "testnet-magic" params.testnetMagic + , [ flag $ show params.era ] + , option "slot-length" $ unwrap params.slotLength + , maybe mempty + (\epochSize -> [ flag "epoch-length", UInt.toString epochSize ]) + params.epochSize + ] + +startCardanoTestnet + :: TestnetClusterConfig + -> Ref (Array (Aff Unit)) + -> Aff + { testnet :: ManagedProcess + , channels :: + { stderr :: EventSource String + , stdout :: EventSource String + } + , workdirAbsolute :: FilePath + , nodes :: Array { | Node () } + } +startCardanoTestnet params cleanupRef = annotateError "startCardanoTestnet" do + tmpDir <- liftEffect tmpdir + { testnet, workspace } <- spawnCardanoTestnet { cwd: tmpDir } params + channels <- liftEffect $ getChannels testnet + + void $ Aff.forkAff $ annotateError "startCardanoTestnet:waitForErrorOrClose" + do + let + waitError = Just <$> waitForError testnet + waitClose = Nothing <$ waitForClose testnet + cause <- waitError <|> waitClose + runCleanup cleanupRef + throwError $ fromMaybe (error "cardano-testnet process has exited") cause + + nodes <- + waitUntil (Milliseconds 3000.0) $ liftEffect do + hush <$> tryAndLogErrors "startCardanoTestnet:waitForNodes" do + nodeDirs <- findNodeDirs { workdir: workspace } + readNodes { testnetDirectory: workspace, nodeDirs } + + liftEffect $ + for_ nodes \{ port } -> + addCleanup cleanupRef (killProcessWithPort port) + + -- clean up on SIGINT + do + shouldCleanup <- liftEffect + $ Node.Process.lookupEnv "TESTNET_CLEANUP_WORKDIR" + <#> case _ of + Just "0" -> false + _ -> true + when shouldCleanup + $ liftEffect + $ addCleanup cleanupRef + $ liftEffect do + log $ "Cleaning up workdir: " <> workspace + _rmdirSync workspace + launchAff_ $ stop testnet + + _ <- redirectChannels + { stderr: channels.stderr, stdout: channels.stdout } + { stdoutTo: + { log: Just $ workspace <> "cardano-testnet.stdout.log" + , console: Nothing + } + , stderrTo: + { log: Just $ workspace <> "cardano-testnet.stderr.log" + , console: Nothing + } + } + + log "startCardanoTestnet:done" + pure { testnet, workdirAbsolute: workspace, channels, nodes } + +getChannels + :: ManagedProcess + -> Effect + { stderr :: EventSource String + , stdout :: EventSource String + } +getChannels (ManagedProcess _ process _) = ado + stdout <- onLine (Node.ChildProcess.stdout process) Just + stderr <- onLine (Node.ChildProcess.stderr process) Just + in { stdout, stderr } + +-- Note: it will not throw, so to check the computation result +-- Fiber must be inspected. +redirectChannels + :: { stderr :: EventSource String + , stdout :: EventSource String + } + -> { stderrTo :: { log :: Maybe FilePath, console :: Maybe String } + , stdoutTo :: { log :: Maybe FilePath, console :: Maybe String } + } + -> Aff (Aff.Fiber (Either Error Unit)) +redirectChannels { stderr, stdout } { stderrTo, stdoutTo } = do + handleStderr <- redirectLogging + stderr + { storeLogs: stderrTo.log <#> + { logFile: _ + , toString: identity + } + , handleLine: case stderrTo.console of + Nothing -> const $ pure unit + Just prefix -> append prefix >>> log + } + handleStdout <- redirectLogging + stdout + { storeLogs: stdoutTo.log <#> + { logFile: _ + , toString: identity + } + , handleLine: case stdoutTo.console of + Nothing -> const $ pure unit + Just prefix -> append prefix >>> log + } + pure $ applySecond <$> handleStderr <*> handleStdout + +redirectLogging + :: forall a + . EventSource a + -> { storeLogs :: + Maybe + { logFile :: FilePath + , toString :: a -> String + } + , handleLine :: a -> Effect Unit + } + -> Aff (Aff.Fiber (Either Error Unit)) +redirectLogging events { handleLine, storeLogs } = + Aff.forkAff $ tryAndLogErrors "redirectLogging" $ flip tailRecM unit \_ -> do + line <- waitForEvent events + liftEffect $ suppressAndLogErrors "redirectLogging: callback error" $ void + do + handleLine line + for storeLogs \{ logFile, toString } -> + Node.FS.appendTextFile UTF8 logFile $ toString line <> "\n" + pure $ Loop unit + +type ClusterConfig r = + ( ogmiosConfig :: ServerConfig + , kupoConfig :: ServerConfig + , hooks :: Hooks + | LogParams r + ) + +-- | TODO: Replace original log params with the row type +type LogParams r = + ( logLevel :: LogLevel + , customLogger :: Maybe (LogLevel -> Message -> Aff Unit) + , suppressLogs :: Boolean + | r + ) + +-- Similar to `Aff.bracket`, except cleanup is pushed onto a stack to be run +-- later. +cleanupBracket + :: forall (a :: Type) (b :: Type) + . Ref (Array (Aff Unit)) + -> Aff a + -> (a -> Aff Unit) + -> (a -> Aff b) + -> Aff b +cleanupBracket cleanupRef before after action = do + Aff.bracket + before + (\res -> liftEffect $ Ref.modify_ ([ after res ] <> _) cleanupRef) + action + +mkLogging + :: forall r + . Record (LogParams r) + -> Effect + { updatedConfig :: Record (LogParams r) + , logger :: Logger + , customLogger :: Maybe (LogLevel -> Message -> Aff Unit) + , printLogs :: Aff Unit + , clearLogs :: Aff Unit + } +mkLogging cfg + | cfg.suppressLogs = ado + -- if logs should be suppressed, setup the machinery and continue with + -- the bracket + { addLogEntry, suppressedLogger, printLogs, clearLogs } <- + setupLogs cfg.logLevel cfg.customLogger + let + configLogger = Just $ map liftEffect <<< addLogEntry + in + { updatedConfig: cfg { customLogger = configLogger } + , logger: suppressedLogger + , customLogger: configLogger + , printLogs: liftEffect printLogs + , clearLogs: liftEffect clearLogs + } + | otherwise = pure + -- otherwise, proceed with the env setup and provide a normal logger + { updatedConfig: cfg + , logger: mkLogger cfg.logLevel cfg.customLogger + , customLogger: cfg.customLogger + , printLogs: pure unit + , clearLogs: pure unit + } + +makeNaiveClusterContractEnv + :: forall r + . Record (ClusterConfig r) + -> Logger + -> Maybe (LogLevel -> Message -> Aff Unit) + -> Aff ContractEnv +makeNaiveClusterContractEnv cfg logger customLogger = do + usedTxOuts <- newUsedTxOuts + backend <- buildBackend logger $ mkCtlBackendParams + { ogmiosConfig: cfg.ogmiosConfig + , kupoConfig: cfg.kupoConfig + } + ledgerConstants <- getLedgerConstants + cfg { customLogger = customLogger } + backend + backendKnownTxs <- liftEffect $ Ref.new Set.empty + pure + { backend + , handle: mkQueryHandle cfg backend + , networkId: MainnetId + , logLevel: cfg.logLevel + , customLogger: customLogger + , suppressLogs: cfg.suppressLogs + , hooks: cfg.hooks + , wallet: Nothing + , usedTxOuts + , ledgerConstants + -- timeParams have no effect when KeyWallet is used + , timeParams: defaultTimeParams + , synchronizationParams: defaultSynchronizationParams + , knownTxs: { backend: backendKnownTxs } + } + +-- | Makes cluster ContractEnv with configured logs suppression and cleanup scheduled. +makeClusterContractEnv + :: forall r + . Ref (Array (Aff Unit)) + -> Record (ClusterConfig r) + -> Aff + { env :: ContractEnv + , clearLogs :: Aff Unit + , printLogs :: Aff Unit + } +makeClusterContractEnv cleanupRef cfg = do + { updatedConfig + , logger + , customLogger + , printLogs + , clearLogs + } <- liftEffect $ mkLogging cfg + cleanupBracket + cleanupRef + (makeNaiveClusterContractEnv updatedConfig logger customLogger) + stopContractEnv + $ pure + <<< { env: _, printLogs, clearLogs } + +-- | Kill a process and wait for it to stop listening on a specific port. +stopChildProcessWithPort :: UInt -> ManagedProcess -> Aff Unit +stopChildProcessWithPort port childProcess = do + stop childProcess + void $ recovering defaultRetryPolicy ([ \_ _ -> pure true ]) + \_ -> do + isAvailable <- isPortAvailable port + unless isAvailable do + liftEffect $ throw "retry" + +defaultRetryPolicy :: RetryPolicy +defaultRetryPolicy = limitRetriesByCumulativeDelay (Milliseconds 3000.00) $ + constantDelay (Milliseconds 100.0) + +-- replace with Effect.Console.log to debug. Not providing an option at runtime, +-- because it's just for the CTL developers. +log :: forall m. Monad m => String -> m Unit +log _ = pure unit diff --git a/src/Internal/Testnet/Types.purs b/src/Internal/Testnet/Types.purs new file mode 100644 index 0000000000..ea735e05c4 --- /dev/null +++ b/src/Internal/Testnet/Types.purs @@ -0,0 +1,182 @@ +module Ctl.Internal.Testnet.Types + ( CardanoTestnetStartupParams + , Era(Byron, Shelley, Allegra, Mary, Alonzo, Babbage, Conway) + , LoggingFormat(LogAsJson, LogAsText) + , TestnetPaths + , Event(Ready872, Finished, Failed, StartupFailed) + , StartupFailure(SpawnFailed, InitializationFailed) + , NodeLocation + , Node + , GenesisUtxoKeyLocation + , OptionalStartupParams + , TestnetRuntime + , TestnetClusterConfig + , TestnetConfig + , LogParams + , defaultOptionalStartupParams + , defaultStartupParams + ) where + +import Contract.Prelude + +import Contract.Config as Config +import Ctl.Internal.Contract.Hooks (Hooks) +import Ctl.Internal.ServerConfig (ServerConfig) +import Data.Log.Message (Message) +import Data.Time.Duration (Milliseconds, Seconds) +import Data.UInt (UInt) +import Node.Path (FilePath) +import Record as Record + +type TestnetConfig = + { logLevel :: LogLevel + -- Server configs are used to deploy the corresponding services: + , ogmiosConfig :: ServerConfig + , kupoConfig :: ServerConfig + , customLogger :: Maybe (LogLevel -> Message -> Aff Unit) + , suppressLogs :: Boolean + , hooks :: Hooks + , clusterConfig :: TestnetClusterConfig + } + +type TestnetClusterConfig = + { testnetMagic :: Int + , era :: Era + , slotLength :: Seconds + , epochSize :: Maybe UInt + -- FIXME: , maxTxSize :: Maybe UInt + -- FIXME: , raiseExUnitsToMax :: Boolean + } + +data Era + = Byron + | Shelley + | Allegra + | Mary + | Alonzo + | Babbage + | Conway + +data StartupFailure + = SpawnFailed + | InitializationFailed + +derive instance Eq StartupFailure +derive instance Generic StartupFailure _ +instance Show StartupFailure where + show = genericShow + +data Event + = Ready872 -- when cardano-testnet 8.7.2 is ready to go + | Finished + | Failed + | StartupFailed StartupFailure + +derive instance Eq Event +derive instance Generic Event _ +instance Show Event where + show = genericShow + +instance Show Era where + show = case _ of + Byron -> "byron-era" + Shelley -> "shelley-era" + Allegra -> "allegra-era" + Mary -> "mary-era" + Alonzo -> "alonzo-era" + Babbage -> "babbage-era" + Conway -> "conway-era" + +data LoggingFormat = LogAsJson | LogAsText + +instance Show LoggingFormat where + show = case _ of + LogAsJson -> "json" + LogAsText -> "text" + +type OptionalStartupParams r = + ( numPoolNodes :: Maybe Int + , era :: Maybe Era + , epochLength :: Maybe Milliseconds + , slotLength :: Maybe Seconds + , activeSlotsCoeff :: Maybe Number + , enableP2p :: Maybe Boolean + , nodeLoggingFormat :: Maybe LoggingFormat + | r + ) + +-- | Command line params for the cardano-testnet executable +type CardanoTestnetStartupParams r = + ( testnetMagic :: Int + | OptionalStartupParams r + ) + +defaultStartupParams + :: { testnetMagic :: Int } -> Record (CardanoTestnetStartupParams ()) +defaultStartupParams necessaryParams = + defaultOptionalStartupParams `Record.union` necessaryParams + +defaultOptionalStartupParams :: Record (OptionalStartupParams ()) +defaultOptionalStartupParams = + { numPoolNodes: Nothing + , era: Just Babbage + , epochLength: Nothing + , slotLength: Nothing + , activeSlotsCoeff: Nothing + , enableP2p: Nothing + , nodeLoggingFormat: Nothing + } + +type TestnetPaths = + { testnetDirectory :: FilePath + , genesisKeys :: Array { | GenesisUtxoKeyLocation () } + , nodeConfigPath :: FilePath + , nodeSocketPath :: FilePath + , nodeDirs :: Array { | NodeLocation () } + } + +type Node r = + ( socket :: FilePath + , port :: UInt + | NodeLocation r + ) + +type NodeLocation r = + ( idx :: Int + , name :: String + , workdir :: FilePath + | r + ) + +type GenesisUtxoKeyLocation r = + ( path :: FilePath + , idx :: Int + | r + ) + +{- +type TestnetClusterConfig r = + ( hooks :: Config.Hooks + | KupmiosConfig (LogParams r) + ) +-} + +type LogParams r = + ( logLevel :: LogLevel + , customLogger :: Maybe (LogLevel -> Config.Message -> Aff Unit) + , suppressLogs :: Boolean + | r + ) + +{- +type KupmiosConfig r = + ( kupoConfig :: Config.ServerConfig + , ogmiosConfig :: Config.ServerConfig + | r + ) +-} + +type TestnetRuntime r = + ( nodes :: Array { | Node () } + | r + ) diff --git a/src/Internal/Testnet/Utils.js b/src/Internal/Testnet/Utils.js new file mode 100644 index 0000000000..45bf58db68 --- /dev/null +++ b/src/Internal/Testnet/Utils.js @@ -0,0 +1,62 @@ +import os from "os"; + +try { + process.setMaxListeners(10000); +} catch (e) { + console.warn(e); +} + +export function tmpdir() { + return os.tmpdir(); +} + +export function setLineHandler(interf) { + return callback => () => { + const signal = "line"; + const cb = line => callback(line)(); + interf.on(signal, cb); + return { signal, callback: cb }; + }; +} +export function setErrorHandler(interfc) { + return callback => () => { + const signal = "error"; + const cb = err => callback(err)(); + interfc.on(signal, cb); + return { signal, callback: cb }; + }; +} +export function onExit(callback) { + const cb = exitcode => { + callback(exitcode)(); + }; + const signal = "exit"; + return () => { + process.on(signal, cb); + return { signal, callback }; + }; +} +export function onBeforeExit(callback) { + const signal = "beforeExit"; + return () => { + process.on(signal, callback); + return { signal, callback }; + }; +} +export function onUncaughtException(callback) { + const cb = error => { + callback(error)(); + }; + const signal = "uncaughtException"; + return () => { + process.on(signal, cb); + return { signal, callback }; + }; +} +export function setCloseHandler(readline) { + return callback => () => { + const signal = "close"; + readline.on(signal, callback); + return { signal, callback }; + }; +} diff --git a/src/Internal/Testnet/Utils.purs b/src/Internal/Testnet/Utils.purs new file mode 100644 index 0000000000..401191c03d --- /dev/null +++ b/src/Internal/Testnet/Utils.purs @@ -0,0 +1,615 @@ +module Ctl.Internal.Testnet.Utils + ( find811TestnetWorkir + , findNodeDirs + , EventSource(EventSource) + , onLine + , makeEventSource + , findTestnetPaths + , getNodePort + , getRuntime + , scheduleCleanup + , addCleanup + , tmpdir + , runCleanup + , tryAndLogErrors + , suppressAndLogErrors + , after + , is811TestnetDirectoryName + , onTestnetEvent + , parseEvent + , readNodes + , read872GenesisKey + , whenError + , waitFor + , waitForClose + , waitForError + , waitForEvent + , waitUntil + , waitForTestnet872Workdir + , cleanupOnExit + , annotateError + ) where + +import Contract.Prelude hiding (log) + +import Contract.Config as Contract.Config +import Contract.TextEnvelope + ( TextEnvelope(TextEnvelope) + , TextEnvelopeType(PaymentSigningKeyShelleyed25519) + , decodeTextEnvelope + ) +import Contract.Wallet.KeyFile (privatePaymentKeyFromTextEnvelope) +import Control.Alt ((<|>)) +import Control.Monad.Error.Class + ( class MonadError + , catchError + , liftMaybe + , throwError + ) +import Control.Monad.Except (lift, runExceptT) +import Control.Monad.Rec.Class (Step(Done, Loop), tailRecM) +import Control.Parallel (parallel, sequential) +import Ctl.Internal.Helpers ((<>)) +import Ctl.Internal.QueryM.UniqueId (uniqueId) +import Ctl.Internal.Spawn + ( ManagedProcess(ManagedProcess) + , OnSignalRef + , removeOnSignal + , waitForSignal + ) +import Ctl.Internal.Testnet.Types + ( Event(Ready872, Finished, StartupFailed) + , GenesisUtxoKeyLocation + , Node + , NodeLocation + , StartupFailure(InitializationFailed, SpawnFailed) + , TestnetPaths + , TestnetRuntime + ) +import Data.Array as Array +import Data.Int as Int +import Data.Map as Map +import Data.Posix.Signal (Signal(SIGINT)) +import Data.String (Pattern(Pattern)) +import Data.String as String +import Data.Time.Duration (Milliseconds) +import Data.UInt (UInt) +import Data.UInt as UInt +import Effect.Aff (try) +import Effect.Aff as Aff +import Effect.Class (class MonadEffect) +import Effect.Exception (Error, error, message) +import Effect.Random (randomInt) +import Effect.Ref (Ref) +import Effect.Ref as Ref +import Node.ChildProcess as Node.ChildProcess +import Node.Encoding (Encoding(UTF8)) +import Node.Encoding as Node.Encoding +import Node.FS.Sync as Node.FS +import Node.FS.Sync as Node.FS.Sync +import Node.Path (FilePath) +import Node.Process as Process +import Node.ReadLine as RL +import Node.Stream (Readable) + +-- | For cardano-node 8.1.1 +is811TestnetDirectoryName :: Int -> FilePath -> Boolean +is811TestnetDirectoryName n = + isJust <<< String.stripPrefix (Pattern $ "testnet-" <> show n <> "-test-") + +find811TestnetWorkir + :: { tmpdir :: FilePath, dirIdx :: Int } -> Effect (Maybe FilePath) +find811TestnetWorkir { tmpdir: tmpDir, dirIdx } = + map (tmpDir <> _) + <<< Array.find (is811TestnetDirectoryName dirIdx) + <$> Node.FS.readdir tmpDir + +waitForTestnet872Workdir + :: EventSource String -> { tmpdir :: FilePath } -> Aff { workdir :: FilePath } +waitForTestnet872Workdir src = map { workdir: _ } + <<< waitFor src + <<< parseTestnet872Workdir + +parseTestnet872Workdir :: { tmpdir :: FilePath } -> String -> Maybe FilePath +parseTestnet872Workdir { tmpdir: tmpDir } = String.stripPrefix + $ Pattern + $ " Workspace: " + <> tmpDir + <> "/" + +parseEvent :: String -> Maybe Event +parseEvent = case _ of + -- we can't know this way when 8.1.1 cardano-testnet is ready + " forAll109 =" -> Just Ready872 + "Usage: cardano-testnet cardano [--num-pool-nodes COUNT]" -> + Just $ StartupFailed SpawnFailed + "Failed to start testnet." -> + Just $ StartupFailed InitializationFailed + "Testnet is running. Type CTRL-C to exit." -> + Just Finished + _ -> Nothing + +waitFor :: forall a e. EventSource e -> (e -> Maybe a) -> Aff a +waitFor source f = flip tailRecM unit \_ -> do + event <- waitForEvent source + pure case f event of + Just a -> Done a + Nothing -> Loop unit + +onTestnetEvent :: EventSource String -> Effect (EventSource Event) +onTestnetEvent = narrowEventSource parseEvent + +getRuntime :: TestnetPaths -> Effect (Record (TestnetRuntime ())) +getRuntime paths = do + nodes <- readNodes paths + -- genesis <- readGenesis {workdir: paths.testnetDirectory} + pure { nodes {-, genesis-} } + +readNodes + :: forall r + . { nodeDirs :: Array { | NodeLocation () } + , testnetDirectory :: FilePath + | r + } + -> Effect (Array { | Node () }) +readNodes { nodeDirs, testnetDirectory } = do + for nodeDirs \{ idx, workdir, name } -> do + let + socketPath = testnetDirectory <> "socket" <> name + exists <- Node.FS.exists socketPath + unless exists + $ throwError + $ error + $ "Couldn't find node socket at " + <> socketPath + port <- getNodePort { nodeDir: workdir } + pure { idx, socket: socketPath, port, workdir, name } + +-- | Changes TextEnvelope type to match private payment key one and tries to read that. +readTextEnvelopeAsPaymentSkey + :: FilePath + -> Effect Contract.Config.PrivatePaymentKey +readTextEnvelopeAsPaymentSkey path = do + TextEnvelope envelope <- + liftMaybe (error "Cannot decode skey envelope") + <<< decodeTextEnvelope + =<< Node.FS.Sync.readTextFile Node.Encoding.UTF8 path + let + envelope' = TextEnvelope + (envelope { type_ = PaymentSigningKeyShelleyed25519 }) + liftMaybe (error "Cannot decode payment skey from decoded envelope") + $ privatePaymentKeyFromTextEnvelope envelope' + +parse872UtxoKeyFilename :: FilePath -> Either Error (Maybe { idx :: Int }) +parse872UtxoKeyFilename path = + traverse + ( map { idx: _ } + <<< note (error "Can't parse genesis key index") + <<< Int.fromString + ) + (String.stripPrefix (Pattern "utxo") path) + +read872GenesisKeyLocations + :: { workdir :: FilePath } + -> Effect (Array { | GenesisUtxoKeyLocation () }) +read872GenesisKeyLocations { workdir } = do + let keysDir = workdir <> "utxo-keys" + filenames <- Node.FS.readdir keysDir + map Array.catMaybes + $ liftEither + $ for filenames \filename -> + parse872UtxoKeyFilename filename <#> map \{ idx } -> + { idx + , path: keysDir <> filename <> "utxo.skey" + } + +read872GenesisKey + :: forall r + . { | GenesisUtxoKeyLocation r } + -> Effect Contract.Config.PrivatePaymentKey +read872GenesisKey = readTextEnvelopeAsPaymentSkey <<< _.path + +getNodePort :: { nodeDir :: FilePath } -> Effect UInt +getNodePort { nodeDir } = + liftMaybe (error $ "Failed to parse port at " <> nodeDir <> "/port") + <<< UInt.fromString + =<< Node.FS.readTextFile UTF8 (nodeDir <> "/port") + +findNodeDirs :: { workdir :: FilePath } -> Effect (Array { | NodeLocation () }) +findNodeDirs { workdir } = + Node.FS.readdir workdir <#> \subdirs -> + flip Array.mapMaybe subdirs \dirname -> do + idx <- Int.fromString =<< String.stripPrefix (Pattern "pools-keys/pool1") + dirname + pure { idx, workdir: workdir <> dirname, name: dirname } + +findTestnetPaths + :: { workdir :: FilePath } -> Effect (Either Error TestnetPaths) +findTestnetPaths { workdir } = runExceptT do + let + nodeConfigPath = workdir <> "configuration.yaml" + firstNode = "socket/pool1/sock" + nodeSocketPath = workdir <> firstNode + workdirExists <- lift $ Node.FS.exists workdir + configPathExists <- lift $ Node.FS.exists nodeConfigPath + socketPathExists <- lift $ Node.FS.exists nodeSocketPath + unless workdirExists do + throwError $ error $ + "cardano-testnet working directory not found." + unless configPathExists do + throwError $ error $ + "'configuration.yaml' not found in cardano-testnet working directory." + unless socketPathExists do + throwError $ error + $ firstNode + <> " not found in cardano-testnet working directory." + nodeDirs <- lift $ findNodeDirs { workdir } + genesisKeys <- lift $ read872GenesisKeyLocations { workdir } + pure + { testnetDirectory: workdir + , nodeConfigPath + , nodeSocketPath + , genesisKeys + , nodeDirs + } + +makeEventSource + :: forall a b c + . ( { handle :: Either Error a -> Effect Unit } + -> Effect { unsubscribe :: Effect Unit, outcome :: c } + ) + -> (a -> Maybe b) + -> Effect { eventSource :: EventSource b, outcome :: c } +makeEventSource subscribeOnEvents filter = annotateError "make event source" do + handlers <- Ref.new $ Map.fromFoldable [] + isCanceled <- Ref.new false + cancelRef <- Ref.new mempty + let + markCanceled = Ref.write true isCanceled + cancel error = Ref.read cancelRef >>= (_ $ error) + subscribe handler = do + Ref.read isCanceled >>= + if _ then + pure $ Left $ error "Event source is closed." + else do + id <- uniqueId "sub" + let unsubscribe = Ref.modify_ (Map.delete id) handlers + _ <- Ref.modify_ + (Map.insert id \event -> handler { unsubscribe, event }) + handlers + pure $ Right { unsubscribe } + + { unsubscribe, outcome } <- subscribeOnEvents + { handle: \ea -> case ea of + Left error -> cancel error + Right a -> case filter a of + Just b -> do + Ref.read handlers >>= traverse_ (_ $ Right b) + Nothing -> pure unit + } + flip Ref.write cancelRef \error -> do + Ref.write mempty cancelRef -- canceler may be called only once + unsubscribe + markCanceled + Ref.read handlers >>= traverse_ \cont -> + void $ suppressAndLogErrors "makeEventSource:cancel" $ cont $ Left error + Ref.write (Map.fromFoldable []) handlers + + pure + { eventSource: EventSource { cancel, subscribe } + , outcome + } + +addCleanup :: Ref (Array (Aff Unit)) -> Aff Unit -> Effect Unit +addCleanup = map void <<< flip + (Ref.modify <<< Array.cons <<< suppressAndLogErrors "[addCleanup][error]: ") + +scheduleCleanup + :: forall a + . Ref (Array (Aff Unit)) + -> Aff a + -> (a -> Aff Unit) + -> Aff a +scheduleCleanup cleanupRef create cleanup = + after create $ liftEffect <<< addCleanup cleanupRef <<< cleanup + +-- Similar to `catchError` but preserves the error +whenError :: forall (a :: Type). Aff Unit -> Aff a -> Aff a +whenError whenErrorAction action = do + res <- try action + when (isLeft res) whenErrorAction + liftEither res + +-- | Just as a bracket but without the body. +after :: forall a. Aff a -> (a -> Aff Unit) -> Aff a +after first second = Aff.bracket first second pure + +-- | Create an event source based on another event source, but +-- with smaller variety of events. +narrowEventSource + :: forall a b + . (a -> Maybe b) + -> EventSource a + -> Effect (EventSource b) +narrowEventSource filter (EventSource source) = annotateError + "narrowEventSource" + do + { eventSource: new + , outcome: subscriptionResult -- this goes from the source + } <- flip makeEventSource filter \{ handle } -> + do -- this is how new event source subscribe on the source + source.subscribe (handle <<< _.event) >>= case _ of + Left err -> pure + { outcome: Left err -- this is not for makeEventSource + , unsubscribe: pure unit -- how do 'new' unsubscribe from the 'source' + } + Right { unsubscribe: unsubFromSource } -> pure + { outcome: Right unit -- this is not for makeEventSource + , unsubscribe: unsubFromSource -- how do 'new' unsubscribe from the 'source' + } + liftEither subscriptionResult + pure new + +-- TODO: remove this function when PS bindings for os.tmpdir are available. +-- https://github.com/Plutonomicon/cardano-transaction-lib/issues/726 +foreign import tmpdir :: Effect String + +foreign import setLineHandler + :: RL.Interface -> (String -> Effect Unit) -> Effect OnSignalRef + +foreign import setCloseHandler + :: RL.Interface -> Effect Unit -> Effect OnSignalRef + +foreign import setErrorHandler + :: RL.Interface -> (Error -> Effect Unit) -> Effect OnSignalRef + +foreign import onBeforeExit + :: Effect Unit -> Effect OnSignalRef + +foreign import onExit + :: (Int -> Effect Unit) -> Effect OnSignalRef + +foreign import onUncaughtException + :: (Error -> Effect Unit) -> Effect OnSignalRef + +suppressAndLogErrors + :: forall m. MonadEffect m => MonadError Error m => String -> m Unit -> m Unit +suppressAndLogErrors location = flip catchError $ message + >>> append ("An error occured and suppressed at " <> location <> ": ") + >>> log + +-- replace with Effect.Console.log to debug. Not providing an option at runtime, +-- because it's just for the CTL developers. +log :: forall m. Monad m => String -> m Unit +log _ = pure unit + +newtype EventSource b = EventSource + { subscribe :: + ( { unsubscribe :: Effect Unit + , event :: Either Error b + } + -> Effect Unit + ) + -> Effect (Either Error { unsubscribe :: Effect Unit }) + , cancel :: Error -> Effect Unit + } + +-- | Waits for any event. Note, if the event source throws an async error, any joining process dies. +waitForEvent :: forall a. EventSource a -> Aff a +waitForEvent (EventSource { subscribe }) = annotateError "waitForEvent" $ + Aff.makeAff \cont -> do + subscriptionResult <- subscribe \{ unsubscribe, event } -> do + unsubscribe + cont event + case subscriptionResult of + Right { unsubscribe } -> pure $ Aff.Canceler \err -> liftEffect do + unsubscribe + cont $ Left $ appendErrorMessage "waitForEvent:canceled" err + Left subError -> do + suppressAndLogErrors "waitForEvent:badSubscription" + $ cont + $ Left + $ appendErrorMessage "Failed to subscribe" subError + pure Aff.nonCanceler + +onLine + :: forall a b + . Readable a + -> (String -> Maybe b) + -> Effect (EventSource b) +onLine readable = + map _.eventSource <<< makeEventSource \{ handle: mainHandler } -> do + interface <- RL.createInterface readable mempty + handlers <- Ref.new [] + lineHandler <- setLineHandler interface \x -> do + void + $ suppressAndLogErrors "onLine:setLineHandler" + $ mainHandler + $ Right x + let + cancel = \err -> do + Ref.read handlers >>= traverse_ (try <<< removeOnSignal) + void + $ suppressAndLogErrors "onLine:cancel" + $ mainHandler + $ Left err + closeHandler <- setCloseHandler interface + $ cancel + $ error "Line event source has been closed." + errorHandler <- setErrorHandler interface cancel + Ref.write [ lineHandler, closeHandler, errorHandler ] handlers + pure + { outcome: unit + , unsubscribe: do + cancel $ error "Unsubscribed from line event." + } + +-- | Waits until processe's stdout closes. +-- Assuming this means that process is closed as well. +waitForClose :: ManagedProcess -> Aff Unit +waitForClose (ManagedProcess _ child _) = do + interface <- liftEffect + $ flip RL.createInterface mempty + $ Node.ChildProcess.stdout child + Aff.makeAff \cont -> do + { cancel } <- withOneShotHandler \{ justOnce } -> + setCloseHandler interface $ justOnce $ cont $ Right unit + pure $ Aff.Canceler \err -> liftEffect do + cancel + cont $ Left $ appendErrorMessage "waitForClose has been canceled" err + +waitUntil :: forall a. Milliseconds -> Aff (Maybe a) -> Aff a +waitUntil checkingInterval fa = flip tailRecM unit \_ -> + fa >>= case _ of + Nothing -> do + Aff.delay checkingInterval + pure $ Loop unit + Just x -> pure $ Done x + +-- | Waits until processe's stdout closes. +-- Assuming this means that process is closed as well. +waitForError :: ManagedProcess -> Aff Error +waitForError (ManagedProcess _ child _) = do + interface <- liftEffect + $ flip RL.createInterface mempty + $ Node.ChildProcess.stdout child + Aff.makeAff \cont -> do + { cancel } <- withOneShotHandler \{ justOnce } -> + setErrorHandler interface \err -> justOnce $ cont $ Right err + pure $ Aff.Canceler \err -> liftEffect do + cancel + cont $ Left $ appendErrorMessage "waitForClose has been canceled" err + +-- | Specifically for nodejs handlers: +-- Makes sure that the callback is called at most once, and unregistering it +-- on cancelation and on the first call. +withOneShotHandler + :: ({ justOnce :: Effect Unit -> Effect Unit } -> Effect OnSignalRef) + -> Effect { cancel :: Effect Unit } +withOneShotHandler with = do + removeHandler <- Ref.new mempty + isClosedRef <- Ref.new false + let + cancel = do + join $ Ref.read removeHandler + Ref.write true isClosedRef + handle <- with + { justOnce: \oneShotHandler -> do + -- otherwise it may be triggered multiple times, for unknown reason + Ref.read isClosedRef >>= flip unless do + cancel + oneShotHandler + } + Ref.write (removeOnSignal handle) removeHandler + pure { cancel } + +waitForBeforeExit :: Aff Unit +waitForBeforeExit = Aff.makeAff \cont -> do + { cancel } <- withOneShotHandler \{ justOnce } -> onBeforeExit $ justOnce do + log "ON BEFORE EXIT" + cont $ Right unit + pure $ Aff.Canceler \err -> liftEffect do + cancel + suppressAndLogErrors "waitForBeforeExit" $ cont $ Left err + +waitForUncaughtException :: Aff Error +waitForUncaughtException = Aff.makeAff \cont -> do + n <- randomInt 0 100 + { cancel } <- withOneShotHandler \{ justOnce } -> + onUncaughtException \err -> justOnce do + log $ "ON UNCAUGHT EXCEPTION " <> show n + cont $ Right err + pure $ Aff.Canceler \err -> liftEffect do + cancel + suppressAndLogErrors "waitForUncaughtException" $ cont $ Left err + +waitForExit :: Aff Int +waitForExit = Aff.makeAff \cont -> do + { cancel } <- withOneShotHandler \{ justOnce } -> onExit \exitcode -> justOnce + do + cont $ Right exitcode + pure $ Aff.Canceler \err -> liftEffect do + cancel + suppressAndLogErrors "waitForExit" $ cont $ Left err + +tryAndLogErrors + :: forall a m + . MonadEffect m + => MonadError Error m + => String + -> m a + -> m (Either Error a) +tryAndLogErrors location = try >=> case _ of + Left err -> do + log $ "An error occured and suppressed at " <> location <> ": " <> message + err + pure $ Left err + Right a -> pure $ Right a + +runCleanup :: Ref (Array (Aff Unit)) -> Aff Unit +runCleanup cleanupRef = do + log "Cleaning up" + cleanups <- liftEffect do + cleanups <- Ref.read cleanupRef + Ref.write [] cleanupRef + pure cleanups + if null cleanups then log "No cleanup needed" + else do + sequence_ $ suppressAndLogErrors "runCleanup" <$> cleanups + log "Cleanup finished" + +cleanupOnExit + :: Ref (Array (Aff Unit)) + -> Aff { fiber :: Aff.Fiber Unit } +cleanupOnExit cleanupRef = do + log "Cleanup scheduled" + let + handle handlers = do + handler <- sequential do + ( handlers.onExit + <$> parallel waitForExit + ) + <|> + ( handlers.onUncaughtException + <$> parallel waitForUncaughtException + ) + <|> + ( handlers.onBeforeExit + <$ parallel waitForBeforeExit + ) + <|> + ( handlers.onWaitForSignal + <$ parallel (waitForSignal SIGINT) + ) + handler + cleanup triggeredBy = do + log $ "Running cleanup on " <> triggeredBy + runCleanup cleanupRef + + fiber <- Aff.forkAff $ handle + { onExit: \code -> cleanup $ "exit with " <> show code + , onUncaughtException: \err -> do + cleanup "uncaught exception" + log $ "Failing irrecoverably after the cleanup after error: " <> show + err + liftEffect $ Process.exit 7 -- Failing irrecoverably + , onBeforeExit: cleanup "before exit" + , onWaitForSignal: cleanup "SIGINT" + } + pure { fiber } + +annotateError + :: forall (a :: Type) m + . MonadError Error m + => String + -> m a + -> m a +annotateError withPrefix action = + catchError action $ throwError <<< appendErrorMessage withPrefix + +appendErrorMessage + :: String + -> Error + -> Error +appendErrorMessage withPrefix = + error <<< append (withPrefix <> ": ") <<< message diff --git a/src/Internal/ToData.purs b/src/Internal/ToData.purs deleted file mode 100644 index b1799f0d17..0000000000 --- a/src/Internal/ToData.purs +++ /dev/null @@ -1,343 +0,0 @@ -module Ctl.Internal.ToData - ( class ToData - , class ToDataArgs - , class ToDataWithSchema - , class ToDataArgsRL - , class ToDataArgsRLHelper - , genericToData - , toDataArgsRec - , toDataArgsRec' - , toData - , toDataArgs - , toDataWithSchema - ) where - -import Prelude - -import Contract.Crypto.Secp256k1 (Secp256k1PrivateKey) -import Ctl.Internal.Helpers (uIntToBigInt) -import Ctl.Internal.Plutus.Types.DataSchema - ( class HasPlutusSchema - , class ValidPlutusSchema - ) -import Ctl.Internal.TypeLevel.Nat (class KnownNat, natVal) -import Ctl.Internal.TypeLevel.RowList.Unordered.Indexed - ( class GetIndexWithLabel - , class GetLabelIndex - , class GetWithLabel - ) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum (fromInt, one, toBigInt, zero) as BigNum -import Ctl.Internal.Types.ByteArray (ByteArray(ByteArray)) -import Ctl.Internal.Types.CborBytes (CborBytes) -import Ctl.Internal.Types.PlutusData (PlutusData(Constr, Integer, List, Bytes)) -import Ctl.Internal.Types.RawBytes (RawBytes) -import Data.Array (cons, sortWith) -import Data.Array as Array -import Data.ArrayBuffer.Types (Uint8Array) -import Data.Either (Either(Left, Right)) -import Data.Foldable (class Foldable) -import Data.Generic.Rep as G -import Data.List (List) -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (unwrap) -import Data.NonEmpty (NonEmpty) -import Data.Ratio (Ratio, denominator, numerator) -import Data.Symbol (class IsSymbol) -import Data.TextEncoder (encodeUtf8) -import Data.Tuple (Tuple(Tuple), fst, snd) -import Data.UInt (UInt) -import JS.BigInt (BigInt) -import JS.BigInt as BigInt -import Noble.Secp256k1.ECDSA - ( ECDSAPublicKey - , ECDSASignature - , MessageHash - , unECDSAPublicKey - , unMessageHash - , unPrivateKey - ) -import Noble.Secp256k1.Schnorr - ( SchnorrPublicKey - , SchnorrSignature - , unSchnorrPublicKey - ) -import Prim.Row as Row -import Prim.TypeError (class Fail, Text) -import Record as Record -import Type.Proxy (Proxy(Proxy)) -import Type.RowList as RL - --- | Classes - -class ToData :: Type -> Constraint -class ToData a where - toData :: a -> PlutusData - --- | A class which converts a type to its PlutusData representation with the help of a --- |generated or user-defined Plutus Data Schema (see TypeLevel.DataSchema.purs). --- |We cannot express the constraint that the first type argument have an instance of --- |@HasPlutusSchema@ with a superclass, but in practice every instance of this class will have an instance of --- |that class as well. -class ToDataWithSchema :: Type -> Type -> Constraint -class ToDataWithSchema t a where - toDataWithSchema :: Proxy t -> a -> PlutusData - --- | As explained in https://harry.garrood.me/blog/write-your-own-generics/ this --- | is just a neat pattern that flattens a skewed Product of Products -class ToDataArgs :: Type -> Symbol -> Type -> Constraint -class IsSymbol constr <= ToDataArgs t constr a where - toDataArgs :: Proxy t -> Proxy constr -> a -> Array (PlutusData) - --- | A helper typeclass to implement `ToDataArgs` for records. --- | Adapted from https://github.com/purescript/purescript-quickcheck/blob/v7.1.0/src/Test/QuickCheck/Arbitrary.purs#L247 --- | --- | The Symbol argument represents the name of a constructor. To account for Sum types where multiple variants of the sum have --- | records with the same name, we have to know the name of the constructor (at the type level). See TypeLevel.DataSchema for a --- | more in depth explanation. -class ToDataArgsRL - :: forall (k :: Type) - . Type - -> Symbol - -> RL.RowList k - -> Row Type - -> Constraint -class - ToDataArgsRLHelper t constr list row <= - ToDataArgsRL t constr list row - | t constr list -> row where - toDataArgsRec - :: Proxy t - -> Proxy constr - -> Proxy list - -> Record row - -> Array PlutusData - -instance ToDataArgsRLHelper t constr list row => ToDataArgsRL t constr list row where - toDataArgsRec proxy constr list rec = map snd <<< sortWith fst $ - toDataArgsRec' proxy constr list rec - --- | A helper class used to implement ToDataArgsRL. This mainly exists for performance / ergonomic reasons; --- | specifically, it allows us to only sort once (and not have to worry about maintaing the correct order as we go, --- | which reduces the potential for errors) -class ToDataArgsRLHelper - :: forall (k :: Type) - . Type - -> Symbol - -> RL.RowList k - -> Row Type - -> Constraint -class ToDataArgsRLHelper t constr list row | t constr list -> row where - toDataArgsRec' - :: Proxy t - -> Proxy constr - -> Proxy list - -> Record row - -> Array (Tuple Int PlutusData) - --- | ToDataWithIndex instances for Data.Generic.Rep - -instance - ( ToDataWithSchema t l - , ToDataWithSchema t r - ) => - ToDataWithSchema t (G.Sum l r) where - toDataWithSchema p (G.Inl x) = toDataWithSchema p x - toDataWithSchema p (G.Inr x) = toDataWithSchema p x - --- the following inline comments explain the "type level prolog" at work -instance - ( -- 'constr' is the type variable which represents the type-level symbol corresponding to the name of a constructor. It must be known at compile time. - IsSymbol constr - -- Since this is an instance for constructors with arguments, we must ensure that the arguments can be converted to Plutus Data with the provided constr name - , ToDataArgs t constr arg - -- The type must have an associated Plutus Data Schema, else we can't derive the index (which we need to get ahold of with natVal in the body of the method) - , HasPlutusSchema t schema - -- The plutus schema must be valid, i.e., have no duplicate labels or indices at each level. Otherwise 'GetIndexWithLabel' might return the wrong result - , ValidPlutusSchema schema list - -- 'index' represents the type level Nat index of the field with the constr label. - , GetIndexWithLabel constr list index - -- If that index isn't known, we can't reflect it - , KnownNat index - ) => - ToDataWithSchema t (G.Constructor constr arg) where - toDataWithSchema p (G.Constructor args) = Constr - (BigNum.fromInt <<< natVal $ (Proxy :: Proxy index)) - (toDataArgs p (Proxy :: Proxy constr) args) - --- | ToDataArgs instances for Data.Generic.Rep - -instance IsSymbol constr => ToDataArgs a constr G.NoArguments where - toDataArgs _ _ _ = [] - -instance - ( ToDataArgs t constr (Record row) - ) => - ToDataArgs t constr (G.Argument (Record row)) where - toDataArgs proxy constr (G.Argument r) = toDataArgs proxy constr r -else instance (ToData a, IsSymbol constr) => ToDataArgs x constr (G.Argument a) where - toDataArgs _ _ (G.Argument x) = [ toData x ] - -instance - ( IsSymbol constr - , ToDataArgsRL t constr list row - , RL.RowToList row list - ) => - ToDataArgs t constr (Record row) where - toDataArgs proxy constr rec = toDataArgsRec proxy constr (Proxy :: Proxy list) - rec - -instance - ( ToDataArgs x constr a - , ToDataArgs x constr b - ) => - ToDataArgs x constr (G.Product a b) where - toDataArgs proxy constr (G.Product x y) = toDataArgs proxy constr x <> - toDataArgs proxy constr y - --- | ToDataArgsRL instances - -instance ToDataArgsRLHelper t symbol RL.Nil () where - toDataArgsRec' _ _ _ _ = [] -else instance - ( -- The element of the Row we are inspecting must be convertible to Plutus Data - ToData a - -- The tail of the RowList we are inspecting must be convertible to Plutus Data (with the current constructor name) - , ToDataArgsRLHelper t constr listRest rowRest - -- Row.Lacks and Row.Cons are just the constraints required to use Record.Get - , Row.Lacks label rowRest - , Row.Cons label a rowRest rowFull - , RL.RowToList rowFull (RL.Cons label a listRest) - -- 'label' is a type variable which represents the Symbol label of a *record entry* - , IsSymbol label - -- As in the rest of this module, 'constr' stands for the name of the constructor which has a Record argument that we are inspecting - , IsSymbol constr - -- The type 't' is the "parent type" which has a constructor ('constr') that takes a Record argument - , HasPlutusSchema t schema - -- The schema must be valid (see above), and if it is we get the corresponding RList ('rList') - , ValidPlutusSchema schema rList - -- The RList corresponding to the schema must have a Record argument at the given constructor - , GetWithLabel constr rList rec - -- That record at the given constructor must have a field at the given label, and that field has a Nat index - , GetLabelIndex label rec n - -- we have to be able to reflect the nat index of the record entry located at 'label' - , KnownNat n - ) => - ToDataArgsRLHelper t constr (RL.Cons label a listRest) rowFull where - toDataArgsRec' _ constr _ x = - let - keyProxy = (Proxy :: Proxy label) - - ix = natVal (Proxy :: Proxy n) - - field :: a - field = Record.get keyProxy x - in - Tuple ix (toData field) `cons` toDataArgsRec' (Proxy :: Proxy t) constr - (Proxy :: Proxy listRest) - (Record.delete keyProxy x) - -genericToData - :: forall (t :: Type) (rep :: Type) - . G.Generic t rep - => ToDataWithSchema t rep - => t - -> PlutusData -genericToData = toDataWithSchema (Proxy :: Proxy t) <<< G.from - --- | Base ToData instances - -instance ToData Void where - toData = absurd - -instance ToData Unit where - toData _ = Constr BigNum.zero [] - --- NOTE: For the sake of compatibility the following toDatas have to match --- https://github.com/input-output-hk/plutus/blob/1f31e640e8a258185db01fa899da63f9018c0e85/plutus-tx/src/PlutusTx/IsData/Instances.hs -instance ToData Boolean where - toData false = Constr BigNum.zero [] - toData true = Constr BigNum.one [] - -instance ToData a => ToData (Maybe a) where - toData (Just x) = Constr BigNum.zero [ toData x ] -- Just is zero-indexed by Plutus - toData Nothing = Constr BigNum.one [] - -instance (ToData a, ToData b) => ToData (Either a b) where - toData (Left e) = Constr BigNum.zero [ toData e ] - toData (Right x) = Constr BigNum.one [ toData x ] - -instance Fail (Text "Int is not supported, use BigInt instead") => ToData Int where - toData = toData <<< BigInt.fromInt - -instance ToData BigInt where - toData = Integer - -instance ToData BigNum where - toData = toData <<< BigNum.toBigInt - -instance ToData UInt where - toData = toData <<< uIntToBigInt - -instance ToData a => ToData (Array a) where - toData = List <<< map toData - -instance (Foldable f, ToData a) => ToData (NonEmpty f a) where - toData = foldableToPlutusData - -instance ToData a => ToData (List a) where - toData = foldableToPlutusData - -instance (ToData a, ToData b) => ToData (Tuple a b) where - toData (Tuple a b) = Constr BigNum.zero [ toData a, toData b ] - --- Note that nothing prevents the denominator from being zero, we could provide --- safety here: -instance ToData a => ToData (Ratio a) where - toData ratio = List [ toData (numerator ratio), toData (denominator ratio) ] - -instance ToData ByteArray where - toData = Bytes - -instance ToData CborBytes where - toData = Bytes <<< unwrap - -instance ToData RawBytes where - toData = Bytes <<< unwrap - -instance ToData String where - toData = toData <<< ByteArray <<< encodeUtf8 - -instance ToData PlutusData where - toData = identity - -instance ToData Uint8Array where - toData = toData <<< ByteArray - --- Instances for purescript-noble-secp256k1 types - -instance ToData Secp256k1PrivateKey where - toData = unwrap >>> unPrivateKey >>> ByteArray >>> toData - -instance ToData MessageHash where - toData = unMessageHash >>> ByteArray >>> toData - -instance ToData ECDSAPublicKey where - toData = unECDSAPublicKey >>> ByteArray >>> toData - -instance ToData ECDSASignature where - toData = unwrap >>> ByteArray >>> toData - -instance ToData SchnorrPublicKey where - toData = unSchnorrPublicKey >>> ByteArray >>> toData - -instance ToData SchnorrSignature where - toData = unwrap >>> ByteArray >>> toData - -foldableToPlutusData - :: forall (a :: Type) (t :: Type -> Type) - . Foldable t - => ToData a - => t a - -> PlutusData -foldableToPlutusData = Array.fromFoldable >>> map toData >>> List diff --git a/src/Internal/Transaction.purs b/src/Internal/Transaction.purs index 49baa289ca..e01acd09bc 100644 --- a/src/Internal/Transaction.purs +++ b/src/Internal/Transaction.purs @@ -1,6 +1,6 @@ +-- TODO: consider moving these utils closer to where they are used module Ctl.Internal.Transaction ( attachDatum - , attachRedeemer , attachPlutusScript , attachNativeScript , setScriptDataHash @@ -8,37 +8,45 @@ module Ctl.Internal.Transaction import Prelude -import Ctl.Internal.Cardano.Types.NativeScript (NativeScript) -import Ctl.Internal.Cardano.Types.Transaction - ( Costmdls - , Redeemer - , ScriptDataHash(ScriptDataHash) - , Transaction(Transaction) - , TransactionWitnessSet(TransactionWitnessSet) - , TxBody(TxBody) +import Cardano.Serialization.Lib + ( hashScriptData + , packListContainer + , packMapContainer ) -import Ctl.Internal.Deserialization.WitnessSet as Deserialization.WitnessSet -import Ctl.Internal.Serialization (hashScriptData, toBytes) -import Ctl.Internal.Serialization.PlutusData as Serialization.PlutusData -import Ctl.Internal.Serialization.PlutusScript as Serialization.PlutusScript -import Ctl.Internal.Serialization.Types as Serialization -import Ctl.Internal.Serialization.WitnessSet as Serialization.WitnessSet -import Ctl.Internal.Types.Datum (Datum) -import Ctl.Internal.Types.Scripts (PlutusScript) +import Cardano.Types.CostModel (CostModel) +import Cardano.Types.CostModel as CostModel +import Cardano.Types.Language (Language) +import Cardano.Types.Language as Language +import Cardano.Types.NativeScript (NativeScript) +import Cardano.Types.PlutusData (PlutusData) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.PlutusScript (PlutusScript) +import Cardano.Types.Redeemer (Redeemer) +import Cardano.Types.Redeemer as Redeemer +import Cardano.Types.ScriptDataHash (ScriptDataHash(ScriptDataHash)) +import Cardano.Types.Transaction (Transaction(Transaction)) +import Cardano.Types.TransactionBody (TransactionBody(TransactionBody)) +import Cardano.Types.TransactionWitnessSet + ( TransactionWitnessSet(TransactionWitnessSet) + ) +import Data.Array (nub) import Data.Array as Array import Data.Foldable (null) +import Data.Map (Map) +import Data.Map as Map import Data.Maybe (Maybe(Just)) import Data.Newtype (over, unwrap) -import Data.Traversable (traverse) +import Data.Profunctor.Strong ((***)) import Effect (Effect) -import Effect.Class (liftEffect) +import Literals.Undefined (undefined) +import Unsafe.Coerce (unsafeCoerce) -- | Set the `Transaction` body's script data hash. NOTE: Must include *all* of -- | the datums and redeemers for the given transaction setScriptDataHash - :: Costmdls + :: Map Language CostModel -> Array Redeemer - -> Array Datum + -> Array PlutusData -> Transaction -> Effect Transaction setScriptDataHash costModels rs ds tx@(Transaction { body, witnessSet }) @@ -49,80 +57,72 @@ setScriptDataHash costModels rs ds tx@(Transaction { body, witnessSet }) -- * there are no datums -- | null (unwrap witnessSet).plutusScripts + , null (unwrap witnessSet).plutusData , null rs , null ds = pure tx | otherwise = do - scriptDataHash <- ScriptDataHash <<< unwrap <<< toBytes - <$> hashScriptData costModels rs (unwrap <$> ds) + let + costMdlsCsl = + packMapContainer $ map (Language.toCsl *** CostModel.toCsl) $ + Map.toUnfoldable costModels + redeemersCsl = + packListContainer $ Redeemer.toCsl <$> rs + datumsCsl = + if Array.null ds + -- This is a hack. The datums argument is optional and is + -- supposed to not be provided if there are no datums. + -- TODO: fix upstream + then unsafeCoerce undefined + else packListContainer $ PlutusData.toCsl <$> ds + scriptDataHash = + ScriptDataHash $ hashScriptData redeemersCsl costMdlsCsl datumsCsl pure $ over Transaction _ - { body = over TxBody _ { scriptDataHash = Just scriptDataHash } body + { body = over TransactionBody + _ { scriptDataHash = Just scriptDataHash } + body } tx -- | Attach a `Datum` to a transaction by modifying its existing witness set. -- | Fails if either the datum or updated witness set cannot be converted during -- | (de-)serialization -attachDatum :: Datum -> Transaction -> Effect Transaction -attachDatum d = attachDatums (Array.singleton d) +attachDatum :: PlutusData -> Transaction -> Transaction +attachDatum d = attachDatums [ d ] attachDatums - :: Array Datum -> Transaction -> Effect Transaction -attachDatums [] tx = pure tx -attachDatums datums tx@(Transaction { witnessSet: ws }) = do - let ds = map (Serialization.PlutusData.convertPlutusData <<< unwrap) datums - updateTxWithWitnesses tx - <$> convertWitnessesWith ws (Serialization.WitnessSet.setPlutusData ds) - --- | Attach a `Redeemer` to a transaction by modifying its existing witness set. --- | Note that this is the `Types.Transaction` representation of a redeemer and --- | not a wrapped `PlutusData`. --- --- | Fails if either the redeemer or updated witness set cannot be converted --- | during (de-)serialization -attachRedeemer - :: Redeemer -> Transaction -> Effect Transaction -attachRedeemer r = attachRedeemers (Array.singleton r) - -attachRedeemers - :: Array Redeemer -> Transaction -> Effect Transaction -attachRedeemers rs tx@(Transaction { witnessSet: ws }) = do - rs' <- liftEffect $ traverse Serialization.WitnessSet.convertRedeemer rs - updateTxWithWitnesses tx - <$> convertWitnessesWith ws (Serialization.WitnessSet.setRedeemers rs') + :: Array PlutusData -> Transaction -> Transaction +attachDatums [] tx = tx +attachDatums datums tx@(Transaction { witnessSet: TransactionWitnessSet ws }) = + do + updateTxWithWitnesses tx $ TransactionWitnessSet $ ws + { plutusData = nub $ ws.plutusData <> datums } -- | Attach a `PlutusScript` to a transaction by modifying its existing witness -- | set --- | --- | Fails if either the script or updated witness set cannot be converted --- | during (de-)serialization attachPlutusScript - :: PlutusScript -> Transaction -> Effect Transaction -attachPlutusScript ps = attachPlutusScripts (Array.singleton ps) + :: PlutusScript -> Transaction -> Transaction +attachPlutusScript ps = attachPlutusScripts [ ps ] attachPlutusScripts :: Array PlutusScript -> Transaction - -> Effect Transaction -attachPlutusScripts ps tx@(Transaction { witnessSet: ws }) = do - let ps' = ps # map Serialization.PlutusScript.convertPlutusScript - updateTxWithWitnesses tx - <$> convertWitnessesWith ws (Serialization.WitnessSet.setPlutusScripts ps') + -> Transaction +attachPlutusScripts ps tx@(Transaction { witnessSet: TransactionWitnessSet ws }) = + do + updateTxWithWitnesses tx + $ TransactionWitnessSet + $ ws { plutusScripts = nub $ ws.plutusScripts <> ps } +-- | Attach a `NativeScript` to a transaction by modifying its existing witness +-- | set attachNativeScript :: NativeScript -> Transaction -> Transaction -attachNativeScript ns tx = do - updateTxWithWitnesses tx $ - mempty # over TransactionWitnessSet _ { nativeScripts = Just [ ns ] } - -convertWitnessesWith - :: TransactionWitnessSet - -> (Serialization.TransactionWitnessSet -> Effect Unit) - -> Effect TransactionWitnessSet -convertWitnessesWith ws act = do - ws' <- liftEffect $ Serialization.WitnessSet.convertWitnessSet ws - liftEffect $ act ws' - pure $ Deserialization.WitnessSet.convertWitnessSet ws' +attachNativeScript ns tx@(Transaction { witnessSet: TransactionWitnessSet ws }) = + do + updateTxWithWitnesses tx + $ TransactionWitnessSet + $ ws { nativeScripts = nub $ ws.nativeScripts <> [ ns ] } updateTxWithWitnesses :: Transaction diff --git a/src/Internal/TxOutput.purs b/src/Internal/TxOutput.purs index 8bbbb10203..2806f1be05 100644 --- a/src/Internal/TxOutput.purs +++ b/src/Internal/TxOutput.purs @@ -9,27 +9,25 @@ module Ctl.Internal.TxOutput import Prelude -import Control.Alt ((<|>)) -import Control.Alternative (guard) -import Ctl.Internal.Address (addressToOgmiosAddress, ogmiosAddressToAddress) -import Ctl.Internal.Cardano.Types.Transaction - ( TransactionOutput(TransactionOutput) - ) as Transaction -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.Deserialization.PlutusData as Deserialization -import Ctl.Internal.QueryM.Ogmios as Ogmios -import Ctl.Internal.Serialization (toBytes) -import Ctl.Internal.Serialization.PlutusData as Serialization -import Ctl.Internal.Types.ByteArray (byteArrayToHex, hexToByteArray) -import Ctl.Internal.Types.CborBytes (hexToCborBytes) -import Ctl.Internal.Types.Datum (DataHash, Datum(Datum)) -import Ctl.Internal.Types.OutputDatum - ( OutputDatum(OutputDatum, OutputDatumHash, NoOutputDatum) +import Cardano.AsCbor (decodeCbor, encodeCbor) +import Cardano.Serialization.Lib (fromBytes, toBytes) +import Cardano.Types + ( DataHash + , PlutusData + , TransactionInput(TransactionInput) + ) +import Cardano.Types.Address as Address +import Cardano.Types.OutputDatum + ( OutputDatum(OutputDatumHash, OutputDatum) , outputDatumDataHash , outputDatumDatum ) -import Ctl.Internal.Types.Transaction (TransactionInput(TransactionInput)) as Transaction -import Data.Maybe (Maybe(Just), fromMaybe, isNothing) +import Cardano.Types.TransactionOutput (TransactionOutput(TransactionOutput)) +import Control.Alt ((<|>)) +import Control.Alternative (guard) +import Ctl.Internal.QueryM.Ogmios as Ogmios +import Data.ByteArray (byteArrayToHex, hexToByteArray) +import Data.Maybe (Maybe, isNothing) import Data.Newtype (unwrap, wrap) import Data.Traversable (traverse) @@ -41,9 +39,9 @@ import Data.Traversable (traverse) -- I think txId is a hexadecimal encoding. -- | Converts an Ogmios transaction input to (internal) `TransactionInput` txOutRefToTransactionInput - :: Ogmios.OgmiosTxOutRef -> Maybe Transaction.TransactionInput + :: Ogmios.OgmiosTxOutRef -> Maybe TransactionInput txOutRefToTransactionInput { txId, index } = do - transactionId <- hexToByteArray txId <#> wrap + transactionId <- hexToByteArray txId >>= fromBytes >>> map wrap pure $ wrap { transactionId , index @@ -51,10 +49,10 @@ txOutRefToTransactionInput { txId, index } = do -- | Converts an (internal) `TransactionInput` to an Ogmios transaction input transactionInputToTxOutRef - :: Transaction.TransactionInput -> Ogmios.OgmiosTxOutRef + :: TransactionInput -> Ogmios.OgmiosTxOutRef transactionInputToTxOutRef - (Transaction.TransactionInput { transactionId, index }) = - { txId: byteArrayToHex (unwrap transactionId) + (TransactionInput { transactionId, index }) = + { txId: byteArrayToHex (toBytes $ unwrap transactionId) , index } @@ -63,9 +61,9 @@ transactionInputToTxOutRef -- hexToByteArray for now. https://github.com/Plutonomicon/cardano-transaction-lib/issues/78 -- | Converts an Ogmios transaction output to (internal) `TransactionOutput` ogmiosTxOutToTransactionOutput - :: Ogmios.OgmiosTxOut -> Maybe Transaction.TransactionOutput + :: Ogmios.OgmiosTxOut -> Maybe TransactionOutput ogmiosTxOutToTransactionOutput { address, value, datum, datumHash, script } = do - address' <- ogmiosAddressToAddress address + address' <- Address.fromBech32 address -- If datum ~ Maybe String is Nothing, do nothing. Otherwise, attempt to -- convert and capture failure if we can't. dh <- traverse ogmiosDatumHashToDatumHash datumHash @@ -81,13 +79,13 @@ ogmiosTxOutToTransactionOutput { address, value, datum, datumHash, script } = do -- | Converts an internal transaction output to the Ogmios transaction output. transactionOutputToOgmiosTxOut - :: Transaction.TransactionOutput -> Ogmios.OgmiosTxOut + :: TransactionOutput -> Ogmios.OgmiosTxOut transactionOutputToOgmiosTxOut - (Transaction.TransactionOutput { address, amount: value, datum, scriptRef }) = - { address: addressToOgmiosAddress address + (TransactionOutput { address, amount: value, datum, scriptRef }) = + { address: Address.toBech32 address , value - , datumHash: datumHashToOgmiosDatumHash <$> outputDatumDataHash datum - , datum: datumToOgmiosDatum <$> outputDatumDatum datum + , datumHash: datumHashToOgmiosDatumHash <$> (outputDatumDataHash =<< datum) + , datum: datumToOgmiosDatum <$> (outputDatumDatum =<< datum) , script: scriptRef } @@ -96,25 +94,22 @@ transactionOutputToOgmiosTxOut -------------------------------------------------------------------------------- -- | Converts an Ogmios datum hash `String` to an internal `DataHash` ogmiosDatumHashToDatumHash :: String -> Maybe DataHash -ogmiosDatumHashToDatumHash str = hexToByteArray str <#> wrap +ogmiosDatumHashToDatumHash str = hexToByteArray str >>= wrap >>> decodeCbor -- | Converts an Ogmios datum `String` to an internal `Datum` -ogmiosDatumToDatum :: String -> Maybe Datum +ogmiosDatumToDatum :: String -> Maybe PlutusData ogmiosDatumToDatum = - hexToCborBytes - >=> fromBytes - >=> (Deserialization.convertPlutusData >>> Datum >>> Just) + hexToByteArray >=> wrap >>> decodeCbor -- | Converts an internal `DataHash` to an Ogmios datumhash `String` datumHashToOgmiosDatumHash :: DataHash -> String -datumHashToOgmiosDatumHash = byteArrayToHex <<< unwrap +datumHashToOgmiosDatumHash = byteArrayToHex <<< unwrap <<< encodeCbor -- | Converts an internal `Datum` to an Ogmios datum `String` -datumToOgmiosDatum :: Datum -> String -datumToOgmiosDatum (Datum plutusData) = - Serialization.convertPlutusData plutusData # - toBytes >>> unwrap >>> byteArrayToHex +datumToOgmiosDatum :: PlutusData -> String +datumToOgmiosDatum = + encodeCbor >>> unwrap >>> byteArrayToHex -toOutputDatum :: Maybe Datum -> Maybe DataHash -> OutputDatum +toOutputDatum :: Maybe PlutusData -> Maybe DataHash -> Maybe OutputDatum toOutputDatum d dh = - OutputDatum <$> d <|> OutputDatumHash <$> dh # fromMaybe NoOutputDatum + OutputDatum <$> d <|> OutputDatumHash <$> dh diff --git a/src/Internal/TypeLevel/Nat.purs b/src/Internal/TypeLevel/Nat.purs deleted file mode 100644 index 10dddf3f37..0000000000 --- a/src/Internal/TypeLevel/Nat.purs +++ /dev/null @@ -1,31 +0,0 @@ -module Ctl.Internal.TypeLevel.Nat - ( Z - , S - , Nat - , class KnownNat - , natVal - ) where - -import Prelude ((+)) -import Type.Proxy (Proxy(Proxy)) - --- | The kind of type level natural number. This is not strictly needed, but improves the --- | legibility of type errors and facilitates more comprehensible type signatures -data Nat :: Type -data Nat - --- | Type level natural numbers. We need these for a variety of inductive "operations" (i.e. type classes w/ fundeps) -foreign import data Z :: Nat - -foreign import data S :: Nat -> Nat - --- | PureScript version of the Haskell class defined in GHC.TypeLits. This is the Nat version of IsSymbol, more or less. -class KnownNat :: Nat -> Constraint -class KnownNat n where - natVal :: Proxy n -> Int - -instance KnownNat Z where - natVal _ = 0 - -instance KnownNat n => KnownNat (S n) where - natVal _ = 1 + natVal (Proxy :: Proxy n) diff --git a/src/Internal/TypeLevel/RowList.purs b/src/Internal/TypeLevel/RowList.purs deleted file mode 100644 index 417f2a8531..0000000000 --- a/src/Internal/TypeLevel/RowList.purs +++ /dev/null @@ -1,23 +0,0 @@ -module Ctl.Internal.TypeLevel.RowList - ( class AllUniqueLabels - ) where - -import Prim.TypeError (class Fail, Text) -import Type.RowList (Cons, Nil, RowList) - --- | Uniqueness constraint on the labels of an unordered RowList --- | Current implementation causes a compilation slowdown for complex types --- | GH Issue: https://github.com/Plutonomicon/cardano-transaction-lib/issues/433 -class AllUniqueLabels :: forall (k :: Type). RowList k -> Constraint -class AllUniqueLabels list - -instance AllUniqueLabels Nil -instance AllUniqueLabels (Cons k a Nil) -instance - Fail (Text "Labels are not unique!") => - AllUniqueLabels (Cons k a (Cons k a' xs)) -else instance - ( AllUniqueLabels (Cons k a xs) - , AllUniqueLabels (Cons k' a' xs) - ) => - AllUniqueLabels (Cons k a (Cons k' a' xs)) diff --git a/src/Internal/TypeLevel/RowList/Unordered/Indexed.purs b/src/Internal/TypeLevel/RowList/Unordered/Indexed.purs deleted file mode 100644 index fdf3d8533d..0000000000 --- a/src/Internal/TypeLevel/RowList/Unordered/Indexed.purs +++ /dev/null @@ -1,160 +0,0 @@ -module Ctl.Internal.TypeLevel.RowList.Unordered.Indexed - ( ConsI - , NilI - , RowListI - , class AllUniqueLabelsI - , class GetIndexWithLabel - , class GetLabelIndex - , class GetLabelWithIndex - , class GetWithLabel - , class IndexRowList - , class IndexRowListWithAcc - , class UniqueIndices - ) where - -import Data.Symbol - -import Ctl.Internal.TypeLevel.Nat (class KnownNat, Nat, S, Z) -import Prim.TypeError (class Fail, Text) -import Type.RowList (Cons, Nil, RowList) - --- | A kind for unordered RowLists which contain a Nat representation of their --- | intended position in a non-lexicographic order. Actual RowLists are automagically --- | ordered lexicographically, Haskell records are not ordered lexicographically, so we need --- | this to encode the structure of Haskell records precisely. -data RowListI :: forall (k :: Type). k -> Type -data RowListI k - --- Data constructors for RowListI. -foreign import data ConsI - :: forall (k :: Type). Symbol -> k -> Nat -> RowListI k -> RowListI k - -foreign import data NilI :: forall (k :: Type). RowListI k - --- TODO: See if we can optimize this. Slows down compilation time considerably for complex types --- GH Issue: https://github.com/Plutonomicon/cardano-transaction-lib/issues/433 --- | Uniqueness constraint on the Nat indices of a RowListI which asserts that all indices --- | are unique. This is needed to ensure that the various "lookup" classes return the --- | "values" (types) that we expect. -class UniqueIndices :: forall (k :: Type). RowListI k -> Constraint -class UniqueIndices list - -instance UniqueIndices NilI -instance UniqueIndices (ConsI k a n NilI) -instance - Fail (Text "Indices are not unique!") => - UniqueIndices (ConsI k a n (ConsI k' a' n xs)) -else instance - ( UniqueIndices (ConsI k a n xs) - , UniqueIndices - (ConsI k' a' n' xs) - ) => - UniqueIndices (ConsI k a n (ConsI k' a' n' xs)) - --- TODO: See if we can optimize this. Slows down compilation considerably for complex types. --- GH Issue: https://github.com/Plutonomicon/cardano-transaction-lib/issues/433 --- | Uniqueness constraint on the labels of a RowListI which asserts that all labels are unique. --- | Again, this is needed so that the lookup functions perform in the expected manner. -class AllUniqueLabelsI :: forall (k :: Type). RowListI k -> Constraint -class AllUniqueLabelsI list - -instance AllUniqueLabelsI NilI -instance AllUniqueLabelsI (ConsI k a n NilI) -instance - Fail (Text "Labels are not unique!") => - AllUniqueLabelsI (ConsI k a n (ConsI k a' n' xs)) -else instance - ( AllUniqueLabelsI (ConsI k a n xs) - , AllUniqueLabelsI (ConsI k' a' n' xs) - ) => - AllUniqueLabelsI (ConsI k a n (ConsI k' a' n' xs)) - --- | Get the Nat index corresponding to a given symbol index in a RowListI. --- | This is meant to be used primarily in the context of an instance declaration for some --- | other class (see examples in ToData.purs), and is probably not particularly useful --- | outside of those instance contexts. -class GetIndexWithLabel - :: forall (k :: Type). Symbol -> RowListI k -> Nat -> Constraint -class IsSymbol label <= GetIndexWithLabel label list n | label list -> n - -instance - ( AllUniqueLabelsI (ConsI label a n xs) - , UniqueIndices (ConsI label a n xs) - , IsSymbol label - , KnownNat n - ) => - GetIndexWithLabel label (ConsI label a n xs) n - -else instance - ( GetIndexWithLabel label xs n - , AllUniqueLabelsI (ConsI label' a' n' xs) - , UniqueIndices (ConsI label' a' n' xs) - , IsSymbol label - , KnownNat n - ) => - GetIndexWithLabel label (ConsI label' a' n' xs) n - --- | Given a Nat which appears as an index in the given RowListI, get its corresponding Symbol label -class GetLabelWithIndex - :: forall (k :: Type). Nat -> RowListI k -> Symbol -> Constraint -class - ( KnownNat ix - , AllUniqueLabelsI list - , UniqueIndices list - ) <= - GetLabelWithIndex ix list label - | ix list -> label - -instance - ( AllUniqueLabelsI (ConsI label a ix xs) - , UniqueIndices (ConsI label a ix xs) - , IsSymbol label - , KnownNat ix - ) => - GetLabelWithIndex ix (ConsI label a ix xs) label -else instance - ( GetLabelWithIndex ix xs label - , AllUniqueLabelsI (ConsI label' a' n' xs) - , UniqueIndices (ConsI label' a' n' xs) - , IsSymbol label - , KnownNat ix - ) => - GetLabelWithIndex ix (ConsI label' a' n' xs) label - --- | Given a Symbol which appears as a label in the given RowListI, get ahold of the type indexed by that symbol. --- | Note that this does not "return" a *value* of that type, but the type itself, and is therefore only suitable --- | for type class instance contexts (& other type level computational contexts if any exist) -class GetWithLabel - :: forall (k :: Type). Symbol -> RowListI k -> k -> Constraint -class GetWithLabel label rlist result | label rlist -> result - -instance IsSymbol l => GetWithLabel l (ConsI l a n xs) a -else instance (GetWithLabel l xs a) => GetWithLabel l (ConsI _l _a _n xs) a - --- | Get the nat index at a symbol in a RowList (Note: Not a RowListI! Use GetIndexWithLabel for a RowListI) -class GetLabelIndex - :: forall (k :: Type). Symbol -> RowList k -> Nat -> Constraint -class GetLabelIndex label list result | label list -> result - -instance - ( IndexRowList rowList rowListI - , GetIndexWithLabel label rowListI result - ) => - GetLabelIndex label rowList result - --- | Helper class for GetLabelIndex. Converts a RowList into a RowListI using its natural order (beginning with Z) -class IndexRowList :: forall (k :: Type). RowList k -> RowListI k -> Constraint -class IndexRowList list result | list -> result - -instance IndexRowListWithAcc Z list result => IndexRowList list result - --- | Helper class for IndexRowListWithAcc. -class IndexRowListWithAcc - :: forall (k :: Type). Nat -> RowList k -> RowListI k -> Constraint -class IndexRowListWithAcc acc list result | acc list -> result - --- purescript sure is an ugly dialect of prolog -instance IndexRowListWithAcc n Nil NilI -else instance - IndexRowListWithAcc (S n) xs xs' => - IndexRowListWithAcc n (Cons l a xs) (ConsI l a n xs') diff --git a/src/Internal/Types/Aliases.purs b/src/Internal/Types/Aliases.purs deleted file mode 100644 index 5e2317d9c7..0000000000 --- a/src/Internal/Types/Aliases.purs +++ /dev/null @@ -1,11 +0,0 @@ -module Ctl.Internal.Types.Aliases where - --- | IMPORTANT: All functions accepting `Bech32String` should behave correctly --- | in case `Bech32String` is not in bech32 format. --- | The type alias is here to make the intention of code more readable. -type Bech32String = String - --- | IMPORTANT: All functions accepting `Base58String` should behave correctly --- | in case `Base58String` is not in expected base58 format. --- | The type alias is here to make the intention of code more readable. -type Base58String = String diff --git a/src/Internal/Types/Any.purs b/src/Internal/Types/Any.purs deleted file mode 100644 index 02ca5f7e50..0000000000 --- a/src/Internal/Types/Any.purs +++ /dev/null @@ -1,13 +0,0 @@ -module Ctl.Internal.Types.Any - ( Any - ) where - -import Prelude (class Show) - --- Not sure if this is necessary but keep for now. --- | For converting a subset of polymorphic types to that which will work with --- | `PlutusData`. -foreign import data Any :: Type - -instance Show Any where - show _ = "(Any)" diff --git a/src/Internal/Types/BigNum.js b/src/Internal/Types/BigNum.js deleted file mode 100644 index 5514c30545..0000000000 --- a/src/Internal/Types/BigNum.js +++ /dev/null @@ -1,50 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); - // lib = (await import("../../../../cardano-serialization-lib-gc/nodejs/index.js")); -} - -export function bnCompare(lhs) { - return rhs => lhs.compare(rhs); -} - -export const zero = lib.BigNum.zero(); -export const one = lib.BigNum.one(); - -export function bnAdd(maybe) { - return lhs => rhs => { - try { - return maybe.just(lhs.checked_add(rhs)); - } catch (_) { - return maybe.nothing; - } - }; -} - -export function bnMul(maybe) { - return lhs => rhs => { - try { - return maybe.just(lhs.checked_mul(rhs)); - } catch (_) { - return maybe.nothing; - } - }; -} - -export function _fromString(maybe) { - return str => { - try { - return maybe.just(lib.BigNum.from_str(str)); - } catch (_) { - return maybe.nothing; - } - }; -} - -export function toString(bn) { - return bn.to_str(); -} diff --git a/src/Internal/Types/BigNum.purs b/src/Internal/Types/BigNum.purs deleted file mode 100644 index e5a75d039e..0000000000 --- a/src/Internal/Types/BigNum.purs +++ /dev/null @@ -1,119 +0,0 @@ -module Ctl.Internal.Types.BigNum - ( BigNum - , add - , fromBigInt - , fromInt - , fromString - , fromStringUnsafe - , maxValue - , mul - , one - , toBigInt - , toInt - , toInt' - , toString - , fromUInt - , toUInt - , zero - ) where - -import Prelude - -import Aeson (class DecodeAeson, class EncodeAeson, decodeAeson, encodeAeson) -import Aeson (JsonDecodeError(TypeMismatch)) as Aeson -import Ctl.Internal.Deserialization.Error (FromCslRepError, fromCslRepError) -import Ctl.Internal.Error (E, noteE) -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Data.Either (note) -import Data.Int (fromString) as Int -import Data.Maybe (Maybe, fromJust) -import Data.UInt (UInt) -import Data.UInt (fromInt, fromString, toString) as UInt -import JS.BigInt (BigInt) -import JS.BigInt (fromString, toString) as BigInt -import Partial.Unsafe (unsafePartial) -import Type.Row (type (+)) - -foreign import data BigNum :: Type - -instance Eq BigNum where - eq lhs rhs = bnCompare lhs rhs == 0 - -instance Ord BigNum where - compare lhs rhs = - case bnCompare lhs rhs of - 1 -> GT - 0 -> EQ - _ -> LT - -instance Show BigNum where - show bn = "fromString \"" <> toString bn <> "\"" - -instance DecodeAeson BigNum where - decodeAeson = - note (Aeson.TypeMismatch "Couldn't convert `BigInt` to `BigNum`") - <<< fromBigInt <=< decodeAeson - -instance EncodeAeson BigNum where - encodeAeson = encodeAeson <<< toBigInt - --- Semiring cannot be implemented, because add and mul returns Maybe BigNum - -fromBigInt :: BigInt -> Maybe BigNum -fromBigInt = fromString <<< BigInt.toString - -toBigInt :: BigNum -> BigInt -toBigInt = - -- Converting uint64 to an arbitrary length integer should never fail. - unsafePartial fromJust <<< BigInt.fromString <<< toString - -toInt :: BigNum -> Maybe Int -toInt = Int.fromString <<< toString - -toInt' - :: forall (r :: Row Type). String -> BigNum -> E (FromCslRepError + r) Int -toInt' nm bn = - noteE (fromCslRepError (nm <> ": CSL.BigNum (" <> show bn <> ") -> Int ")) $ - toInt bn - -foreign import bnCompare :: BigNum -> BigNum -> Int - -foreign import zero :: BigNum - -foreign import one :: BigNum - -foreign import bnAdd :: MaybeFfiHelper -> BigNum -> BigNum -> Maybe BigNum - -add :: BigNum -> BigNum -> Maybe BigNum -add = bnAdd maybeFfiHelper - -foreign import bnMul :: MaybeFfiHelper -> BigNum -> BigNum -> Maybe BigNum - -mul :: BigNum -> BigNum -> Maybe BigNum -mul = bnMul maybeFfiHelper - --- | Converts an `Int` to a `BigNum` turning negative `Int`s into `BigNum`s --- | in range from `2^31` to `2^32-1`. -fromInt :: Int -> BigNum -fromInt = - -- Converting `UInt` (u32) to a `BigNum` (u64) should never fail. - fromStringUnsafe <<< UInt.toString <<< UInt.fromInt - -foreign import _fromString :: MaybeFfiHelper -> String -> Maybe BigNum - -fromString :: String -> Maybe BigNum -fromString = _fromString maybeFfiHelper - -fromStringUnsafe :: String -> BigNum -fromStringUnsafe = unsafePartial fromJust <<< fromString - -foreign import toString :: BigNum -> String - -maxValue :: BigNum -maxValue = fromStringUnsafe "18446744073709551615" - -fromUInt :: UInt -> BigNum -fromUInt = fromStringUnsafe <<< UInt.toString - -toUInt :: BigNum -> Maybe UInt -toUInt = toString >>> UInt.fromString diff --git a/src/Internal/Types/ByteArray.js b/src/Internal/Types/ByteArray.js deleted file mode 100644 index 09bf1f2b12..0000000000 --- a/src/Internal/Types/ByteArray.js +++ /dev/null @@ -1,113 +0,0 @@ -// From instance for Array in prelude -export function ord_(f) { - return xs => ys => { - let i = 0; - const xlen = xs.length; - const ylen = ys.length; - while (i < xlen && i < ylen) { - let o = f(xs[i])(ys[i]); - if (o !== 0) { - return o; - } - i++; - } - if (xlen === ylen) { - return 0; - } else if (xlen > ylen) { - return -1; - } else { - return 1; - } - }; -} - -export function concat_(xs) { - return ys => { - const res = new Uint8Array(xs.length + ys.length); - for (let i = 0; i < xs.length; i++) { - res[i] = xs[i]; - } - for (let i = 0; i < ys.length; i++) { - res[i + xs.length] = ys[i]; - } - return res; - }; -} - -export function byteArrayToHex(arr) { - return Buffer.from(arr).toString("hex"); -} - -/* adapted from https://github.com/WebReflection/uint8-to-utf16/blob/master/esm/index.js - * (someone who knows javascript should like import that or something) - */ -const { ceil } = Math; -const { fromCharCode } = String; - -export function byteArrayToUTF16le(uint8array) { - let extra = 0; - const output = []; - const { length } = uint8array; - const len = ceil(length / 2); - for (let j = 0, i = 0; i < len; i++) - output.push( - fromCharCode( - (uint8array[j++] << 8) + (j < length ? uint8array[j++] : extra++) - ) - ); - output.push(fromCharCode(extra)); - return output.join(""); -} - -export function hexToByteArray_(nothing) { - return just => hex => { - let bytes = []; - for (let c = 0; c < hex.length; c += 2) { - const chunk = hex.substr(c, 2); - if (/[0-9a-f]{2}/i.test(chunk)) { - bytes.push(parseInt(chunk, 16)); - } else { - return nothing; - } - } - return just(new Uint8Array(bytes)); - }; -} - -export function hexToByteArrayUnsafe(hex) { - let bytes = []; - for (let c = 0; c < hex.length; c += 2) { - bytes.push(parseInt(hex.substr(c, 2), 16)); - } - return new Uint8Array(bytes); -} - -export function byteArrayFromIntArrayUnsafe(ints) { - return new Uint8Array(ints); -} - -export function byteArrayFromInt16ArrayUnsafe(ints) { - return new Uint8Array(ints.buffer, ints.byteOffset, ints.byteLength); -} - -export function byteArrayFromIntArray_(nothing) { - return just => ints => { - if (ints.every(i => i < 256 && i >= 0)) { - return just(new Uint8Array(ints)); - } else { - return nothing; - } - }; -} - -export function byteArrayToIntArray(bytes) { - return Array.from(bytes); -} - -export function byteLength(bytes) { - return bytes.byteLength; -} - -export function subarray(start) { - return end => bytes => bytes.subarray(start, end); -} diff --git a/src/Internal/Types/ByteArray.purs b/src/Internal/Types/ByteArray.purs deleted file mode 100644 index 565d0e2fc7..0000000000 --- a/src/Internal/Types/ByteArray.purs +++ /dev/null @@ -1,137 +0,0 @@ --- | Our domain type for byte arrays, a wrapper over `Uint8Array`. -module Ctl.Internal.Types.ByteArray - ( ByteArray(ByteArray) - , byteArrayFromIntArray - , byteArrayFromIntArrayUnsafe - , byteArrayFromInt16ArrayUnsafe - , byteArrayFromAscii - , byteArrayToHex - , byteArrayToIntArray - , byteLength - , hexToByteArray - , hexToByteArrayUnsafe - , byteArrayToUTF16le - , subarray - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch, UnexpectedValue) - , caseAesonString - , encodeAeson - , toStringifiedNumbersJson - ) -import Data.ArrayBuffer.Types (Uint8Array) -import Data.Char (toCharCode) -import Data.Either (Either(Left), note) -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (class Newtype) -import Data.String.CodeUnits (toCharArray) -import Data.Traversable (for) -import Test.QuickCheck.Arbitrary - ( class Arbitrary - , class Coarbitrary - , arbitrary - , coarbitrary - ) - -newtype ByteArray = ByteArray Uint8Array - -derive instance Newtype ByteArray _ - -instance Show ByteArray where - show arr = "(hexToByteArrayUnsafe " <> show (byteArrayToHex arr) - <> ")" - -instance Eq ByteArray where - eq a b = compare a b == EQ - -instance Ord ByteArray where - compare = \xs ys -> compare 0 (ord_ toDelta xs ys) - where - toDelta x y = - case compare x y of - EQ -> 0 - LT -> 1 - GT -> -1 - -instance Semigroup ByteArray where - append = concat_ - -instance Monoid ByteArray where - mempty = byteArrayFromIntArrayUnsafe [] - -instance DecodeAeson ByteArray where - decodeAeson j = caseAesonString (Left typeMismatchError) - (note unexpectedValueError <<< hexToByteArray) - j - where - typeMismatchError = TypeMismatch "expected a hex-encoded string" - unexpectedValueError = UnexpectedValue $ toStringifiedNumbersJson j - -instance EncodeAeson ByteArray where - encodeAeson ba = encodeAeson (byteArrayToHex ba) - -foreign import ord_ :: (Int -> Int -> Int) -> ByteArray -> ByteArray -> Int - -foreign import concat_ :: ByteArray -> ByteArray -> ByteArray - -foreign import byteArrayToHex :: ByteArray -> String - -foreign import hexToByteArray_ - :: (forall (a :: Type). Maybe a) - -> (forall (a :: Type). a -> Maybe a) - -> String - -> Maybe ByteArray - --- | Input string must consist of hexadecimal numbers. --- | Length of the input string must be even (2 characters per byte). -hexToByteArray :: String -> Maybe ByteArray -hexToByteArray = hexToByteArray_ Nothing Just - --- | Characters not in range will be converted to zero. -foreign import hexToByteArrayUnsafe :: String -> ByteArray - --- | Overflowing integers will be silently accepted modulo 256. -foreign import byteArrayFromIntArrayUnsafe :: Array Int -> ByteArray - -foreign import byteArrayFromIntArray_ - :: (forall (a :: Type). Maybe a) - -> (forall (a :: Type). a -> Maybe a) - -> Array Int - -> Maybe ByteArray - --- | A safer version of `byteArrayFromIntArrayUnsafe` that checks that elements are in range 0-255. -byteArrayFromIntArray :: Array Int -> Maybe ByteArray -byteArrayFromIntArray = byteArrayFromIntArray_ Nothing Just - -foreign import byteArrayToIntArray :: ByteArray -> Array Int - -foreign import byteLength :: ByteArray -> Int - --- | Given a begin offset (inclusive) and end offset (exclusive), efficiently --- | create a new `ByteArray` backed by the same underlying buffer. -foreign import subarray :: Int -> Int -> ByteArray -> ByteArray - -instance Arbitrary ByteArray where - arbitrary = byteArrayFromIntArrayUnsafe <$> arbitrary - -instance Coarbitrary ByteArray where - coarbitrary bytes generator = coarbitrary (byteArrayToIntArray bytes) - generator - --- | Convert characters in range `0-255` into a `ByteArray`. --- | Fails with `Nothing` if there are characters out of this range in a string. -byteArrayFromAscii :: String -> Maybe ByteArray -byteArrayFromAscii str = do - byteArrayFromIntArrayUnsafe <$> for (toCharArray str) \cp -> do - let charCode = toCharCode cp - if charCode <= 255 && charCode >= 0 then pure charCode - else Nothing - -foreign import byteArrayFromInt16ArrayUnsafe :: Array Int -> ByteArray - -foreign import byteArrayToUTF16le :: ByteArray -> String diff --git a/src/Internal/Types/Cbor.purs b/src/Internal/Types/Cbor.purs index 0245de4e93..9d65a33df6 100644 --- a/src/Internal/Types/Cbor.purs +++ b/src/Internal/Types/Cbor.purs @@ -19,16 +19,16 @@ module Ctl.Internal.Types.Cbor import Prelude +import Cardano.Types.CborBytes (CborBytes(CborBytes)) import Contract.Prelude (foldl) import Control.Monad.Except (Except, runExcept, throwError) import Control.Monad.State.Trans (StateT, evalStateT, get, put) -import Ctl.Internal.Types.ByteArray - ( ByteArray +import Data.ByteArray + ( ByteArray(ByteArray) , byteArrayToIntArray , byteLength , subarray ) -import Ctl.Internal.Types.CborBytes (CborBytes(CborBytes)) import Data.Either (Either) import Data.Newtype (class Newtype) import Data.UInt (UInt, shl, zshr, (.&.), (.|.)) diff --git a/src/Internal/Types/CborBytes.purs b/src/Internal/Types/CborBytes.purs deleted file mode 100644 index 4d69c1d5e3..0000000000 --- a/src/Internal/Types/CborBytes.purs +++ /dev/null @@ -1,79 +0,0 @@ --- | CborBytes. A wrapper over `ByteArray` to indicate that the bytes are cbor. -module Ctl.Internal.Types.CborBytes - ( CborBytes(CborBytes) - , cborBytesToByteArray - , cborBytesFromByteArray - , cborBytesFromAscii - , cborBytesToIntArray - , cborBytesFromIntArray - , cborBytesFromIntArrayUnsafe - , cborBytesToHex - , cborByteLength - , hexToCborBytes - , hexToCborBytesUnsafe - , rawBytesAsCborBytes - ) where - -import Prelude - -import Aeson (class DecodeAeson, class EncodeAeson) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.ByteArray as ByteArray -import Ctl.Internal.Types.RawBytes (RawBytes) -import Data.Maybe (Maybe) -import Data.Newtype (class Newtype, unwrap, wrap) -import Test.QuickCheck.Arbitrary (class Arbitrary) - --- | An array of bytes containing CBOR data -newtype CborBytes = CborBytes ByteArray - -instance Show CborBytes where - show rb = "(hexToCborBytesUnsafe " <> show (cborBytesToHex rb) <> - ")" - -derive instance Newtype CborBytes _ - -derive newtype instance Eq CborBytes -derive newtype instance Ord CborBytes -derive newtype instance Semigroup CborBytes -derive newtype instance Monoid CborBytes -derive newtype instance EncodeAeson CborBytes -derive newtype instance DecodeAeson CborBytes -derive newtype instance Arbitrary CborBytes -derive newtype instance ToMetadata CborBytes -derive newtype instance FromMetadata CborBytes - -cborBytesToIntArray :: CborBytes -> Array Int -cborBytesToIntArray = ByteArray.byteArrayToIntArray <<< unwrap - -cborBytesFromIntArray :: Array Int -> Maybe CborBytes -cborBytesFromIntArray = map wrap <<< ByteArray.byteArrayFromIntArray - -cborBytesFromIntArrayUnsafe :: Array Int -> CborBytes -cborBytesFromIntArrayUnsafe = wrap <<< ByteArray.byteArrayFromIntArrayUnsafe - -cborBytesToHex :: CborBytes -> String -cborBytesToHex = ByteArray.byteArrayToHex <<< unwrap - -cborByteLength :: CborBytes -> Int -cborByteLength = ByteArray.byteLength <<< unwrap - -hexToCborBytes :: String -> Maybe CborBytes -hexToCborBytes = map wrap <<< ByteArray.hexToByteArray - -hexToCborBytesUnsafe :: String -> CborBytes -hexToCborBytesUnsafe = wrap <<< ByteArray.hexToByteArrayUnsafe - -cborBytesToByteArray :: CborBytes -> ByteArray -cborBytesToByteArray = unwrap - -cborBytesFromByteArray :: ByteArray -> CborBytes -cborBytesFromByteArray = wrap - -cborBytesFromAscii :: String -> Maybe CborBytes -cborBytesFromAscii = map wrap <<< ByteArray.byteArrayFromAscii - -rawBytesAsCborBytes :: RawBytes -> CborBytes -rawBytesAsCborBytes = wrap <<< unwrap diff --git a/src/Internal/Types/Chain.purs b/src/Internal/Types/Chain.purs index d400f576fe..a085a5dd56 100644 --- a/src/Internal/Types/Chain.purs +++ b/src/Internal/Types/Chain.purs @@ -6,7 +6,7 @@ module Ctl.Internal.Types.Chain import Prelude -import Ctl.Internal.Serialization.Address (Slot) +import Cardano.Types.Slot (Slot) import Data.Generic.Rep (class Generic) import Data.Newtype (class Newtype) import Data.Show.Generic (genericShow) diff --git a/src/Internal/Types/Datum.purs b/src/Internal/Types/Datum.purs deleted file mode 100644 index ec32862077..0000000000 --- a/src/Internal/Types/Datum.purs +++ /dev/null @@ -1,42 +0,0 @@ -module Ctl.Internal.Types.Datum - ( Datum(Datum) - , unitDatum - , module X - ) where - -import Prelude - -import Aeson (class DecodeAeson, class EncodeAeson, decodeAeson, encodeAeson) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.PlutusData (PlutusData) -import Ctl.Internal.Types.Transaction (DataHash(DataHash)) as X -import Data.Generic.Rep (class Generic) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Show.Generic (genericShow) - --- | Define data types mirroring Plutus `Datum`, like `Datum` itself and --- | `Redeemer` where the latter is not to be confused with the CSL-stype --- | `Types.Transaction.Redeemer`. - --- | `Datum` is defined as a newtype of `PlutusData` -newtype Datum = Datum PlutusData - -derive instance Newtype Datum _ -derive instance Generic Datum _ -derive newtype instance Eq Datum -derive newtype instance FromData Datum -derive newtype instance Ord Datum -derive newtype instance ToData Datum - -instance EncodeAeson Datum where - encodeAeson = encodeAeson <<< unwrap - -instance DecodeAeson Datum where - decodeAeson = map wrap <<< decodeAeson - -instance Show Datum where - show = genericShow - -unitDatum :: Datum -unitDatum = Datum $ toData unit diff --git a/src/Internal/Types/DelegationsAndRewards.purs b/src/Internal/Types/DelegationsAndRewards.purs index fbe25d1e72..0309cbc06f 100644 --- a/src/Internal/Types/DelegationsAndRewards.purs +++ b/src/Internal/Types/DelegationsAndRewards.purs @@ -4,8 +4,8 @@ module Ctl.Internal.Types.DelegationsAndRewards import Data.Maybe -import Ctl.Internal.Cardano.Types.Transaction (PoolPubKeyHash) -import Ctl.Internal.Cardano.Types.Value (Coin) +import Cardano.Types.Coin (Coin) +import Cardano.Types.PoolPubKeyHash (PoolPubKeyHash) type DelegationsAndRewards = { rewards :: Maybe Coin diff --git a/src/Internal/Types/Epoch.purs b/src/Internal/Types/Epoch.purs deleted file mode 100644 index fed438326d..0000000000 --- a/src/Internal/Types/Epoch.purs +++ /dev/null @@ -1,24 +0,0 @@ -module Ctl.Internal.Types.Epoch (Epoch(Epoch)) where - -import Prelude - -import Aeson (class DecodeAeson, class EncodeAeson) -import Ctl.Internal.Helpers (showWithParens) -import Data.Generic.Rep (class Generic) -import Data.Newtype (class Newtype) -import JS.BigInt (BigInt) - --- | An epoch number or length with greater precision for Ogmios than --- | `Cardano.Types.Epoch`. [ 0 .. 18446744073709552000 ] -newtype Epoch = Epoch BigInt - -derive instance Generic Epoch _ -derive instance Newtype Epoch _ -derive newtype instance Eq Epoch -derive newtype instance Ord Epoch -derive newtype instance DecodeAeson Epoch -derive newtype instance EncodeAeson Epoch - -instance Show Epoch where - show (Epoch e) = showWithParens "Epoch" e - diff --git a/src/Internal/Types/EraSummaries.purs b/src/Internal/Types/EraSummaries.purs index ae6cf387c5..a49335858a 100644 --- a/src/Internal/Types/EraSummaries.purs +++ b/src/Internal/Types/EraSummaries.purs @@ -18,16 +18,15 @@ import Aeson , finiteNumber , getField ) -import Ctl.Internal.Helpers (showWithParens) -import Ctl.Internal.Serialization.Address (Slot) +import Cardano.Types.Epoch (Epoch) +import Cardano.Types.Slot (Slot) +import Ctl.Internal.Helpers (showWithParens, unsafeFromJust) import Ctl.Internal.Service.Helpers (aesonObject) -import Ctl.Internal.Types.Epoch (Epoch) import Data.Generic.Rep (class Generic) -import Data.Maybe (Maybe, fromJust) +import Data.Maybe (Maybe) import Data.Newtype (class Newtype, wrap) import Data.Show.Generic (genericShow) import JS.BigInt (BigInt) -import Partial.Unsafe (unsafePartial) -------------------------------------------------------------------------------- -- EraSummaries @@ -143,7 +142,8 @@ derive newtype instance DecodeAeson RelativeTime instance EncodeAeson RelativeTime where encodeAeson (RelativeTime rt) = -- We assume the numbers are finite. - encodeAeson $ unsafePartial $ fromJust $ finiteNumber rt + encodeAeson $ unsafeFromJust "instance EncodeAeson RelativeTime" $ + finiteNumber rt instance Show RelativeTime where show (RelativeTime rt) = showWithParens "RelativeTime" rt @@ -170,7 +170,8 @@ derive newtype instance DecodeAeson SlotLength instance EncodeAeson SlotLength where encodeAeson (SlotLength sl) = -- We assume the numbers are finite. - encodeAeson $ unsafePartial $ fromJust $ finiteNumber sl + encodeAeson $ unsafeFromJust "instance EncodeAeson SlotLength" $ + finiteNumber sl instance Show SlotLength where show (SlotLength slotLength) = showWithParens "SlotLength" slotLength diff --git a/src/Internal/Types/Int.js b/src/Internal/Types/Int.js deleted file mode 100644 index 8110b53cb3..0000000000 --- a/src/Internal/Types/Int.js +++ /dev/null @@ -1,15 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -export const newPositive = lib.Int.new; -export const newNegative = lib.Int.new_negative; - -export function _intToStr(n) { - return n.to_str(); -} diff --git a/src/Internal/Types/Int.purs b/src/Internal/Types/Int.purs deleted file mode 100644 index 5d9fceb7c5..0000000000 --- a/src/Internal/Types/Int.purs +++ /dev/null @@ -1,73 +0,0 @@ --- | `cardano-serialization-lib` Int type (can be positive or negative). -module Ctl.Internal.Types.Int - ( Int - , newPositive - , newNegative - , fromBigInt - , toBigInt - , fromInt - , toInt - , fromString - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , decodeAeson - , encodeAeson - ) -import Control.Alternative ((<|>)) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum (fromBigInt, fromInt) as BigNum -import Data.Either (note) -import Data.Function (on) -import Data.Maybe (Maybe, fromJust) -import JS.BigInt as BigInt -import Partial.Unsafe (unsafePartial) -import Prim as Prim - -foreign import data Int :: Prim.Type - -foreign import newPositive :: BigNum -> Int -foreign import newNegative :: BigNum -> Int -foreign import _intToStr :: Int -> Prim.String - -instance Eq Int where - eq = eq `on` _intToStr - -instance Ord Int where - compare = compare `on` toBigInt - -instance Show Int where - show = _intToStr - -instance EncodeAeson Int where - encodeAeson = encodeAeson <<< toBigInt - -instance DecodeAeson Int where - decodeAeson aeson = - decodeAeson aeson >>= note (TypeMismatch "Int") <<< fromBigInt - -fromBigInt :: BigInt.BigInt -> Maybe Int -fromBigInt bi = - (newPositive <$> BigNum.fromBigInt bi) <|> - (newNegative <$> BigNum.fromBigInt (negate bi)) - -toBigInt :: Int -> BigInt.BigInt -toBigInt int = - -- Assuming every Int can be represented as BigInt - unsafePartial $ fromJust $ BigInt.fromString $ _intToStr int - -fromInt :: Prim.Int -> Int -fromInt n - | n < 0 = newNegative $ BigNum.fromInt n - | otherwise = newPositive $ BigNum.fromInt n - -toInt :: Int -> Maybe Prim.Int -toInt = toBigInt >>> BigInt.toInt - -fromString :: Prim.String -> Maybe Int -fromString = fromBigInt <=< BigInt.fromString diff --git a/src/Internal/Types/Interval.purs b/src/Internal/Types/Interval.purs index 740320eae7..3a7e2ded55 100644 --- a/src/Internal/Types/Interval.purs +++ b/src/Internal/Types/Interval.purs @@ -28,7 +28,6 @@ module Ctl.Internal.Types.Interval , after , always , before - , beginningOfTime , contains , findSlotEraSummary , findTimeEraSummary @@ -77,42 +76,35 @@ import Aeson , isNull , (.:) ) +import Cardano.FromData (class FromData, fromData, genericFromData) +import Cardano.Plutus.DataSchema + ( class HasPlutusSchema + , type (:+) + , type (:=) + , type (@@) + , PNil + , S + , Z + ) +import Cardano.ToData (class ToData, genericToData, toData) +import Cardano.Types.BigNum (add, fromBigInt, maxValue, one, toBigInt, zero) as BigNum +import Cardano.Types.PlutusData (PlutusData(Constr)) +import Cardano.Types.Slot (Slot(Slot)) import Control.Monad.Error.Class (throwError) import Control.Monad.Except (runExcept) -import Ctl.Internal.FromData (class FromData, fromData, genericFromData) import Ctl.Internal.Helpers - ( contentsProp - , encodeTagged' + ( encodeTagged' , liftEither , liftM , mkErrorRecord , showWithParens - , tagProp + , unsafeFromJust ) -import Ctl.Internal.Plutus.Types.DataSchema - ( class HasPlutusSchema - , type (:+) - , type (:=) - , type (@@) - , PNil - ) -import Ctl.Internal.QueryM.Ogmios (aesonObject, slotLengthFactor) -import Ctl.Internal.Serialization.Address (Slot(Slot)) -import Ctl.Internal.ToData (class ToData, genericToData, toData) -import Ctl.Internal.TypeLevel.Nat (S, Z) -import Ctl.Internal.Types.BigNum - ( add - , fromBigInt - , maxValue - , one - , toBigInt - , zero - ) as BigNum +import Ctl.Internal.QueryM.Ogmios (aesonObject) import Ctl.Internal.Types.EraSummaries ( EraSummaries(EraSummaries) , EraSummary(EraSummary) ) -import Ctl.Internal.Types.PlutusData (PlutusData(Constr)) import Ctl.Internal.Types.SystemStart (SystemStart, sysStartUnixTime) import Data.Argonaut.Encode.Encoders (encodeString) import Data.Array (find, head, index, length) @@ -127,7 +119,7 @@ import Data.Lattice , class JoinSemilattice , class MeetSemilattice ) -import Data.Maybe (Maybe(Just, Nothing), fromJust, maybe) +import Data.Maybe (Maybe(Just, Nothing), maybe) import Data.Newtype (class Newtype, unwrap, wrap) import Data.Number (trunc, (%)) as Math import Data.Show.Generic (genericShow) @@ -135,8 +127,7 @@ import Data.Tuple (uncurry) import Data.Tuple.Nested (type (/\), (/\)) import Foreign.Object (Object) import JS.BigInt (BigInt) -import JS.BigInt (fromInt, fromNumber, fromString, toNumber) as BigInt -import Partial.Unsafe (unsafePartial) +import JS.BigInt (fromInt, fromNumber, toNumber) as BigInt import Prim.TypeError (class Warn, Text) import Test.QuickCheck (class Arbitrary, arbitrary) import Test.QuickCheck.Gen (Gen, frequency) @@ -601,14 +592,6 @@ instance Show OnchainPOSIXTimeRange where type SlotRange = Interval Slot --- | 'beginningOfTime' corresponds to the Shelley launch date --- | (2020-07-29T21:44:51Z) which is 1596059091000 in POSIX time --- | (number of milliseconds since 1970-01-01T00:00:00Z). -beginningOfTime :: BigInt -beginningOfTime = - unsafePartial fromJust $ - BigInt.fromString "1596059091000" - -- | Maximum slot (u64) maxSlot :: Slot maxSlot = wrap BigNum.maxValue @@ -651,7 +634,8 @@ instance EncodeAeson SlotToPosixTimeError where slotToPosixTimeErrorStr "endTimeLessThanTime" -- We assume the numbers are finite - [ unsafePartial $ fromJust $ finiteNumber absTime ] + [ unsafeFromJust "EncodeAeson SlotToPosixTimeError" $ finiteNumber absTime + ] encodeAeson CannotGetBigIntFromNumber = do encodeAeson $ mkErrorRecord slotToPosixTimeErrorStr @@ -848,6 +832,9 @@ absTimeFromRelTime (EraSummary { start, end }) (RelTime relTime) = do wrap <$> (liftM CannotGetBigIntFromNumber $ BigInt.fromNumber absTime) +slotLengthFactor :: Number +slotLengthFactor = 1000.0 + -------------------------------------------------------------------------------- -- POSIXTime (milliseconds) to -- Slot (absolute from System Start - see QueryM.SystemStart.getSystemStart) @@ -944,7 +931,8 @@ posixTimeToSlot eraSummaries sysStart pt'@(POSIXTime pt) = runExcept do -- to a conversion from a Number, which may be an infinity or NaN in the -- general case. However, we know that system time cannot be either of these -- things. - let sysStartPosix = unsafePartial $ fromJust $ sysStartUnixTime sysStart + let + sysStartPosix = unsafeFromJust "posixTimeToSlot" $ sysStartUnixTime sysStart -- Ensure the time we are converting is after the system start, otherwise -- we have negative slots. unless (sysStartPosix <= pt) @@ -992,8 +980,9 @@ relTimeFromAbsTime (EraSummary { start }) at@(AbsTime absTime) = do -- This conversion cannot fail: since 'relTime' is an offset from the start of -- an era, we can't overflow the 64-bit limit. let - relTimeBi = unsafePartial $ fromJust $ BigInt.fromNumber $ Math.trunc - relTime + relTimeBi = unsafeFromJust "relTimeFromAbsTime" $ BigInt.fromNumber $ + Math.trunc + relTime pure $ wrap relTimeBi -- | Converts relative time to a relative slot (using Euclidean division) and @@ -1016,7 +1005,7 @@ relSlotFromRelTime eraSummary (RelTime relTime) = (wrap $ toBigIntUnsafe modTime) where toBigIntUnsafe :: Number -> BigInt - toBigIntUnsafe x = unsafePartial $ fromJust $ BigInt.fromNumber x + toBigIntUnsafe x = unsafeFromJust "relSlotFromRelTime" $ BigInt.fromNumber x slotFromRelSlot :: EraSummary -> RelSlot /\ ModTime -> Either PosixTimeToSlotError Slot @@ -1038,7 +1027,7 @@ slotFromRelSlot end -- Slot numbers should convert without error: they're meant to be 64-bit -- integers anyway. - let bnSlot = unsafePartial $ fromJust $ BigNum.fromBigInt slot + let bnSlot = unsafeFromJust "slotFromRelSlot" $ BigNum.fromBigInt slot -- Check we are less than the end slot, or if equal, there is no excess: unless (slot < endSlot || slot == endSlot && modTime == zero) (throwError $ EndSlotLessThanSlotOrModNonZero (wrap bnSlot) mt) @@ -1174,12 +1163,12 @@ instance (EncodeAeson a) => EncodeAeson (Extended a) where instance (DecodeAeson a) => DecodeAeson (Extended a) where decodeAeson a = lmap (Named "Extended") do obj <- decodeAeson a - tag <- obj .: tagProp + tag <- obj .: "tag" case tag of "NegInf" -> pure NegInf "PosInf" -> pure PosInf - "Finite" -> Finite <$> obj .: contentsProp - _ -> Left $ AtKey tagProp $ UnexpectedValue $ encodeString tag + "Finite" -> Finite <$> obj .: "contents" + _ -> Left $ AtKey "tag" $ UnexpectedValue $ encodeString tag toOnChainPosixTimeRangeErrorStr :: String toOnChainPosixTimeRangeErrorStr = "ToOnChainPosixTimeRangeError" diff --git a/src/Internal/Types/MetadataLabel.purs b/src/Internal/Types/MetadataLabel.purs new file mode 100644 index 0000000000..be724c47bf --- /dev/null +++ b/src/Internal/Types/MetadataLabel.purs @@ -0,0 +1,20 @@ +module Ctl.Internal.Types.MetadataLabel where + +import Prelude + +import Cardano.AsCbor (class AsCbor) +import Cardano.Types (BigNum) +import Data.Generic.Rep (class Generic) +import Data.Newtype (class Newtype) +import Data.Show.Generic (genericShow) + +newtype MetadataLabel = MetadataLabel BigNum + +derive instance Newtype MetadataLabel _ +derive newtype instance AsCbor MetadataLabel +derive instance Eq MetadataLabel +derive instance Generic MetadataLabel _ +derive instance Ord MetadataLabel + +instance Show MetadataLabel where + show = genericShow diff --git a/src/Internal/Types/MultiMap.purs b/src/Internal/Types/MultiMap.purs deleted file mode 100644 index bbd1e45b0d..0000000000 --- a/src/Internal/Types/MultiMap.purs +++ /dev/null @@ -1,50 +0,0 @@ -module Ctl.Internal.Types.MultiMap - ( MultiMap - , empty - , singleton - , insert - , delete - , lookup - ) where - -import Control.Alt (map) -import Control.Bind ((>>=)) -import Control.Category ((>>>)) -import Data.Array as Array -import Data.Bounded (class Ord) -import Data.Function (($)) -import Data.Map as Map -import Data.Maybe (Maybe) -import Data.Monoid ((<>)) - --- | A specific-use MultiMap where values for the same key are stored in FIFO container --- implemented via Array -newtype MultiMap (k :: Type) (v :: Type) = MultiMap (Map.Map k (Array v)) - --- | Constructs an empty `MultiMap` -empty :: forall (k :: Type) (v :: Type). MultiMap k v -empty = MultiMap Map.empty - --- | Constructs a `MultiMap` storing single key-value pair. -singleton :: forall (k :: Type) (v :: Type). Ord k => k -> v -> MultiMap k v -singleton k v = MultiMap $ Map.insert k (Array.singleton v) Map.empty - --- | Inserts value. In case k exist the value is stored at the end of --- existing values array. -insert - :: forall (k :: Type) (v :: Type) - . Ord k - => k - -> v - -> MultiMap k v - -> MultiMap k v -insert k v (MultiMap m) = MultiMap $ Map.insertWith (<>) k (Array.singleton v) m - --- | Deletes first value from a value array under given k. -delete - :: forall (k :: Type) (v :: Type). Ord k => k -> MultiMap k v -> MultiMap k v -delete k (MultiMap m) = MultiMap $ Map.update (Array.uncons >>> map _.tail) k m - --- | Lookup first value for given key. -lookup :: forall (k :: Type) (v :: Type). Ord k => k -> MultiMap k v -> Maybe v -lookup k (MultiMap m) = Map.lookup k m >>= Array.head diff --git a/src/Internal/Types/NatRatio.purs b/src/Internal/Types/NatRatio.purs deleted file mode 100644 index a55a300d34..0000000000 --- a/src/Internal/Types/NatRatio.purs +++ /dev/null @@ -1,79 +0,0 @@ --- | A module for constructing well-defined ratios of natural numbers (with --- | non-zero denominator), potentially via cancellation of negative sign. -module Ctl.Internal.Types.NatRatio - ( NatRatio - , denominator - , denominatorAsNat - , fromBigInts - , fromNaturals - , fromRational - , numerator - , numeratorAsNat - , toRational - ) where - -import Prelude - -import Ctl.Internal.Types.Natural (Natural) -import Ctl.Internal.Types.Natural (fromBigInt', toBigInt) as Nat -import Ctl.Internal.Types.Rational (Rational) -import Ctl.Internal.Types.Rational - ( denominator - , denominatorAsNat - , numerator - , (%) - ) as Rational -import Data.Maybe (Maybe(Nothing)) -import JS.BigInt (BigInt) - --- | `NatRatio` is a newtype over `Rational` with smart constructors to create a --- | `NatRatio` safely. Therefore, the data constructor is not exported. -newtype NatRatio = NatRatio Rational - -derive newtype instance Eq NatRatio -derive newtype instance Ord NatRatio --- If `NatRatio`s are safely constructed, then the underlying `Rational`s --- should obey Semiring laws. -derive newtype instance Semiring NatRatio - -instance Show NatRatio where - show (NatRatio r) = "(NatRatio " <> show r <> ")" - --- | Fails with `Nothing` if the denominator is zero or the overall sign of --- | the rational numbers is negative. -fromRational :: Rational -> Maybe NatRatio -fromRational r = fromBigInts (Rational.numerator r) (Rational.denominator r) - --- | Converts a `NatRatio` to the underlying `Rational`. -toRational :: NatRatio -> Rational -toRational (NatRatio r) = r - --- | Given two `Natural`s, attempts to convert to a `NatRatio`. Fails if the --- | denominator is `zero`. -fromNaturals :: Natural -> Natural -> Maybe NatRatio -fromNaturals n d = NatRatio <$> Nat.toBigInt n Rational.% Nat.toBigInt d - --- | Given two `BigInt`s, attempts to convert to a `NatRatio`. Fails if the --- | denominator is `zero` or the overall sign is negative. -fromBigInts :: BigInt -> BigInt -> Maybe NatRatio -fromBigInts n d - | (n < zero) == (d < zero) = NatRatio <$> n Rational.% d - | otherwise = Nothing - --- | Get the numerator of a `NatRatio` as `BigInt`. -numerator :: NatRatio -> BigInt -numerator (NatRatio r) = Rational.numerator r - --- This is safe because the numerator is guaranteed to be non-negative. --- | Get the numerator of a `NatRatio` as `Natural`. -numeratorAsNat :: NatRatio -> Natural -numeratorAsNat (NatRatio r) = Nat.fromBigInt' $ Rational.numerator r - --- | Get the denominator of a `NatRatio` as `BigInt`. -denominator :: NatRatio -> BigInt -denominator (NatRatio r) = Rational.denominator r - --- This is safe because the denominator is guaranteed to be positive. --- | Get the denominator of a `NatRatio` as `Natural`. -denominatorAsNat :: NatRatio -> Natural -denominatorAsNat (NatRatio r) = Rational.denominatorAsNat r diff --git a/src/Internal/Types/Natural.purs b/src/Internal/Types/Natural.purs deleted file mode 100644 index ac94710c01..0000000000 --- a/src/Internal/Types/Natural.purs +++ /dev/null @@ -1,112 +0,0 @@ --- | Arbitrary precision natural numbers (backed by `BigInt`). -module Ctl.Internal.Types.Natural - ( (^-) - , Natural - , binaryOnBigInt - , fromBigInt - , fromBigInt' - , fromInt - , fromInt' - , fromString - , minus - , toBigInt - ) where - -import Prelude - -import Aeson (class DecodeAeson, JsonDecodeError(TypeMismatch), caseAesonBigInt) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.PlutusData (PlutusData(Integer)) -import Data.Either (Either(Left), note) -import Data.Function (on) -import Data.Maybe (Maybe(Nothing, Just), fromMaybe) -import JS.BigInt (BigInt) -import JS.BigInt (fromInt, fromString) as BigInt - -newtype Natural = Natural BigInt - -derive newtype instance Eq Natural -derive newtype instance Ord Natural -derive newtype instance Semiring Natural -derive newtype instance FromMetadata Natural -derive newtype instance ToMetadata Natural - -instance Show Natural where - show (Natural n) = "(fromBigInt' (BigInt." <> show n <> "))" - -instance FromData Natural where - fromData (Integer n) = fromBigInt n - fromData _ = Nothing - -instance ToData Natural where - toData (Natural n) = toData n - -instance DecodeAeson Natural where - decodeAeson = - caseAesonBigInt - (Left $ TypeMismatch "Expected BigInt from Aeson decoding") - ( \bi -> note (TypeMismatch $ "Invalid Natural number: " <> show bi) $ - fromBigInt bi - ) - -type MNatural = Maybe Natural - --- | Attempts to convert an instance of `Semiring` to `Natural`. --- | Fails with `Nothing` on negative input. -fromSemiringType - :: forall (a :: Type). Semiring a => Ord a => (a -> BigInt) -> a -> MNatural -fromSemiringType f n - | n >= zero = Just (Natural $ f n) - | otherwise = Nothing - --- | Converts an instance of `Semiring` to `Natural`. --- | If the input is negative, negates it. -fromSemiringType' - :: forall (a :: Type). Semiring a => Ord a => (a -> BigInt) -> a -> Natural -fromSemiringType' f n - | n >= zero = Natural (f n) - | otherwise = Natural (negate $ f n) - --- | Attempts to convert `BigInt` to `Natural`. --- | Fails with `Nothing` on negative input. -fromBigInt :: BigInt -> Maybe Natural -fromBigInt = fromSemiringType identity - --- | Converts `BigInt` to `Natural`. Negates `BigInt` if it's negative. -fromBigInt' :: BigInt -> Natural -fromBigInt' = fromSemiringType' identity - --- | Unwraps `Natural` and returns the underlying `BigInt`. -toBigInt :: Natural -> BigInt -toBigInt (Natural n) = n - --- | Attempts to convert `Int` to `Natural`. --- | Fails with `Nothing` on negative input. -fromInt :: Int -> Maybe Natural -fromInt = fromSemiringType BigInt.fromInt - --- | Converts `Int` to `Natural`. Negates `Int` if it's negative. -fromInt' :: Int -> Natural -fromInt' = fromSemiringType' BigInt.fromInt - --- | Attempts to build `Natural` from `String`. -fromString :: String -> Maybe Natural -fromString = fromBigInt <=< BigInt.fromString - --- | Use an arbitrary binary operation on the underlying `BigInt` for two --- | natural numbers to return a natural number with potential failure if the --- | output is not natural. -binaryOnBigInt - :: (BigInt -> BigInt -> BigInt) -> Natural -> Natural -> Maybe Natural -binaryOnBigInt bin n = fromBigInt <<< (bin `on` toBigInt) n - --- | Subtracts one natural number from another via `BigInt`. If the number --- | becomes negative, we return zero. -minus :: Natural -> Natural -> Natural -minus n = fromMaybe zero <<< binaryOnBigInt (-) n - --- Part of an `AdditiveHemigroup` notation but we'll use this for now. -infixl 6 minus as ^- diff --git a/src/Internal/Types/OutputDatum.purs b/src/Internal/Types/OutputDatum.purs deleted file mode 100644 index cb4ff8f335..0000000000 --- a/src/Internal/Types/OutputDatum.purs +++ /dev/null @@ -1,105 +0,0 @@ -module Ctl.Internal.Types.OutputDatum - ( OutputDatum(NoOutputDatum, OutputDatumHash, OutputDatum) - , outputDatumDataHash - , outputDatumDatum - , pprintOutputDatum - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch, UnexpectedValue) - , caseAesonObject - , fromString - , toStringifiedNumbersJson - , (.:) - ) -import Ctl.Internal.FromData (class FromData, genericFromData) -import Ctl.Internal.Helpers (encodeTagged') -import Ctl.Internal.Plutus.Types.DataSchema - ( class HasPlutusSchema - , type (:+) - , type (:=) - , type (@@) - , PNil - ) -import Ctl.Internal.ToData (class ToData, genericToData) -import Ctl.Internal.TypeLevel.Nat (S, Z) -import Ctl.Internal.Types.ByteArray (byteArrayToHex) -import Ctl.Internal.Types.Datum (Datum) -import Ctl.Internal.Types.PlutusData (pprintPlutusData) -import Ctl.Internal.Types.Transaction (DataHash) -import Data.Either (Either(Left)) -import Data.Generic.Rep (class Generic) -import Data.Log.Tag (TagSet, tag, tagSetTag) -import Data.Log.Tag as TagSet -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (unwrap) -import Data.Show.Generic (genericShow) - -data OutputDatum = NoOutputDatum | OutputDatumHash DataHash | OutputDatum Datum - -derive instance Generic OutputDatum _ -derive instance Eq OutputDatum - -instance Show OutputDatum where - show = genericShow - -instance - HasPlutusSchema OutputDatum - ( "NoOutputDatum" := PNil @@ Z - :+ "OutputDatumHash" - := PNil - @@ (S Z) - :+ "OutputDatum" - := PNil - @@ (S (S Z)) - :+ PNil - ) - -instance ToData OutputDatum where - toData = genericToData - -instance FromData OutputDatum where - fromData = genericFromData - -instance EncodeAeson OutputDatum where - encodeAeson = case _ of - NoOutputDatum -> encodeTagged' "NoOutputDatum" {} - OutputDatumHash r -> encodeTagged' "OutputDatumHash" r - OutputDatum r -> encodeTagged' "OutputDatum" r - -instance DecodeAeson OutputDatum where - decodeAeson = caseAesonObject (Left $ TypeMismatch "Expected object") $ - \obj -> do - tag <- obj .: "tag" - case tag of - "NoOutputDatum" -> - pure NoOutputDatum - "OutputDatumHash" -> do - dataHash <- obj .: "contents" - pure $ OutputDatumHash dataHash - "OutputDatum" -> do - datum <- obj .: "contents" - pure $ OutputDatum datum - tagValue -> do - Left $ UnexpectedValue $ toStringifiedNumbersJson $ fromString - tagValue - -pprintOutputDatum :: OutputDatum -> TagSet -pprintOutputDatum = TagSet.fromArray <<< case _ of - NoOutputDatum -> [ "datum" `tag` "none" ] - OutputDatumHash hash -> - [ "datumHash" `tag` byteArrayToHex (unwrap hash) ] - OutputDatum d -> - [ "datum" `tagSetTag` pprintPlutusData (unwrap d) ] - -outputDatumDataHash :: OutputDatum -> Maybe DataHash -outputDatumDataHash (OutputDatumHash hash) = Just hash -outputDatumDataHash _ = Nothing - -outputDatumDatum :: OutputDatum -> Maybe Datum -outputDatumDatum (OutputDatum datum) = Just datum -outputDatumDatum _ = Nothing diff --git a/src/Internal/Types/PaymentPubKey.purs b/src/Internal/Types/PaymentPubKey.purs deleted file mode 100644 index c1c53669b2..0000000000 --- a/src/Internal/Types/PaymentPubKey.purs +++ /dev/null @@ -1,36 +0,0 @@ -module Ctl.Internal.Types.PaymentPubKey - ( PaymentPubKey(PaymentPubKey) - , paymentPubKeyToRequiredSigner - , paymentPubKeyToVkey - ) where - -import Prelude - -import Ctl.Internal.Cardano.Types.Transaction - ( PublicKey - , RequiredSigner(RequiredSigner) - , Vkey(Vkey) - , convertPubKey - ) -import Ctl.Internal.Serialization (publicKeyHash) -import Data.Generic.Rep (class Generic) -import Data.Newtype (class Newtype) -import Data.Show.Generic (genericShow) - --- Plutus has a type called `PubKey` which we replace with `PublicKey` -newtype PaymentPubKey = PaymentPubKey PublicKey - -derive instance Generic PaymentPubKey _ -derive instance Newtype PaymentPubKey _ -derive newtype instance Eq PaymentPubKey -derive newtype instance Ord PaymentPubKey - -instance Show PaymentPubKey where - show = genericShow - -paymentPubKeyToVkey :: PaymentPubKey -> Vkey -paymentPubKeyToVkey (PaymentPubKey pk) = Vkey pk - -paymentPubKeyToRequiredSigner :: PaymentPubKey -> RequiredSigner -paymentPubKeyToRequiredSigner (PaymentPubKey pk) = - RequiredSigner <<< publicKeyHash $ convertPubKey pk diff --git a/src/Internal/Types/PlutusData.purs b/src/Internal/Types/PlutusData.purs deleted file mode 100644 index d9a67c594e..0000000000 --- a/src/Internal/Types/PlutusData.purs +++ /dev/null @@ -1,133 +0,0 @@ -module Ctl.Internal.Types.PlutusData - ( PlutusData - ( Constr - , Map - , List - , Integer - , Bytes - ) - , pprintPlutusData - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(UnexpectedValue) - , decodeAeson - , encodeAeson - , toStringifiedNumbersJson - , (.:) - ) -import Control.Alt ((<|>)) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum as BigNum -import Ctl.Internal.Types.ByteArray (ByteArray, byteArrayToHex, hexToByteArray) -import Data.Either (Either(Left)) -import Data.Generic.Rep (class Generic) -import Data.Log.Tag (TagSet, tag, tagSetTag) -import Data.Log.Tag as TagSet -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Show.Generic (genericShow) -import Data.Traversable (for) -import Data.Tuple (Tuple) -import Data.Tuple.Nested ((/\)) -import JS.BigInt (BigInt) -import JS.BigInt as BigInt - --- Doesn't distinguish "BuiltinData" and "Data" like Plutus: -data PlutusData - = Constr BigNum (Array PlutusData) - | Map (Array (Tuple PlutusData PlutusData)) - | List (Array PlutusData) - | Integer BigInt - | Bytes ByteArray - -derive instance Eq PlutusData -derive instance Ord PlutusData -derive instance Generic PlutusData _ - -instance Show PlutusData where - show x = genericShow x - --- Based off Ogmios Datum Cache Json format, although we no longer use ODC -instance DecodeAeson PlutusData where - decodeAeson aeson = decodeConstr - <|> decodeMap - <|> decodeList - <|> decodeInteger - <|> decodeBytes - where - decodeConstr :: Either JsonDecodeError PlutusData - decodeConstr = do - x <- decodeAeson aeson - constr <- x .: "constr" - fields <- x .: "fields" - pure $ Constr constr fields - - decodeMap :: Either JsonDecodeError PlutusData - decodeMap = do - obj <- decodeAeson aeson - map1 <- (obj .: "map" :: Either _ (Array _)) - kvs <- for map1 \entryJson -> do - key <- entryJson .: "key" - value <- entryJson .: "value" - pure $ key /\ value - pure $ Map kvs - - decodeList :: Either JsonDecodeError PlutusData - decodeList = do - List <$> decodeAeson aeson - - decodeInteger :: Either JsonDecodeError PlutusData - decodeInteger = do - Integer <$> decodeAeson aeson - - decodeBytes :: Either JsonDecodeError PlutusData - decodeBytes = do - bytesHex <- decodeAeson aeson - case hexToByteArray bytesHex of - Nothing -> Left $ UnexpectedValue $ toStringifiedNumbersJson $ - encodeAeson bytesHex - Just res -> pure $ Bytes res - -instance EncodeAeson PlutusData where - encodeAeson (Constr constr fields) = encodeAeson - { "constr": constr - , "fields": fields - } - encodeAeson (Map elems) = encodeAeson - { "map": encodeAeson $ map - ( \(k /\ v) -> - { "key": k - , "value": v - } - ) - elems - } - encodeAeson (List elems) = encodeAeson elems - encodeAeson (Integer bi) = encodeAeson bi - encodeAeson (Bytes ba) = encodeAeson ba - -pprintPlutusData :: PlutusData -> TagSet -pprintPlutusData (Constr n children) = TagSet.fromArray - [ ("Constr " <> BigInt.toString (BigNum.toBigInt n)) `tagSetTag` - TagSet.fromArray (pprintPlutusData <$> children) - ] -pprintPlutusData (Map entries) = TagSet.fromArray - [ tagSetTag "Map" $ TagSet.fromArray $ - entries <#> \(key /\ value) -> - TagSet.fromArray - [ "key" `tagSetTag` pprintPlutusData key - , "value" `tagSetTag` pprintPlutusData value - ] - ] -pprintPlutusData (List children) = TagSet.fromArray - [ tagSetTag "List" $ TagSet.fromArray $ - children <#> pprintPlutusData - ] -pprintPlutusData (Integer n) = TagSet.fromArray - [ "Integer" `tag` BigInt.toString n ] -pprintPlutusData (Bytes bytes) = TagSet.fromArray - [ "Bytes" `tag` byteArrayToHex bytes ] diff --git a/src/Internal/Types/ProtocolParameters.purs b/src/Internal/Types/ProtocolParameters.purs index 4a78635594..36b74c3a5c 100644 --- a/src/Internal/Types/ProtocolParameters.purs +++ b/src/Internal/Types/ProtocolParameters.purs @@ -1,54 +1,51 @@ module Ctl.Internal.Types.ProtocolParameters ( ProtocolParameters(ProtocolParameters) - , CoinsPerUtxoUnit(CoinsPerUtxoByte, CoinsPerUtxoWord) , CostModelV1 , CostModelV2 + , CostModelV3 , convertPlutusV1CostModel , convertPlutusV2CostModel + , convertPlutusV3CostModel ) where import Prelude -import Ctl.Internal.Cardano.Types.Transaction - ( Costmdls - , ExUnitPrices - , ExUnits - , Nonce - ) -import Ctl.Internal.Cardano.Types.Transaction as T -import Ctl.Internal.Cardano.Types.Value (Coin) -import Ctl.Internal.Types.Epoch (Epoch) -import Ctl.Internal.Types.Int as Csl +import Cardano.Types.Coin (Coin) +import Cardano.Types.CostModel (CostModel) +import Cardano.Types.Epoch (Epoch) +import Cardano.Types.ExUnitPrices (ExUnitPrices) +import Cardano.Types.ExUnits (ExUnits) +import Cardano.Types.Int as Cardano +import Cardano.Types.Language (Language) import Ctl.Internal.Types.Rational (Rational) import Data.Array (reverse) +import Data.Array (sortWith) as Array +import Data.Bitraversable (ltraverse) import Data.Generic.Rep (class Generic) +import Data.Int (fromString) as Int import Data.List (List) import Data.List as List +import Data.Map (Map) import Data.Maybe (Maybe) import Data.Newtype (class Newtype, wrap) import Data.Show.Generic (genericShow) +import Data.Traversable (traverse) +import Data.Tuple (fst, snd) import Data.Tuple.Nested (type (/\)) import Data.UInt (UInt) +import Foreign.Object (Object) +import Foreign.Object (toUnfoldable) as Object import Heterogeneous.Folding (class HFoldl, hfoldl) -data CoinsPerUtxoUnit = CoinsPerUtxoByte Coin | CoinsPerUtxoWord Coin - -derive instance Generic CoinsPerUtxoUnit _ -derive instance Eq CoinsPerUtxoUnit - -instance Show CoinsPerUtxoUnit where - show = genericShow - -- Based on `Cardano.Api.ProtocolParameters.ProtocolParameters` from -- `cardano-api`. newtype ProtocolParameters = ProtocolParameters { protocolVersion :: UInt /\ UInt , decentralization :: Rational - , extraPraosEntropy :: Maybe Nonce , maxBlockHeaderSize :: UInt , maxBlockBodySize :: UInt , maxTxSize :: UInt - , txFeeFixed :: UInt + , txFeeFixed :: Coin , txFeePerByte :: UInt , stakeAddressDeposit :: Coin , stakePoolDeposit :: Coin @@ -58,14 +55,16 @@ newtype ProtocolParameters = ProtocolParameters , poolPledgeInfluence :: Rational , monetaryExpansion :: Rational , treasuryCut :: Rational - , coinsPerUtxoUnit :: CoinsPerUtxoUnit - , costModels :: Costmdls + , coinsPerUtxoByte :: Coin + , costModels :: Map Language CostModel , prices :: ExUnitPrices , maxTxExUnits :: ExUnits , maxBlockExUnits :: ExUnits , maxValueSize :: UInt , collateralPercent :: UInt , maxCollateralInputs :: UInt + , govActionDeposit :: Coin + , drepDeposit :: Coin } derive instance Newtype ProtocolParameters _ @@ -77,203 +76,214 @@ instance Show ProtocolParameters where -- | A type that represents a JSON-encoded Costmodel in format used by Ogmios type CostModelV1 = - ( "addInteger-cpu-arguments-intercept" :: Csl.Int - , "addInteger-cpu-arguments-slope" :: Csl.Int - , "addInteger-memory-arguments-intercept" :: Csl.Int - , "addInteger-memory-arguments-slope" :: Csl.Int - , "appendByteString-cpu-arguments-intercept" :: Csl.Int - , "appendByteString-cpu-arguments-slope" :: Csl.Int - , "appendByteString-memory-arguments-intercept" :: Csl.Int - , "appendByteString-memory-arguments-slope" :: Csl.Int - , "appendString-cpu-arguments-intercept" :: Csl.Int - , "appendString-cpu-arguments-slope" :: Csl.Int - , "appendString-memory-arguments-intercept" :: Csl.Int - , "appendString-memory-arguments-slope" :: Csl.Int - , "bData-cpu-arguments" :: Csl.Int - , "bData-memory-arguments" :: Csl.Int - , "blake2b_256-cpu-arguments-intercept" :: Csl.Int - , "blake2b_256-cpu-arguments-slope" :: Csl.Int - , "blake2b_256-memory-arguments" :: Csl.Int - , "cekApplyCost-exBudgetCPU" :: Csl.Int - , "cekApplyCost-exBudgetMemory" :: Csl.Int - , "cekBuiltinCost-exBudgetCPU" :: Csl.Int - , "cekBuiltinCost-exBudgetMemory" :: Csl.Int - , "cekConstCost-exBudgetCPU" :: Csl.Int - , "cekConstCost-exBudgetMemory" :: Csl.Int - , "cekDelayCost-exBudgetCPU" :: Csl.Int - , "cekDelayCost-exBudgetMemory" :: Csl.Int - , "cekForceCost-exBudgetCPU" :: Csl.Int - , "cekForceCost-exBudgetMemory" :: Csl.Int - , "cekLamCost-exBudgetCPU" :: Csl.Int - , "cekLamCost-exBudgetMemory" :: Csl.Int - , "cekStartupCost-exBudgetCPU" :: Csl.Int - , "cekStartupCost-exBudgetMemory" :: Csl.Int - , "cekVarCost-exBudgetCPU" :: Csl.Int - , "cekVarCost-exBudgetMemory" :: Csl.Int - , "chooseData-cpu-arguments" :: Csl.Int - , "chooseData-memory-arguments" :: Csl.Int - , "chooseList-cpu-arguments" :: Csl.Int - , "chooseList-memory-arguments" :: Csl.Int - , "chooseUnit-cpu-arguments" :: Csl.Int - , "chooseUnit-memory-arguments" :: Csl.Int - , "consByteString-cpu-arguments-intercept" :: Csl.Int - , "consByteString-cpu-arguments-slope" :: Csl.Int - , "consByteString-memory-arguments-intercept" :: Csl.Int - , "consByteString-memory-arguments-slope" :: Csl.Int - , "constrData-cpu-arguments" :: Csl.Int - , "constrData-memory-arguments" :: Csl.Int - , "decodeUtf8-cpu-arguments-intercept" :: Csl.Int - , "decodeUtf8-cpu-arguments-slope" :: Csl.Int - , "decodeUtf8-memory-arguments-intercept" :: Csl.Int - , "decodeUtf8-memory-arguments-slope" :: Csl.Int - , "divideInteger-cpu-arguments-constant" :: Csl.Int - , "divideInteger-cpu-arguments-model-arguments-intercept" :: Csl.Int - , "divideInteger-cpu-arguments-model-arguments-slope" :: Csl.Int - , "divideInteger-memory-arguments-intercept" :: Csl.Int - , "divideInteger-memory-arguments-minimum" :: Csl.Int - , "divideInteger-memory-arguments-slope" :: Csl.Int - , "encodeUtf8-cpu-arguments-intercept" :: Csl.Int - , "encodeUtf8-cpu-arguments-slope" :: Csl.Int - , "encodeUtf8-memory-arguments-intercept" :: Csl.Int - , "encodeUtf8-memory-arguments-slope" :: Csl.Int - , "equalsByteString-cpu-arguments-constant" :: Csl.Int - , "equalsByteString-cpu-arguments-intercept" :: Csl.Int - , "equalsByteString-cpu-arguments-slope" :: Csl.Int - , "equalsByteString-memory-arguments" :: Csl.Int - , "equalsData-cpu-arguments-intercept" :: Csl.Int - , "equalsData-cpu-arguments-slope" :: Csl.Int - , "equalsData-memory-arguments" :: Csl.Int - , "equalsInteger-cpu-arguments-intercept" :: Csl.Int - , "equalsInteger-cpu-arguments-slope" :: Csl.Int - , "equalsInteger-memory-arguments" :: Csl.Int - , "equalsString-cpu-arguments-constant" :: Csl.Int - , "equalsString-cpu-arguments-intercept" :: Csl.Int - , "equalsString-cpu-arguments-slope" :: Csl.Int - , "equalsString-memory-arguments" :: Csl.Int - , "fstPair-cpu-arguments" :: Csl.Int - , "fstPair-memory-arguments" :: Csl.Int - , "headList-cpu-arguments" :: Csl.Int - , "headList-memory-arguments" :: Csl.Int - , "iData-cpu-arguments" :: Csl.Int - , "iData-memory-arguments" :: Csl.Int - , "ifThenElse-cpu-arguments" :: Csl.Int - , "ifThenElse-memory-arguments" :: Csl.Int - , "indexByteString-cpu-arguments" :: Csl.Int - , "indexByteString-memory-arguments" :: Csl.Int - , "lengthOfByteString-cpu-arguments" :: Csl.Int - , "lengthOfByteString-memory-arguments" :: Csl.Int - , "lessThanByteString-cpu-arguments-intercept" :: Csl.Int - , "lessThanByteString-cpu-arguments-slope" :: Csl.Int - , "lessThanByteString-memory-arguments" :: Csl.Int - , "lessThanEqualsByteString-cpu-arguments-intercept" :: Csl.Int - , "lessThanEqualsByteString-cpu-arguments-slope" :: Csl.Int - , "lessThanEqualsByteString-memory-arguments" :: Csl.Int - , "lessThanEqualsInteger-cpu-arguments-intercept" :: Csl.Int - , "lessThanEqualsInteger-cpu-arguments-slope" :: Csl.Int - , "lessThanEqualsInteger-memory-arguments" :: Csl.Int - , "lessThanInteger-cpu-arguments-intercept" :: Csl.Int - , "lessThanInteger-cpu-arguments-slope" :: Csl.Int - , "lessThanInteger-memory-arguments" :: Csl.Int - , "listData-cpu-arguments" :: Csl.Int - , "listData-memory-arguments" :: Csl.Int - , "mapData-cpu-arguments" :: Csl.Int - , "mapData-memory-arguments" :: Csl.Int - , "mkCons-cpu-arguments" :: Csl.Int - , "mkCons-memory-arguments" :: Csl.Int - , "mkNilData-cpu-arguments" :: Csl.Int - , "mkNilData-memory-arguments" :: Csl.Int - , "mkNilPairData-cpu-arguments" :: Csl.Int - , "mkNilPairData-memory-arguments" :: Csl.Int - , "mkPairData-cpu-arguments" :: Csl.Int - , "mkPairData-memory-arguments" :: Csl.Int - , "modInteger-cpu-arguments-constant" :: Csl.Int - , "modInteger-cpu-arguments-model-arguments-intercept" :: Csl.Int - , "modInteger-cpu-arguments-model-arguments-slope" :: Csl.Int - , "modInteger-memory-arguments-intercept" :: Csl.Int - , "modInteger-memory-arguments-minimum" :: Csl.Int - , "modInteger-memory-arguments-slope" :: Csl.Int - , "multiplyInteger-cpu-arguments-intercept" :: Csl.Int - , "multiplyInteger-cpu-arguments-slope" :: Csl.Int - , "multiplyInteger-memory-arguments-intercept" :: Csl.Int - , "multiplyInteger-memory-arguments-slope" :: Csl.Int - , "nullList-cpu-arguments" :: Csl.Int - , "nullList-memory-arguments" :: Csl.Int - , "quotientInteger-cpu-arguments-constant" :: Csl.Int - , "quotientInteger-cpu-arguments-model-arguments-intercept" :: Csl.Int - , "quotientInteger-cpu-arguments-model-arguments-slope" :: Csl.Int - , "quotientInteger-memory-arguments-intercept" :: Csl.Int - , "quotientInteger-memory-arguments-minimum" :: Csl.Int - , "quotientInteger-memory-arguments-slope" :: Csl.Int - , "remainderInteger-cpu-arguments-constant" :: Csl.Int - , "remainderInteger-cpu-arguments-model-arguments-intercept" :: Csl.Int - , "remainderInteger-cpu-arguments-model-arguments-slope" :: Csl.Int - , "remainderInteger-memory-arguments-intercept" :: Csl.Int - , "remainderInteger-memory-arguments-minimum" :: Csl.Int - , "remainderInteger-memory-arguments-slope" :: Csl.Int - , "sha2_256-cpu-arguments-intercept" :: Csl.Int - , "sha2_256-cpu-arguments-slope" :: Csl.Int - , "sha2_256-memory-arguments" :: Csl.Int - , "sha3_256-cpu-arguments-intercept" :: Csl.Int - , "sha3_256-cpu-arguments-slope" :: Csl.Int - , "sha3_256-memory-arguments" :: Csl.Int - , "sliceByteString-cpu-arguments-intercept" :: Csl.Int - , "sliceByteString-cpu-arguments-slope" :: Csl.Int - , "sliceByteString-memory-arguments-intercept" :: Csl.Int - , "sliceByteString-memory-arguments-slope" :: Csl.Int - , "sndPair-cpu-arguments" :: Csl.Int - , "sndPair-memory-arguments" :: Csl.Int - , "subtractInteger-cpu-arguments-intercept" :: Csl.Int - , "subtractInteger-cpu-arguments-slope" :: Csl.Int - , "subtractInteger-memory-arguments-intercept" :: Csl.Int - , "subtractInteger-memory-arguments-slope" :: Csl.Int - , "tailList-cpu-arguments" :: Csl.Int - , "tailList-memory-arguments" :: Csl.Int - , "trace-cpu-arguments" :: Csl.Int - , "trace-memory-arguments" :: Csl.Int - , "unBData-cpu-arguments" :: Csl.Int - , "unBData-memory-arguments" :: Csl.Int - , "unConstrData-cpu-arguments" :: Csl.Int - , "unConstrData-memory-arguments" :: Csl.Int - , "unIData-cpu-arguments" :: Csl.Int - , "unIData-memory-arguments" :: Csl.Int - , "unListData-cpu-arguments" :: Csl.Int - , "unListData-memory-arguments" :: Csl.Int - , "unMapData-cpu-arguments" :: Csl.Int - , "unMapData-memory-arguments" :: Csl.Int - , "verifyEd25519Signature-cpu-arguments-intercept" :: Csl.Int - , "verifyEd25519Signature-cpu-arguments-slope" :: Csl.Int - , "verifyEd25519Signature-memory-arguments" :: Csl.Int + ( "addInteger-cpu-arguments-intercept" :: Cardano.Int + , "addInteger-cpu-arguments-slope" :: Cardano.Int + , "addInteger-memory-arguments-intercept" :: Cardano.Int + , "addInteger-memory-arguments-slope" :: Cardano.Int + , "appendByteString-cpu-arguments-intercept" :: Cardano.Int + , "appendByteString-cpu-arguments-slope" :: Cardano.Int + , "appendByteString-memory-arguments-intercept" :: Cardano.Int + , "appendByteString-memory-arguments-slope" :: Cardano.Int + , "appendString-cpu-arguments-intercept" :: Cardano.Int + , "appendString-cpu-arguments-slope" :: Cardano.Int + , "appendString-memory-arguments-intercept" :: Cardano.Int + , "appendString-memory-arguments-slope" :: Cardano.Int + , "bData-cpu-arguments" :: Cardano.Int + , "bData-memory-arguments" :: Cardano.Int + , "blake2b_256-cpu-arguments-intercept" :: Cardano.Int + , "blake2b_256-cpu-arguments-slope" :: Cardano.Int + , "blake2b_256-memory-arguments" :: Cardano.Int + , "cekApplyCost-exBudgetCPU" :: Cardano.Int + , "cekApplyCost-exBudgetMemory" :: Cardano.Int + , "cekBuiltinCost-exBudgetCPU" :: Cardano.Int + , "cekBuiltinCost-exBudgetMemory" :: Cardano.Int + , "cekConstCost-exBudgetCPU" :: Cardano.Int + , "cekConstCost-exBudgetMemory" :: Cardano.Int + , "cekDelayCost-exBudgetCPU" :: Cardano.Int + , "cekDelayCost-exBudgetMemory" :: Cardano.Int + , "cekForceCost-exBudgetCPU" :: Cardano.Int + , "cekForceCost-exBudgetMemory" :: Cardano.Int + , "cekLamCost-exBudgetCPU" :: Cardano.Int + , "cekLamCost-exBudgetMemory" :: Cardano.Int + , "cekStartupCost-exBudgetCPU" :: Cardano.Int + , "cekStartupCost-exBudgetMemory" :: Cardano.Int + , "cekVarCost-exBudgetCPU" :: Cardano.Int + , "cekVarCost-exBudgetMemory" :: Cardano.Int + , "chooseData-cpu-arguments" :: Cardano.Int + , "chooseData-memory-arguments" :: Cardano.Int + , "chooseList-cpu-arguments" :: Cardano.Int + , "chooseList-memory-arguments" :: Cardano.Int + , "chooseUnit-cpu-arguments" :: Cardano.Int + , "chooseUnit-memory-arguments" :: Cardano.Int + , "consByteString-cpu-arguments-intercept" :: Cardano.Int + , "consByteString-cpu-arguments-slope" :: Cardano.Int + , "consByteString-memory-arguments-intercept" :: Cardano.Int + , "consByteString-memory-arguments-slope" :: Cardano.Int + , "constrData-cpu-arguments" :: Cardano.Int + , "constrData-memory-arguments" :: Cardano.Int + , "decodeUtf8-cpu-arguments-intercept" :: Cardano.Int + , "decodeUtf8-cpu-arguments-slope" :: Cardano.Int + , "decodeUtf8-memory-arguments-intercept" :: Cardano.Int + , "decodeUtf8-memory-arguments-slope" :: Cardano.Int + , "divideInteger-cpu-arguments-constant" :: Cardano.Int + , "divideInteger-cpu-arguments-model-arguments-intercept" :: Cardano.Int + , "divideInteger-cpu-arguments-model-arguments-slope" :: Cardano.Int + , "divideInteger-memory-arguments-intercept" :: Cardano.Int + , "divideInteger-memory-arguments-minimum" :: Cardano.Int + , "divideInteger-memory-arguments-slope" :: Cardano.Int + , "encodeUtf8-cpu-arguments-intercept" :: Cardano.Int + , "encodeUtf8-cpu-arguments-slope" :: Cardano.Int + , "encodeUtf8-memory-arguments-intercept" :: Cardano.Int + , "encodeUtf8-memory-arguments-slope" :: Cardano.Int + , "equalsByteString-cpu-arguments-constant" :: Cardano.Int + , "equalsByteString-cpu-arguments-intercept" :: Cardano.Int + , "equalsByteString-cpu-arguments-slope" :: Cardano.Int + , "equalsByteString-memory-arguments" :: Cardano.Int + , "equalsData-cpu-arguments-intercept" :: Cardano.Int + , "equalsData-cpu-arguments-slope" :: Cardano.Int + , "equalsData-memory-arguments" :: Cardano.Int + , "equalsInteger-cpu-arguments-intercept" :: Cardano.Int + , "equalsInteger-cpu-arguments-slope" :: Cardano.Int + , "equalsInteger-memory-arguments" :: Cardano.Int + , "equalsString-cpu-arguments-constant" :: Cardano.Int + , "equalsString-cpu-arguments-intercept" :: Cardano.Int + , "equalsString-cpu-arguments-slope" :: Cardano.Int + , "equalsString-memory-arguments" :: Cardano.Int + , "fstPair-cpu-arguments" :: Cardano.Int + , "fstPair-memory-arguments" :: Cardano.Int + , "headList-cpu-arguments" :: Cardano.Int + , "headList-memory-arguments" :: Cardano.Int + , "iData-cpu-arguments" :: Cardano.Int + , "iData-memory-arguments" :: Cardano.Int + , "ifThenElse-cpu-arguments" :: Cardano.Int + , "ifThenElse-memory-arguments" :: Cardano.Int + , "indexByteString-cpu-arguments" :: Cardano.Int + , "indexByteString-memory-arguments" :: Cardano.Int + , "lengthOfByteString-cpu-arguments" :: Cardano.Int + , "lengthOfByteString-memory-arguments" :: Cardano.Int + , "lessThanByteString-cpu-arguments-intercept" :: Cardano.Int + , "lessThanByteString-cpu-arguments-slope" :: Cardano.Int + , "lessThanByteString-memory-arguments" :: Cardano.Int + , "lessThanEqualsByteString-cpu-arguments-intercept" :: Cardano.Int + , "lessThanEqualsByteString-cpu-arguments-slope" :: Cardano.Int + , "lessThanEqualsByteString-memory-arguments" :: Cardano.Int + , "lessThanEqualsInteger-cpu-arguments-intercept" :: Cardano.Int + , "lessThanEqualsInteger-cpu-arguments-slope" :: Cardano.Int + , "lessThanEqualsInteger-memory-arguments" :: Cardano.Int + , "lessThanInteger-cpu-arguments-intercept" :: Cardano.Int + , "lessThanInteger-cpu-arguments-slope" :: Cardano.Int + , "lessThanInteger-memory-arguments" :: Cardano.Int + , "listData-cpu-arguments" :: Cardano.Int + , "listData-memory-arguments" :: Cardano.Int + , "mapData-cpu-arguments" :: Cardano.Int + , "mapData-memory-arguments" :: Cardano.Int + , "mkCons-cpu-arguments" :: Cardano.Int + , "mkCons-memory-arguments" :: Cardano.Int + , "mkNilData-cpu-arguments" :: Cardano.Int + , "mkNilData-memory-arguments" :: Cardano.Int + , "mkNilPairData-cpu-arguments" :: Cardano.Int + , "mkNilPairData-memory-arguments" :: Cardano.Int + , "mkPairData-cpu-arguments" :: Cardano.Int + , "mkPairData-memory-arguments" :: Cardano.Int + , "modInteger-cpu-arguments-constant" :: Cardano.Int + , "modInteger-cpu-arguments-model-arguments-intercept" :: Cardano.Int + , "modInteger-cpu-arguments-model-arguments-slope" :: Cardano.Int + , "modInteger-memory-arguments-intercept" :: Cardano.Int + , "modInteger-memory-arguments-minimum" :: Cardano.Int + , "modInteger-memory-arguments-slope" :: Cardano.Int + , "multiplyInteger-cpu-arguments-intercept" :: Cardano.Int + , "multiplyInteger-cpu-arguments-slope" :: Cardano.Int + , "multiplyInteger-memory-arguments-intercept" :: Cardano.Int + , "multiplyInteger-memory-arguments-slope" :: Cardano.Int + , "nullList-cpu-arguments" :: Cardano.Int + , "nullList-memory-arguments" :: Cardano.Int + , "quotientInteger-cpu-arguments-constant" :: Cardano.Int + , "quotientInteger-cpu-arguments-model-arguments-intercept" :: Cardano.Int + , "quotientInteger-cpu-arguments-model-arguments-slope" :: Cardano.Int + , "quotientInteger-memory-arguments-intercept" :: Cardano.Int + , "quotientInteger-memory-arguments-minimum" :: Cardano.Int + , "quotientInteger-memory-arguments-slope" :: Cardano.Int + , "remainderInteger-cpu-arguments-constant" :: Cardano.Int + , "remainderInteger-cpu-arguments-model-arguments-intercept" :: Cardano.Int + , "remainderInteger-cpu-arguments-model-arguments-slope" :: Cardano.Int + , "remainderInteger-memory-arguments-intercept" :: Cardano.Int + , "remainderInteger-memory-arguments-minimum" :: Cardano.Int + , "remainderInteger-memory-arguments-slope" :: Cardano.Int + , "sha2_256-cpu-arguments-intercept" :: Cardano.Int + , "sha2_256-cpu-arguments-slope" :: Cardano.Int + , "sha2_256-memory-arguments" :: Cardano.Int + , "sha3_256-cpu-arguments-intercept" :: Cardano.Int + , "sha3_256-cpu-arguments-slope" :: Cardano.Int + , "sha3_256-memory-arguments" :: Cardano.Int + , "sliceByteString-cpu-arguments-intercept" :: Cardano.Int + , "sliceByteString-cpu-arguments-slope" :: Cardano.Int + , "sliceByteString-memory-arguments-intercept" :: Cardano.Int + , "sliceByteString-memory-arguments-slope" :: Cardano.Int + , "sndPair-cpu-arguments" :: Cardano.Int + , "sndPair-memory-arguments" :: Cardano.Int + , "subtractInteger-cpu-arguments-intercept" :: Cardano.Int + , "subtractInteger-cpu-arguments-slope" :: Cardano.Int + , "subtractInteger-memory-arguments-intercept" :: Cardano.Int + , "subtractInteger-memory-arguments-slope" :: Cardano.Int + , "tailList-cpu-arguments" :: Cardano.Int + , "tailList-memory-arguments" :: Cardano.Int + , "trace-cpu-arguments" :: Cardano.Int + , "trace-memory-arguments" :: Cardano.Int + , "unBData-cpu-arguments" :: Cardano.Int + , "unBData-memory-arguments" :: Cardano.Int + , "unConstrData-cpu-arguments" :: Cardano.Int + , "unConstrData-memory-arguments" :: Cardano.Int + , "unIData-cpu-arguments" :: Cardano.Int + , "unIData-memory-arguments" :: Cardano.Int + , "unListData-cpu-arguments" :: Cardano.Int + , "unListData-memory-arguments" :: Cardano.Int + , "unMapData-cpu-arguments" :: Cardano.Int + , "unMapData-memory-arguments" :: Cardano.Int + , "verifyEd25519Signature-cpu-arguments-intercept" :: Cardano.Int + , "verifyEd25519Signature-cpu-arguments-slope" :: Cardano.Int + , "verifyEd25519Signature-memory-arguments" :: Cardano.Int ) type CostModelV2 = - ( "serialiseData-cpu-arguments-intercept" :: Csl.Int - , "serialiseData-cpu-arguments-slope" :: Csl.Int - , "serialiseData-memory-arguments-intercept" :: Csl.Int - , "serialiseData-memory-arguments-slope" :: Csl.Int - , "verifyEcdsaSecp256k1Signature-cpu-arguments" :: Csl.Int - , "verifyEcdsaSecp256k1Signature-memory-arguments" :: Csl.Int - , "verifySchnorrSecp256k1Signature-cpu-arguments-intercept" :: Csl.Int - , "verifySchnorrSecp256k1Signature-cpu-arguments-slope" :: Csl.Int - , "verifySchnorrSecp256k1Signature-memory-arguments" :: Csl.Int + ( "serialiseData-cpu-arguments-intercept" :: Cardano.Int + , "serialiseData-cpu-arguments-slope" :: Cardano.Int + , "serialiseData-memory-arguments-intercept" :: Cardano.Int + , "serialiseData-memory-arguments-slope" :: Cardano.Int + , "verifyEcdsaSecp256k1Signature-cpu-arguments" :: Cardano.Int + , "verifyEcdsaSecp256k1Signature-memory-arguments" :: Cardano.Int + , "verifySchnorrSecp256k1Signature-cpu-arguments-intercept" :: Cardano.Int + , "verifySchnorrSecp256k1Signature-cpu-arguments-slope" :: Cardano.Int + , "verifySchnorrSecp256k1Signature-memory-arguments" :: Cardano.Int | CostModelV1 ) +type CostModelV3 = Object Cardano.Int + -- This assumes that cost models are stored in lexicographical order convertCostModel :: forall costModel - . HFoldl (List Csl.Int -> Csl.Int -> List Csl.Int) (List Csl.Int) costModel - (List Csl.Int) + . HFoldl (List Cardano.Int -> Cardano.Int -> List Cardano.Int) + (List Cardano.Int) + costModel + (List Cardano.Int) => costModel - -> T.CostModel + -> CostModel convertCostModel model = wrap $ reverse $ List.toUnfoldable $ hfoldl - ((\xs x -> x List.: xs) :: List Csl.Int -> Csl.Int -> List Csl.Int) - (mempty :: List Csl.Int) + ( (\xs x -> x List.: xs) + :: List Cardano.Int -> Cardano.Int -> List Cardano.Int + ) + (mempty :: List Cardano.Int) model -- Specialized conversions to only perform the type level traversals once -convertPlutusV1CostModel :: Record CostModelV1 -> T.CostModel +convertPlutusV1CostModel :: Record CostModelV1 -> CostModel convertPlutusV1CostModel = convertCostModel -convertPlutusV2CostModel :: Record CostModelV2 -> T.CostModel +convertPlutusV2CostModel :: Record CostModelV2 -> CostModel convertPlutusV2CostModel = convertCostModel + +convertPlutusV3CostModel :: CostModelV3 -> Maybe CostModel +convertPlutusV3CostModel costModelRaw = + wrap <<< map snd <<< Array.sortWith fst <$> + traverse (ltraverse Int.fromString) (Object.toUnfoldable costModelRaw) diff --git a/src/Internal/Types/PubKeyHash.purs b/src/Internal/Types/PubKeyHash.purs deleted file mode 100644 index ffb6398fe0..0000000000 --- a/src/Internal/Types/PubKeyHash.purs +++ /dev/null @@ -1,154 +0,0 @@ -module Ctl.Internal.Types.PubKeyHash - ( PaymentPubKeyHash(PaymentPubKeyHash) - , PubKeyHash(PubKeyHash) - , StakePubKeyHash(StakePubKeyHash) - , payPubKeyHashBaseAddress - , payPubKeyHashEnterpriseAddress - , payPubKeyHashRewardAddress - , pubKeyHashBaseAddress - , pubKeyHashEnterpriseAddress - , pubKeyHashRewardAddress - , stakePubKeyHashRewardAddress - , ed25519RewardAddress - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , decodeAeson - , encodeAeson - , (.:) - ) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata) -import Ctl.Internal.Serialization.Address - ( Address - , EnterpriseAddress - , NetworkId - , RewardAddress - , baseAddressToAddress - , enterpriseAddress - , enterpriseAddressToAddress - , keyHashCredential - , paymentKeyHashStakeKeyHashAddress - , rewardAddress - , rewardAddressToAddress - ) -import Ctl.Internal.Serialization.Hash (Ed25519KeyHash) -import Ctl.Internal.ToData (class ToData) -import Data.Generic.Rep (class Generic) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Show.Generic (genericShow) - -newtype PubKeyHash = PubKeyHash Ed25519KeyHash - -derive instance Generic PubKeyHash _ -derive instance Newtype PubKeyHash _ -derive newtype instance Eq PubKeyHash -derive newtype instance FromData PubKeyHash -derive newtype instance FromMetadata PubKeyHash -derive newtype instance Ord PubKeyHash -derive newtype instance ToData PubKeyHash -derive newtype instance ToMetadata PubKeyHash - -instance Show PubKeyHash where - show = genericShow - -instance EncodeAeson PubKeyHash where - encodeAeson x = encodeAeson { getPubKeyHash: unwrap x } - -instance DecodeAeson PubKeyHash where - decodeAeson a = do - obj <- decodeAeson a - wrap <$> obj .: "getPubKeyHash" - -ed25519EnterpriseAddress - :: forall (n :: Type) - . Newtype n Ed25519KeyHash - => NetworkId - -> n - -> EnterpriseAddress -ed25519EnterpriseAddress network pkh = - enterpriseAddress - { network - , paymentCred: keyHashCredential (unwrap pkh) - } - -ed25519RewardAddress - :: forall (n :: Type) - . Newtype n Ed25519KeyHash - => NetworkId - -> n - -> RewardAddress -ed25519RewardAddress network skh = - rewardAddress - { network - , paymentCred: keyHashCredential (unwrap skh) - } - -pubKeyHashBaseAddress :: NetworkId -> PubKeyHash -> StakePubKeyHash -> Address -pubKeyHashBaseAddress networkId pkh skh = - baseAddressToAddress $ paymentKeyHashStakeKeyHashAddress networkId - (unwrap pkh) - (unwrap $ unwrap skh) - -pubKeyHashRewardAddress :: NetworkId -> PubKeyHash -> Address -pubKeyHashRewardAddress networkId = - rewardAddressToAddress <<< ed25519RewardAddress networkId - -pubKeyHashEnterpriseAddress :: NetworkId -> PubKeyHash -> Address -pubKeyHashEnterpriseAddress networkId = - enterpriseAddressToAddress <<< ed25519EnterpriseAddress networkId - -newtype PaymentPubKeyHash = PaymentPubKeyHash PubKeyHash - -derive instance Generic PaymentPubKeyHash _ -derive instance Newtype PaymentPubKeyHash _ -derive newtype instance Eq PaymentPubKeyHash -derive newtype instance FromData PaymentPubKeyHash -derive newtype instance Ord PaymentPubKeyHash -derive newtype instance ToData PaymentPubKeyHash - -instance EncodeAeson PaymentPubKeyHash where - encodeAeson (PaymentPubKeyHash pkh) = encodeAeson - { "unPaymentPubKeyHash": pkh } - -instance DecodeAeson PaymentPubKeyHash where - decodeAeson json = do - obj <- decodeAeson json - PaymentPubKeyHash <<< PubKeyHash <$> obj .: "unPaymentPubKeyHash" - -instance Show PaymentPubKeyHash where - show = genericShow - -newtype StakePubKeyHash = StakePubKeyHash PubKeyHash - -derive instance Generic StakePubKeyHash _ -derive instance Newtype StakePubKeyHash _ -derive newtype instance Eq StakePubKeyHash -derive newtype instance FromData StakePubKeyHash -derive newtype instance Ord StakePubKeyHash -derive newtype instance ToData StakePubKeyHash - -instance Show StakePubKeyHash where - show = genericShow - -payPubKeyHashRewardAddress :: NetworkId -> PaymentPubKeyHash -> Address -payPubKeyHashRewardAddress networkId (PaymentPubKeyHash pkh) = - pubKeyHashRewardAddress networkId pkh - -payPubKeyHashBaseAddress - :: NetworkId -> PaymentPubKeyHash -> StakePubKeyHash -> Address -payPubKeyHashBaseAddress networkId (PaymentPubKeyHash pkh) skh = - pubKeyHashBaseAddress networkId pkh skh - -payPubKeyHashEnterpriseAddress :: NetworkId -> PaymentPubKeyHash -> Address -payPubKeyHashEnterpriseAddress networkId (PaymentPubKeyHash pkh) = - pubKeyHashEnterpriseAddress networkId pkh - -stakePubKeyHashRewardAddress :: NetworkId -> StakePubKeyHash -> Address -stakePubKeyHashRewardAddress networkId = - rewardAddressToAddress <<< ed25519RewardAddress networkId <<< unwrap diff --git a/src/Internal/Types/Rational.purs b/src/Internal/Types/Rational.purs index 4b7d940c2b..69a92563f7 100644 --- a/src/Internal/Types/Rational.purs +++ b/src/Internal/Types/Rational.purs @@ -6,7 +6,6 @@ module Ctl.Internal.Types.Rational , recip , numerator , denominator - , denominatorAsNat ) where import Prelude @@ -20,12 +19,10 @@ import Aeson , toStringifiedNumbersJson , (.:) ) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.ToData (class ToData) -import Ctl.Internal.Types.BigNum as BigNum -import Ctl.Internal.Types.Natural (Natural) -import Ctl.Internal.Types.Natural (fromBigInt', toBigInt) as Nat -import Ctl.Internal.Types.PlutusData (PlutusData(Constr, Integer)) +import Cardano.FromData (class FromData) +import Cardano.ToData (class ToData) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.PlutusData (PlutusData(Constr, Integer)) import Data.Either (Either(Left)) import Data.Maybe (Maybe(Just, Nothing), maybe) import Data.Ratio (Ratio) @@ -92,11 +89,6 @@ numerator (Rational r) = Ratio.numerator r denominator :: Rational -> BigInt denominator (Rational r) = Ratio.denominator r --- This is safe because the denominator is guaranteed to be positive. --- | Get the denominator of a `Rational` as `Natural`. -denominatorAsNat :: Rational -> Natural -denominatorAsNat = Nat.fromBigInt' <<< denominator - -------------------------------------------------------------------------------- -- FromData / ToData -------------------------------------------------------------------------------- @@ -132,6 +124,3 @@ instance RationalComponent BigInt where instance RationalComponent Int where reduce n d = reduce (BigInt.fromInt n) (BigInt.fromInt d) - -instance RationalComponent Natural where - reduce n d = reduce (Nat.toBigInt n) (Nat.toBigInt d) diff --git a/src/Internal/Types/RawBytes.purs b/src/Internal/Types/RawBytes.purs deleted file mode 100644 index 9be49b1c37..0000000000 --- a/src/Internal/Types/RawBytes.purs +++ /dev/null @@ -1,74 +0,0 @@ --- | A wrapper over `ByteArray` to indicate a byte array with no further specified meaning - -module Ctl.Internal.Types.RawBytes - ( RawBytes(RawBytes) - , rawBytesToByteArray - , rawBytesFromByteArray - , rawBytesToIntArray - , rawBytesFromIntArray - , rawBytesFromIntArrayUnsafe - , rawBytesFromAscii - , rawBytesToHex - , byteLength - , hexToRawBytes - , hexToRawBytesUnsafe - ) where - -import Prelude - -import Aeson (class DecodeAeson, class EncodeAeson) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.ByteArray as BytesArray -import Data.Maybe (Maybe) -import Data.Newtype (class Newtype, unwrap, wrap) -import Test.QuickCheck.Arbitrary (class Arbitrary) - --- | An array of Bytes with no information about the content format -newtype RawBytes = RawBytes ByteArray - -instance Show RawBytes where - show rb = "(hexToRawBytesUnsafe " <> show (rawBytesToHex rb) <> ")" - -derive instance Newtype RawBytes _ - -derive newtype instance Eq RawBytes -derive newtype instance Ord RawBytes -derive newtype instance Semigroup RawBytes -derive newtype instance Monoid RawBytes -derive newtype instance EncodeAeson RawBytes -derive newtype instance DecodeAeson RawBytes -derive newtype instance Arbitrary RawBytes -derive newtype instance ToMetadata RawBytes -derive newtype instance FromMetadata RawBytes - -rawBytesToIntArray :: RawBytes -> Array Int -rawBytesToIntArray = BytesArray.byteArrayToIntArray <<< unwrap - -rawBytesFromIntArray :: Array Int -> Maybe RawBytes -rawBytesFromIntArray = map wrap <<< BytesArray.byteArrayFromIntArray - -rawBytesFromIntArrayUnsafe :: Array Int -> RawBytes -rawBytesFromIntArrayUnsafe = wrap <<< BytesArray.byteArrayFromIntArrayUnsafe - -rawBytesToHex :: RawBytes -> String -rawBytesToHex = BytesArray.byteArrayToHex <<< unwrap - -byteLength :: RawBytes -> Int -byteLength = BytesArray.byteLength <<< unwrap - -hexToRawBytes :: String -> Maybe RawBytes -hexToRawBytes = map wrap <<< BytesArray.hexToByteArray - -hexToRawBytesUnsafe :: String -> RawBytes -hexToRawBytesUnsafe = wrap <<< BytesArray.hexToByteArrayUnsafe - -rawBytesToByteArray :: RawBytes -> ByteArray -rawBytesToByteArray = unwrap - -rawBytesFromByteArray :: ByteArray -> RawBytes -rawBytesFromByteArray = wrap - -rawBytesFromAscii :: String -> Maybe RawBytes -rawBytesFromAscii = map wrap <<< BytesArray.byteArrayFromAscii diff --git a/src/Internal/Types/Redeemer.purs b/src/Internal/Types/Redeemer.purs deleted file mode 100644 index 786f8836ce..0000000000 --- a/src/Internal/Types/Redeemer.purs +++ /dev/null @@ -1,54 +0,0 @@ -module Ctl.Internal.Types.Redeemer - ( Redeemer(Redeemer) - , unitRedeemer - , RedeemerHash(RedeemerHash) - , redeemerHash - ) where - -import Prelude - -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Hashing (hashPlutusData) -import Ctl.Internal.Serialization (toBytes) -import Ctl.Internal.Serialization.PlutusData (convertPlutusData) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.ByteArray (ByteArray(ByteArray)) -import Ctl.Internal.Types.PlutusData (PlutusData) -import Data.Generic.Rep (class Generic) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Show.Generic (genericShow) - -newtype Redeemer = Redeemer PlutusData - -derive instance Generic Redeemer _ -derive instance Newtype Redeemer _ -derive newtype instance Eq Redeemer -derive newtype instance FromData Redeemer -derive newtype instance Ord Redeemer -derive newtype instance ToData Redeemer - -instance Show Redeemer where - show = genericShow - -unitRedeemer :: Redeemer -unitRedeemer = Redeemer (toData unit) - --- We could also use `type RedeemerHash = DataHash`? -newtype RedeemerHash = RedeemerHash ByteArray - -derive instance Generic RedeemerHash _ -derive instance Newtype RedeemerHash _ -derive newtype instance Eq RedeemerHash -derive newtype instance FromData RedeemerHash -derive newtype instance Ord RedeemerHash -derive newtype instance ToData RedeemerHash - -instance Show RedeemerHash where - show = genericShow - --- | Converts Plutus-style `Redeemer` to internal (non-CSL) `RedeemerHash`. --- | This is a duplicate of `datumHash`. -redeemerHash :: Redeemer -> RedeemerHash -redeemerHash = - wrap <<< unwrap <<< toBytes <<< hashPlutusData <<< convertPlutusData <<< - unwrap diff --git a/src/Internal/Types/RedeemerTag.purs b/src/Internal/Types/RedeemerTag.purs deleted file mode 100644 index d1f40211bb..0000000000 --- a/src/Internal/Types/RedeemerTag.purs +++ /dev/null @@ -1,37 +0,0 @@ -module Ctl.Internal.Types.RedeemerTag - ( RedeemerTag(Spend, Mint, Cert, Reward) - , fromString - ) where - -import Prelude - -import Aeson (class EncodeAeson) -import Ctl.Internal.Helpers (encodeTagged') -import Data.Generic.Rep (class Generic) -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Show.Generic (genericShow) - --- lives in it's own module due to a name conflict with the `Mint` Type -data RedeemerTag = Spend | Mint | Cert | Reward - -fromString :: String -> Maybe RedeemerTag -fromString = case _ of - "spend" -> Just Spend - "mint" -> Just Mint - "certificate" -> Just Cert - "withdrawal" -> Just Reward - _ -> Nothing - -derive instance Generic RedeemerTag _ -derive instance Eq RedeemerTag -derive instance Ord RedeemerTag - -instance Show RedeemerTag where - show = genericShow - -instance EncodeAeson RedeemerTag where - encodeAeson = case _ of - Spend -> encodeTagged' "Spend" {} - Mint -> encodeTagged' "Mint" {} - Cert -> encodeTagged' "Cert" {} - Reward -> encodeTagged' "Reward" {} diff --git a/src/Internal/Types/RewardAddress.purs b/src/Internal/Types/RewardAddress.purs deleted file mode 100644 index 99b48400d5..0000000000 --- a/src/Internal/Types/RewardAddress.purs +++ /dev/null @@ -1,68 +0,0 @@ -module Ctl.Internal.Types.RewardAddress - ( RewardAddress(RewardAddress) - , rewardAddressFromBytes - , rewardAddressToBytes - , rewardAddressFromBech32 - , rewardAddressToBech32 - , stakePubKeyHashRewardAddress - , stakeValidatorHashRewardAddress - , unRewardAddress - ) where - -import Prelude - -import Aeson (class DecodeAeson, class EncodeAeson) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Serialization.Address - ( keyHashCredential - , scriptHashCredential - ) -import Ctl.Internal.Serialization.Address as Csl -import Ctl.Internal.ToData (class ToData) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes) -import Ctl.Internal.Types.PubKeyHash (StakePubKeyHash) -import Ctl.Internal.Types.Scripts (StakeValidatorHash) -import Data.Maybe (Maybe) -import Data.Newtype (unwrap, wrap) - -newtype RewardAddress = RewardAddress Csl.RewardAddress - -derive newtype instance Eq RewardAddress -derive newtype instance Ord RewardAddress -derive newtype instance Show RewardAddress -derive newtype instance FromData RewardAddress -derive newtype instance ToData RewardAddress -derive newtype instance EncodeAeson RewardAddress -derive newtype instance DecodeAeson RewardAddress - -unRewardAddress :: RewardAddress -> Csl.RewardAddress -unRewardAddress (RewardAddress address) = address - -rewardAddressFromBytes :: ByteArray -> Maybe RewardAddress -rewardAddressFromBytes = wrap >>> Csl.rewardAddressFromBytes >>> map - RewardAddress - -rewardAddressFromBech32 :: Bech32String -> Maybe RewardAddress -rewardAddressFromBech32 = Csl.rewardAddressFromBech32 >>> map RewardAddress - -rewardAddressToBech32 :: RewardAddress -> Bech32String -rewardAddressToBech32 = unRewardAddress >>> Csl.rewardAddressBech32 - -rewardAddressToBytes :: RewardAddress -> CborBytes -rewardAddressToBytes = unRewardAddress >>> Csl.rewardAddressBytes - -stakePubKeyHashRewardAddress - :: Csl.NetworkId -> StakePubKeyHash -> RewardAddress -stakePubKeyHashRewardAddress networkId pkh = RewardAddress $ Csl.rewardAddress - { network: networkId - , paymentCred: keyHashCredential $ unwrap $ unwrap pkh - } - -stakeValidatorHashRewardAddress - :: Csl.NetworkId -> StakeValidatorHash -> RewardAddress -stakeValidatorHashRewardAddress networkId sh = RewardAddress $ Csl.rewardAddress - { network: networkId - , paymentCred: scriptHashCredential (unwrap sh) - } diff --git a/src/Internal/Types/ScriptLookups.purs b/src/Internal/Types/ScriptLookups.purs index 677ddbce3c..26bd89ad72 100644 --- a/src/Internal/Types/ScriptLookups.purs +++ b/src/Internal/Types/ScriptLookups.purs @@ -1,28 +1,31 @@ module Ctl.Internal.Types.ScriptLookups ( ScriptLookups(ScriptLookups) - , mintingPolicy - , mintingPolicyM + , nativeMintingPolicy + , plutusMintingPolicy , datum , validator - , validatorM , ownPaymentPubKeyHash - , ownPaymentPubKeyHashM , ownStakePubKeyHash - , ownStakePubKeyHashM , unspentOutputs - , unspentOutputsM ) where import Prelude hiding (join) -import Ctl.Internal.Hashing (datumHash) as Hashing +import Cardano.Types + ( DataHash + , PaymentPubKeyHash + , PlutusData + , PlutusScript + , PublicKey + , StakePubKeyHash + , TransactionInput + , TransactionOutput + , UtxoMap + ) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.NativeScript (NativeScript) import Ctl.Internal.Helpers ((<\>)) -import Ctl.Internal.Plutus.Types.Transaction (TransactionOutputWithRefScript) as Plutus -import Ctl.Internal.Types.Datum (DataHash, Datum) -import Ctl.Internal.Types.PaymentPubKey (PaymentPubKey) -import Ctl.Internal.Types.PubKeyHash (PaymentPubKeyHash, StakePubKeyHash) -import Ctl.Internal.Types.Scripts (MintingPolicy, Validator) -import Ctl.Internal.Types.Transaction (TransactionInput) +import Data.Array (nub) import Data.Array (singleton, union) as Array import Data.Generic.Rep (class Generic) import Data.Map (Map, empty, singleton, union) @@ -46,17 +49,15 @@ import Data.Show.Generic (genericShow) -- The lookups uses the Plutus type `TransactionOutput` and does internal -- conversions to the Serialization/Cardano to append to the `TxBody` as needed. newtype ScriptLookups = ScriptLookups - { mps :: - Array MintingPolicy -- Minting policies that the script interacts with - , txOutputs :: - Map TransactionInput Plutus.TransactionOutputWithRefScript -- Unspent outputs that the script may want to spend - , scripts :: - Array Validator -- Script validators - , datums :: Map DataHash Datum -- Datums that we might need + { plutusMintingPolicies :: Array PlutusScript + , nativeMintingPolicies :: Array NativeScript + , txOutputs :: UtxoMap + , scripts :: Array PlutusScript -- Script validators + , datums :: Map DataHash PlutusData -- FIXME there's currently no way to set this field -- See https://github.com/Plutonomicon/cardano-transaction-lib/issues/569 , paymentPubKeyHashes :: - Map PaymentPubKeyHash PaymentPubKey -- Public keys that we might need + Map PaymentPubKeyHash PublicKey -- Public keys that we might need , ownPaymentPubKeyHash :: Maybe PaymentPubKeyHash -- The contract's payment public key hash, used for depositing tokens etc. , ownStakePubKeyHash :: @@ -75,7 +76,10 @@ instance Show ScriptLookups where instance Semigroup ScriptLookups where append (ScriptLookups l) (ScriptLookups r) = ScriptLookups - { mps: l.mps `Array.union` r.mps + { plutusMintingPolicies: nub $ l.plutusMintingPolicies `Array.union` + r.plutusMintingPolicies + , nativeMintingPolicies: nub $ l.nativeMintingPolicies `Array.union` + r.nativeMintingPolicies , txOutputs: l.txOutputs `union` r.txOutputs , scripts: l.scripts `Array.union` r.scripts , datums: l.datums `union` r.datums @@ -87,7 +91,8 @@ instance Semigroup ScriptLookups where instance Monoid ScriptLookups where mempty = ScriptLookups - { mps: mempty + { plutusMintingPolicies: mempty + , nativeMintingPolicies: mempty , txOutputs: empty , scripts: mempty , datums: empty @@ -104,60 +109,37 @@ instance Monoid ScriptLookups where -- | input constraints. unspentOutputs :: forall (a :: Type) - . Map TransactionInput Plutus.TransactionOutputWithRefScript + . Map TransactionInput TransactionOutput -> ScriptLookups unspentOutputs mp = over ScriptLookups _ { txOutputs = mp } mempty --- | Same as `unspentOutputs` but in `Maybe` context for convenience. --- | This should not fail. -unspentOutputsM - :: forall (a :: Type) - . Map TransactionInput Plutus.TransactionOutputWithRefScript - -> Maybe ScriptLookups -unspentOutputsM = pure <<< unspentOutputs - -- | A script lookups value with a minting policy script. -mintingPolicy :: MintingPolicy -> ScriptLookups -mintingPolicy pl = over ScriptLookups _ { mps = Array.singleton pl } mempty +plutusMintingPolicy :: PlutusScript -> ScriptLookups +plutusMintingPolicy ps = over ScriptLookups + _ { plutusMintingPolicies = Array.singleton ps } + mempty --- | Same as `mintingPolicy` but in `Maybe` context for convenience. This --- | should not fail. -mintingPolicyM :: forall (a :: Type). MintingPolicy -> Maybe ScriptLookups -mintingPolicyM = pure <<< mintingPolicy +nativeMintingPolicy :: NativeScript -> ScriptLookups +nativeMintingPolicy ns = over ScriptLookups + _ { nativeMintingPolicies = Array.singleton ns } + mempty -- | A script lookups value with a validator script. -validator :: forall (a :: Type). Validator -> ScriptLookups +validator :: forall (a :: Type). PlutusScript -> ScriptLookups validator vl = over ScriptLookups _ { scripts = Array.singleton vl } mempty --- | Same as `validator` but in `Maybe` context for convenience. This --- | should not fail. -validatorM :: forall (a :: Type). Validator -> Maybe ScriptLookups -validatorM = pure <<< validator - -- | A script lookups value with a datum. -datum :: Datum -> ScriptLookups +datum :: PlutusData -> ScriptLookups datum dt = - over ScriptLookups _ { datums = singleton (Hashing.datumHash dt) dt } mempty + over ScriptLookups _ { datums = singleton (hashPlutusData dt) dt } mempty -- | Add your own `PaymentPubKeyHash` to the lookup. ownPaymentPubKeyHash :: PaymentPubKeyHash -> ScriptLookups ownPaymentPubKeyHash pkh = over ScriptLookups _ { ownPaymentPubKeyHash = Just pkh } mempty --- | Same as `ownPaymentPubKeyHash` but in `Maybe` context for convenience. This --- | should not fail. -ownPaymentPubKeyHashM - :: PaymentPubKeyHash -> Maybe ScriptLookups -ownPaymentPubKeyHashM = pure <<< ownPaymentPubKeyHash - -- | Add your own `StakePubKeyHash` to the lookup. ownStakePubKeyHash :: StakePubKeyHash -> ScriptLookups ownStakePubKeyHash skh = over ScriptLookups _ { ownStakePubKeyHash = Just skh } mempty - --- | Same as `ownStakePubKeyHash` but in `Maybe` context for convenience. This --- | should not fail. -ownStakePubKeyHashM - :: StakePubKeyHash -> Maybe ScriptLookups -ownStakePubKeyHashM = pure <<< ownStakePubKeyHash diff --git a/src/Internal/Types/Scripts.purs b/src/Internal/Types/Scripts.purs deleted file mode 100644 index 7159515e19..0000000000 --- a/src/Internal/Types/Scripts.purs +++ /dev/null @@ -1,233 +0,0 @@ -module Ctl.Internal.Types.Scripts - ( MintingPolicy(PlutusMintingPolicy, NativeMintingPolicy) - , MintingPolicyHash(MintingPolicyHash) - , PlutusScript(PlutusScript) - , PlutusScriptStakeValidator(PlutusScriptStakeValidator) - , NativeScriptStakeValidator(NativeScriptStakeValidator) - , StakeValidatorHash(StakeValidatorHash) - , Validator(Validator) - , ValidatorHash(ValidatorHash) - , Language(PlutusV1, PlutusV2) - , plutusV1Script - , plutusV2Script - , stakeValidatorHashToBech32 - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , Aeson - , JsonDecodeError(TypeMismatch, UnexpectedValue) - , caseAesonObject - , caseAesonString - , decodeAeson - , encodeAeson - , fromString - , getField - , toStringifiedNumbersJson - ) -import Control.Alt ((<|>)) -import Ctl.Internal.Cardano.Types.NativeScript (NativeScript) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata) -import Ctl.Internal.Serialization.Hash (ScriptHash, scriptHashToBech32Unsafe) -import Ctl.Internal.ToData (class ToData) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Data.Either (Either(Left)) -import Data.Generic.Rep (class Generic) -import Data.Newtype (class Newtype, unwrap) -import Data.Show.Generic (genericShow) -import Data.Tuple.Nested (type (/\), (/\)) - -data Language - = PlutusV1 - | PlutusV2 - -derive instance Eq Language -derive instance Ord Language -derive instance Generic Language _ - -instance DecodeAeson Language where - decodeAeson = caseAesonString - (Left $ TypeMismatch "Expected string") - case _ of - "PlutusV1" -> pure PlutusV1 - "PlutusV2" -> pure PlutusV2 - other -> Left $ UnexpectedValue $ toStringifiedNumbersJson $ fromString - other - -instance EncodeAeson Language where - encodeAeson = encodeAeson <<< case _ of - PlutusV1 -> "PlutusV1" - PlutusV2 -> "PlutusV2" - -instance Show Language where - show = genericShow - --------------------------------------------------------------------------------- --- `PlutusScript` newtypes and `TypedValidator` --------------------------------------------------------------------------------- --- | Corresponds to "Script" in Plutus -newtype PlutusScript = PlutusScript (ByteArray /\ Language) - -derive instance Generic PlutusScript _ -derive instance Newtype PlutusScript _ -derive newtype instance Eq PlutusScript -derive newtype instance Ord PlutusScript -derive newtype instance DecodeAeson PlutusScript -derive newtype instance EncodeAeson PlutusScript - -instance Show PlutusScript where - show = genericShow - -plutusV1Script :: ByteArray -> PlutusScript -plutusV1Script ba = PlutusScript (ba /\ PlutusV1) - -plutusV2Script :: ByteArray -> PlutusScript -plutusV2Script ba = PlutusScript (ba /\ PlutusV2) - -decodeAesonHelper - :: ∀ (a :: Type) (b :: Type) - . DecodeAeson a - => String - -> (a -> b) - -> Aeson - -> Either JsonDecodeError b -decodeAesonHelper constrName constr = caseAesonObject - (Left $ TypeMismatch "Expected object") - (flip getField constrName >=> decodeAeson >>> map constr) - --- | `MintingPolicy` is a sum type of `PlutusScript` and `NativeScript` which are used as --- | validators for minting constraints. -data MintingPolicy - = PlutusMintingPolicy PlutusScript - | NativeMintingPolicy NativeScript - -derive instance Generic MintingPolicy _ -derive instance Eq MintingPolicy - -instance DecodeAeson MintingPolicy where - decodeAeson aes = - decodeAesonHelper "getPlutusMintingPolicy" PlutusMintingPolicy aes <|> - decodeAesonHelper "getNativeMintingPolicy" NativeMintingPolicy aes - -instance EncodeAeson MintingPolicy where - encodeAeson (NativeMintingPolicy nscript) = - encodeAeson { "getNativeMintingPolicy": nscript } - encodeAeson (PlutusMintingPolicy script) = - encodeAeson { "getPlutusMintingPolicy": script } - -instance Show MintingPolicy where - show = genericShow - -newtype Validator = Validator PlutusScript - -derive instance Generic Validator _ -derive instance Newtype Validator _ -derive newtype instance Eq Validator -derive newtype instance Ord Validator - -instance DecodeAeson Validator where - decodeAeson = decodeAesonHelper "getValidator" Validator - -instance EncodeAeson Validator where - encodeAeson (Validator script) = - encodeAeson { "getValidator": script } - -instance Show Validator where - show = genericShow - --- | `NativeScriptStakeValidator`s are used as validators for withdrawals and --- | stake address certificates. -newtype NativeScriptStakeValidator = NativeScriptStakeValidator NativeScript - -derive instance Newtype NativeScriptStakeValidator _ -derive instance Generic NativeScriptStakeValidator _ -derive instance Eq NativeScriptStakeValidator - -instance Show NativeScriptStakeValidator where - show = genericShow - --- | `PlutusScriptStakeValidator`s are used as validators for withdrawals and --- | stake address certificates. -newtype PlutusScriptStakeValidator = PlutusScriptStakeValidator PlutusScript - -derive instance Newtype PlutusScriptStakeValidator _ -derive instance Generic PlutusScriptStakeValidator _ -derive instance Eq PlutusScriptStakeValidator - -instance DecodeAeson PlutusScriptStakeValidator where - decodeAeson = decodeAesonHelper "getStakeValidator" PlutusScriptStakeValidator - -instance EncodeAeson PlutusScriptStakeValidator where - encodeAeson (PlutusScriptStakeValidator script) = - encodeAeson { "getStakeValidator": script } - -instance Show PlutusScriptStakeValidator where - show = genericShow - --------------------------------------------------------------------------------- --- `ScriptHash` newtypes --------------------------------------------------------------------------------- -newtype MintingPolicyHash = MintingPolicyHash ScriptHash - -derive instance Generic MintingPolicyHash _ -derive instance Newtype MintingPolicyHash _ -derive newtype instance Eq MintingPolicyHash -derive newtype instance Ord MintingPolicyHash -derive newtype instance FromData MintingPolicyHash -derive newtype instance ToData MintingPolicyHash -derive newtype instance FromMetadata MintingPolicyHash -derive newtype instance ToMetadata MintingPolicyHash - -instance DecodeAeson MintingPolicyHash where - decodeAeson = decodeAesonHelper "getMintingPolicyHash" MintingPolicyHash - -instance EncodeAeson MintingPolicyHash where - encodeAeson (MintingPolicyHash hash) = - encodeAeson { "getMintingPolicyHash": hash } - -instance Show MintingPolicyHash where - show = genericShow - -newtype ValidatorHash = ValidatorHash ScriptHash - -derive instance Generic ValidatorHash _ -derive instance Newtype ValidatorHash _ -derive newtype instance Eq ValidatorHash -derive newtype instance Ord ValidatorHash -derive newtype instance FromData ValidatorHash -derive newtype instance ToData ValidatorHash -derive newtype instance FromMetadata ValidatorHash -derive newtype instance ToMetadata ValidatorHash -derive newtype instance EncodeAeson ValidatorHash -derive newtype instance DecodeAeson ValidatorHash - -instance Show ValidatorHash where - show = genericShow - -newtype StakeValidatorHash = StakeValidatorHash ScriptHash - -derive instance Generic StakeValidatorHash _ -derive instance Newtype StakeValidatorHash _ -derive newtype instance Eq StakeValidatorHash -derive newtype instance Ord StakeValidatorHash -derive newtype instance ToData StakeValidatorHash -derive newtype instance FromData StakeValidatorHash - -instance DecodeAeson StakeValidatorHash where - decodeAeson = decodeAesonHelper "getStakeValidatorHash" StakeValidatorHash - -instance EncodeAeson StakeValidatorHash where - encodeAeson (StakeValidatorHash hash) = - encodeAeson { "getStakeValidatorHash": hash } - -instance Show StakeValidatorHash where - show = genericShow - -stakeValidatorHashToBech32 :: StakeValidatorHash -> Bech32String -stakeValidatorHashToBech32 = unwrap >>> scriptHashToBech32Unsafe "script" diff --git a/src/Internal/Types/StakeValidatorHash.purs b/src/Internal/Types/StakeValidatorHash.purs new file mode 100644 index 0000000000..ebacb2dcfa --- /dev/null +++ b/src/Internal/Types/StakeValidatorHash.purs @@ -0,0 +1,33 @@ +module Ctl.Internal.Types.StakeValidatorHash + ( StakeValidatorHash(StakeValidatorHash) + ) where + +import Prelude + +import Aeson (class DecodeAeson, class EncodeAeson, encodeAeson) +import Cardano.FromData (class FromData) +import Cardano.ToData (class ToData) +import Cardano.Types.ScriptHash (ScriptHash) +import Ctl.Internal.Helpers (decodeTaggedNewtype) +import Data.Generic.Rep (class Generic) +import Data.Newtype (class Newtype) +import Data.Show.Generic (genericShow) + +newtype StakeValidatorHash = StakeValidatorHash ScriptHash + +derive instance Generic StakeValidatorHash _ +derive instance Newtype StakeValidatorHash _ +derive newtype instance Eq StakeValidatorHash +derive newtype instance Ord StakeValidatorHash +derive newtype instance ToData StakeValidatorHash +derive newtype instance FromData StakeValidatorHash + +instance DecodeAeson StakeValidatorHash where + decodeAeson = decodeTaggedNewtype "getStakeValidatorHash" StakeValidatorHash + +instance EncodeAeson StakeValidatorHash where + encodeAeson (StakeValidatorHash hash) = + encodeAeson { "getStakeValidatorHash": hash } + +instance Show StakeValidatorHash where + show = genericShow diff --git a/src/Internal/Types/SystemStart.purs b/src/Internal/Types/SystemStart.purs index 80e37b524d..f2311ba31e 100644 --- a/src/Internal/Types/SystemStart.purs +++ b/src/Internal/Types/SystemStart.purs @@ -9,18 +9,18 @@ module Ctl.Internal.Types.SystemStart import Prelude import Control.Alt ((<|>)) +import Ctl.Internal.Helpers (unsafeFromJust) import Data.DateTime (DateTime) import Data.DateTime.Instant (fromDateTime, unInstant) import Data.Either (Either, hush) import Data.Formatter.DateTime (Formatter, format, parseFormatString, unformat) import Data.Generic.Rep (class Generic) -import Data.Maybe (Maybe, fromJust) +import Data.Maybe (Maybe) import Data.Newtype (class Newtype, unwrap, wrap) import Data.Show.Generic (genericShow) import Data.String (length, take) as String import JS.BigInt (BigInt) import JS.BigInt (fromNumber) as BigInt -import Partial.Unsafe (unsafePartial) newtype SystemStart = SystemStart DateTime @@ -52,7 +52,8 @@ sysStartFromOgmiosTimestamp timestamp = wrap <$> (unformatMsec <|> unformatSec) sysStartFromOgmiosTimestampUnsafe :: String -> SystemStart sysStartFromOgmiosTimestampUnsafe timestamp = - unsafePartial fromJust $ hush $ sysStartFromOgmiosTimestamp timestamp + unsafeFromJust "sysStartFromOgmiosTimestampUnsafe" $ hush $ + sysStartFromOgmiosTimestamp timestamp sysStartToOgmiosTimestamp :: SystemStart -> String sysStartToOgmiosTimestamp = @@ -61,7 +62,7 @@ sysStartToOgmiosTimestamp = mkDateTimeFormatterUnsafe :: String -> Formatter mkDateTimeFormatterUnsafe = - unsafePartial fromJust <<< hush <<< parseFormatString + unsafeFromJust "mkDateTimeFormatterUnsafe" <<< hush <<< parseFormatString ogmiosDateTimeFormatStringSec :: String ogmiosDateTimeFormatStringSec = "YYYY-MM-DDTHH:mm:ss" @@ -71,4 +72,3 @@ ogmiosDateTimeFormatStringMsec = ogmiosDateTimeFormatStringSec <> ".SSS" ogmiosDateTimeFormatStringMsecUTC :: String ogmiosDateTimeFormatStringMsecUTC = ogmiosDateTimeFormatStringMsec <> "Z" - diff --git a/src/Internal/Types/TokenName.js b/src/Internal/Types/TokenName.js deleted file mode 100644 index f432d39277..0000000000 --- a/src/Internal/Types/TokenName.js +++ /dev/null @@ -1,26 +0,0 @@ -/* global BROWSER_RUNTIME */ - -// `TextDecoder` is not available in `node`, use polyfill in that case -let OurTextDecoder; -if (typeof BROWSER_RUNTIME == "undefined" || !BROWSER_RUNTIME) { - const util = await import("util"); - OurTextDecoder = util.TextDecoder; -} else { - OurTextDecoder = TextDecoder; -} - -export function _decodeUtf8(buffer) { - return left => right => { - let decoder = new OurTextDecoder("utf-8", { fatal: true }); // Without fatal=true it never fails - - try { - return right(decoder.decode(buffer)); - } catch (err) { - return left(err.toString()); - } - }; -} - -// FIXME: https://github.com/Plutonomicon/cardano-transaction-lib/issues/548 -const call = property => object => object[property](); -export const assetNameName = call("name"); diff --git a/src/Internal/Types/TokenName.purs b/src/Internal/Types/TokenName.purs deleted file mode 100644 index 86593a9d3b..0000000000 --- a/src/Internal/Types/TokenName.purs +++ /dev/null @@ -1,124 +0,0 @@ -module Ctl.Internal.Types.TokenName - ( TokenName - , adaToken - , getTokenName - , mkTokenName - , mkTokenNames - , tokenNameFromAssetName - , assetNameName - , fromTokenName - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , caseAesonObject - , encodeAeson - , getField - ) -import Contract.Prim.ByteArray (hexToByteArray) -import Ctl.Internal.FromData (class FromData) -import Ctl.Internal.Metadata.FromMetadata (class FromMetadata) -import Ctl.Internal.Metadata.ToMetadata (class ToMetadata) -import Ctl.Internal.Serialization.Types (AssetName) as CSL -import Ctl.Internal.ToData (class ToData) -import Ctl.Internal.Types.ByteArray (ByteArray, byteArrayToHex, byteLength) -import Ctl.Internal.Types.RawBytes (RawBytes(RawBytes)) -import Data.ArrayBuffer.Types (Uint8Array) -import Data.Bitraversable (ltraverse) -import Data.Either (Either(Right, Left), either, note) -import Data.Map (Map) -import Data.Map (fromFoldable) as Map -import Data.Maybe (Maybe(Nothing), fromJust) -import Data.Newtype (unwrap, wrap) -import Data.String.CodePoints (drop, take) -import Data.TextEncoder (encodeUtf8) -import Data.Traversable (class Traversable, traverse) -import Data.Tuple.Nested (type (/\)) -import JS.BigInt (BigInt) -import Partial.Unsafe (unsafePartial) -import Test.QuickCheck.Arbitrary (class Arbitrary, arbitrary) -import Test.QuickCheck.Gen (resize) - -newtype TokenName = TokenName RawBytes - -derive newtype instance Eq TokenName -derive newtype instance FromData TokenName -derive newtype instance FromMetadata TokenName -derive newtype instance ToMetadata TokenName -derive newtype instance Ord TokenName -derive newtype instance ToData TokenName - -instance Arbitrary TokenName where - arbitrary = unsafePartial fromJust <<< mkTokenName <$> resize 32 arbitrary - -foreign import _decodeUtf8 - :: forall (r :: Type). Uint8Array -> (String -> r) -> (String -> r) -> r - -fromTokenName - :: forall (r :: Type). (ByteArray -> r) -> (String -> r) -> TokenName -> r -fromTokenName arrayHandler stringHandler (TokenName (RawBytes ba)) = either - (const $ arrayHandler $ ba) - stringHandler - (_decodeUtf8 (unwrap ba) Left Right) - --- | Corresponds to the Haskell instance at https://github.com/input-output-hk/plutus/blob/4fd86930f1dc628a816adf5f5d854b3fec578312/plutus-ledger-api/src/Plutus/V1/Ledger/Value.hs#L155: -instance DecodeAeson TokenName where - decodeAeson = caseAesonObject (Left $ TypeMismatch "Expected object") $ - \aes -> do - tkstr <- getField aes "unTokenName" - case take 3 tkstr of - "\x0000000x" -> do -- this is 3 characters '\NUL' '0' 'x' - let stripped = drop 3 tkstr -- strip the \NUL followed by "0x" - ba <- - note - (TypeMismatch $ "Expected base16 encoded string got " <> stripped) - $ hexToByteArray stripped - pure $ TokenName (wrap ba) - "\x0\x0\x0" -> Right $ tkFromStr (drop 2 tkstr) -- if the original started with \NUL, we prepended 2 additional \NULs - _ -> Right $ tkFromStr tkstr - where - tkFromStr :: String -> TokenName - tkFromStr = TokenName <<< wrap <<< wrap <<< encodeUtf8 - -instance EncodeAeson TokenName where - encodeAeson = encodeAeson <<< { "unTokenName": _ } <<< fromTokenName - (\ba -> "\x0" <> "0x" <> byteArrayToHex ba) - ( \s -> case take 1 s of - "\x0" -> "\x0\x0" <> s - _ -> s - ) - -instance Show TokenName where - show (TokenName tn) = "(TokenName " <> show tn <> ")" - -getTokenName :: TokenName -> ByteArray -getTokenName (TokenName tokenName) = unwrap tokenName - --- | The empty token name. -adaToken :: TokenName -adaToken = TokenName mempty - --- | Create a `TokenName` from a `ByteArray` since TokenName data constructor is --- | not exported -mkTokenName :: ByteArray -> Maybe TokenName -mkTokenName byteArr - | byteLength byteArr <= 32 = pure $ TokenName $ wrap byteArr - | otherwise = Nothing - -foreign import assetNameName :: CSL.AssetName -> ByteArray - -tokenNameFromAssetName :: CSL.AssetName -> TokenName -tokenNameFromAssetName = TokenName <<< wrap <<< assetNameName - --- | Creates a Map of `TokenName` and Big Integers from a `Traversable` of 2-tuple --- | `ByteArray` and Big Integers with the possibility of failure -mkTokenNames - :: forall (t :: Type -> Type) - . Traversable t - => t (ByteArray /\ BigInt) - -> Maybe (Map TokenName BigInt) -mkTokenNames = traverse (ltraverse mkTokenName) >>> map Map.fromFoldable diff --git a/src/Internal/Types/Transaction.purs b/src/Internal/Types/Transaction.purs deleted file mode 100644 index 1377c96ed9..0000000000 --- a/src/Internal/Types/Transaction.purs +++ /dev/null @@ -1,123 +0,0 @@ --- | A module for shared types across Cardano.Types.Transaction and --- | Plutus.Types.Transaction. -module Ctl.Internal.Types.Transaction - ( DataHash(DataHash) - , TransactionHash(TransactionHash) - , TransactionInput(TransactionInput) - ) where - -import Prelude - -import Aeson (class DecodeAeson, class EncodeAeson) -import Ctl.Internal.FromData (class FromData, fromData) -import Ctl.Internal.ToData (class ToData, toData) -import Ctl.Internal.Types.BigNum (zero) as BigNum -import Ctl.Internal.Types.ByteArray - ( ByteArray - , byteArrayFromIntArrayUnsafe - , byteArrayToHex - ) -import Ctl.Internal.Types.PlutusData (PlutusData(Constr)) -import Data.Generic.Rep (class Generic) -import Data.Maybe (Maybe(Nothing)) -import Data.Newtype (class Newtype, wrap) -import Data.Show.Generic (genericShow) -import Data.UInt (UInt, toInt) -import Test.QuickCheck.Arbitrary - ( class Arbitrary - , class Coarbitrary - , coarbitrary - ) -import Test.QuickCheck.Gen (chooseInt, vectorOf) - -newtype TransactionInput = TransactionInput - { transactionId :: TransactionHash - , index :: UInt - } - -derive instance Newtype TransactionInput _ -derive instance Generic TransactionInput _ -derive newtype instance Eq TransactionInput -derive newtype instance EncodeAeson TransactionInput -derive newtype instance DecodeAeson TransactionInput - --- Potential fix me: the below is based on a small sample of smart contract --- transactions, so fix this as required. --- Not newtype derived this because it is not lexicographical as `index` is tested --- before `transactionId`. We require lexicographical order over hexstring --- `TransactionHash`, then `index`, seemingly inline with Cardano/Plutus. -instance Ord TransactionInput where - compare (TransactionInput txInput) (TransactionInput txInput') = - case compare txInput.transactionId txInput'.transactionId of - EQ -> compare txInput.index txInput'.index - x -> x - -instance Show TransactionInput where - show = genericShow - --- `Constr` is used for indexing, and `TransactionInput` is always zero-indexed -instance FromData TransactionInput where - fromData (Constr n [ txId, idx ]) | n == BigNum.zero = - TransactionInput <$> - ({ transactionId: _, index: _ } <$> fromData txId <*> fromData idx) - fromData _ = Nothing - --- `Constr` is used for indexing, and `TransactionInput` is always zero-indexed -instance ToData TransactionInput where - toData (TransactionInput { transactionId, index }) = - Constr BigNum.zero [ toData transactionId, toData index ] - -instance Coarbitrary TransactionInput where - coarbitrary (TransactionInput input) generator = - coarbitrary (toInt input.index) $ coarbitrary input.transactionId generator - --- | 32-bytes blake2b256 hash of a tx body. --- | NOTE. Plutus docs might incorrectly state that it uses --- | SHA256 for this purposes. -newtype TransactionHash = TransactionHash ByteArray - -derive instance Generic TransactionHash _ -derive instance Newtype TransactionHash _ -derive newtype instance Eq TransactionHash -derive newtype instance EncodeAeson TransactionHash -derive newtype instance DecodeAeson TransactionHash - --- This is not newtyped derived because it will be used for ordering a --- `TransactionInput`, we want lexicographical ordering on the hexstring. -instance Ord TransactionHash where - compare (TransactionHash h) (TransactionHash h') = - compare (byteArrayToHex h) (byteArrayToHex h') - -instance Show TransactionHash where - show = genericShow - --- Plutus actually has this as a zero indexed record -instance FromData TransactionHash where - fromData (Constr n [ bytes ]) | n == BigNum.zero = TransactionHash <$> - fromData bytes - fromData _ = Nothing - --- Plutus actually has this as a zero indexed record -instance ToData TransactionHash where - toData (TransactionHash bytes) = Constr BigNum.zero [ toData bytes ] - -instance Arbitrary TransactionHash where - arbitrary = - wrap <<< byteArrayFromIntArrayUnsafe <$> vectorOf 32 (chooseInt 0 255) - -instance Coarbitrary TransactionHash where - coarbitrary (TransactionHash bytes) generator = coarbitrary bytes generator - -newtype DataHash = DataHash ByteArray - -derive instance Generic DataHash _ -derive instance Newtype DataHash _ -derive newtype instance Eq DataHash -derive newtype instance FromData DataHash -derive newtype instance Ord DataHash -derive newtype instance ToData DataHash -derive newtype instance DecodeAeson DataHash -derive newtype instance EncodeAeson DataHash - -instance Show DataHash where - show = genericShow diff --git a/src/Internal/Types/TransactionMetadata.purs b/src/Internal/Types/TransactionMetadata.purs deleted file mode 100644 index c92752e996..0000000000 --- a/src/Internal/Types/TransactionMetadata.purs +++ /dev/null @@ -1,91 +0,0 @@ -module Ctl.Internal.Types.TransactionMetadata - ( GeneralTransactionMetadata(GeneralTransactionMetadata) - , TransactionMetadatum - ( MetadataMap - , MetadataList - , Int - , Bytes - , Text - ) - , TransactionMetadatumLabel(TransactionMetadatumLabel) - ) where - -import Prelude - -import Aeson (class EncodeAeson) -import Ctl.Internal.Helpers - ( appendRightMap - , encodeMap - , encodeTagged' - , showWithParens - ) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.Int (Int) as Int -import Data.Generic.Rep (class Generic) -import Data.Map (Map) -import Data.Map (empty) as Map -import Data.Newtype (class Newtype) -import Data.Show.Generic (genericShow) -import JS.BigInt (BigInt) - -newtype GeneralTransactionMetadata = - GeneralTransactionMetadata - (Map TransactionMetadatumLabel TransactionMetadatum) - -derive instance Newtype GeneralTransactionMetadata _ - -derive newtype instance Eq GeneralTransactionMetadata -derive instance Generic GeneralTransactionMetadata _ - -instance Show GeneralTransactionMetadata where - show = genericShow - -instance EncodeAeson GeneralTransactionMetadata where - encodeAeson (GeneralTransactionMetadata m) = encodeMap m - --- This Semigroup instance simply takes the Last value for duplicate keys --- to avoid a Semigroup instance for TransactionMetadatum. --- Do we want to avoid a Semigroup instance for TransactionMetadatum? Recursion --- is fine but how to combine Text with Bytes for example? One would have to take --- precedence and replace the other. -instance Semigroup GeneralTransactionMetadata where - append (GeneralTransactionMetadata hm) (GeneralTransactionMetadata hm') = - GeneralTransactionMetadata $ hm `appendRightMap` hm' - -instance Monoid GeneralTransactionMetadata where - mempty = GeneralTransactionMetadata Map.empty - -newtype TransactionMetadatumLabel = TransactionMetadatumLabel BigInt - -derive instance Newtype TransactionMetadatumLabel _ -derive newtype instance Eq TransactionMetadatumLabel -derive newtype instance Ord TransactionMetadatumLabel -derive newtype instance EncodeAeson TransactionMetadatumLabel -derive instance Generic TransactionMetadatumLabel _ - -instance Show TransactionMetadatumLabel where - show (TransactionMetadatumLabel tml) = - showWithParens "TransactionMetadatumLabel" tml - -data TransactionMetadatum - = MetadataMap (Map TransactionMetadatum TransactionMetadatum) - | MetadataList (Array TransactionMetadatum) - | Int Int.Int - | Bytes ByteArray - | Text String - -derive instance Eq TransactionMetadatum -derive instance Ord TransactionMetadatum -derive instance Generic TransactionMetadatum _ - -instance Show TransactionMetadatum where - show x = genericShow x - -instance EncodeAeson TransactionMetadatum where - encodeAeson = case _ of - MetadataMap m -> encodeTagged' "MetadataMap" $ encodeMap m - MetadataList arr -> encodeTagged' "MetadataList" arr - Int n -> encodeTagged' "Int" n - Bytes bytes -> encodeTagged' "Bytes" bytes - Text string -> encodeTagged' "Text" string - diff --git a/src/Internal/Types/TxConstraints.purs b/src/Internal/Types/TxConstraints.purs index a7f9ab229d..467d463f54 100644 --- a/src/Internal/Types/TxConstraints.purs +++ b/src/Internal/Types/TxConstraints.purs @@ -21,6 +21,7 @@ module Ctl.Internal.Types.TxConstraints , MustPayToScript , MustProduceAtLeast , MustReferenceOutput + , MustRegisterDrep , MustRegisterPool , MustRegisterStakePubKey , MustRegisterStakeScript @@ -35,8 +36,7 @@ module Ctl.Internal.Types.TxConstraints , MustWithdrawStakeNativeScript , MustWithdrawStakePubKey ) - , TxConstraints(TxConstraints) - , isSatisfiable + , TxConstraints , mustBeSignedBy , mustDelegateStakeNativeScript , mustDelegateStakePlutusScript @@ -69,15 +69,14 @@ module Ctl.Internal.Types.TxConstraints , mustPayToScriptAddressWithScriptRef , mustPayToScriptWithScriptRef , mustProduceAtLeast - , mustProduceAtLeastTotal , mustReferenceOutput + , mustRegisterDrep , mustRegisterPool , mustRegisterStakePubKey , mustRegisterStakeScript , mustRetirePool , mustSatisfyAnyOf , mustSpendAtLeast - , mustSpendAtLeastTotal , mustSpendNativeScriptOutput , mustSpendPubKeyOutput , mustSpendScriptOutput @@ -86,65 +85,47 @@ module Ctl.Internal.Types.TxConstraints , mustWithdrawStakeNativeScript , mustWithdrawStakePlutusScript , mustWithdrawStakePubKey - , pubKeyPayments - , requiredDatums - , requiredMonetaryPolicies - , requiredSignatories - , singleton , utxoWithScriptRef ) where import Prelude hiding (join) -import Ctl.Internal.Cardano.Types.NativeScript (NativeScript) -import Ctl.Internal.Cardano.Types.ScriptRef (ScriptRef) -import Ctl.Internal.Cardano.Types.Transaction - ( Epoch +import Cardano.Types + ( Anchor + , AssetName + , Credential + , DataHash + , Epoch + , Mint + , NativeScript + , PaymentPubKeyHash + , PlutusData + , PlutusScript + , PoolParams , PoolPubKeyHash - , PoolRegistrationParams + , ScriptHash + , ScriptRef + , StakePubKeyHash + , TransactionInput + , TransactionOutput + , TransactionUnspentOutput(TransactionUnspentOutput) + , Value ) -import Ctl.Internal.NativeScripts (NativeScriptHash) -import Ctl.Internal.Plutus.Types.Credential (Credential) -import Ctl.Internal.Plutus.Types.CurrencySymbol - ( CurrencySymbol - , currencyMPSHash - ) -import Ctl.Internal.Plutus.Types.Transaction (TransactionOutputWithRefScript) -import Ctl.Internal.Plutus.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - ) -import Ctl.Internal.Plutus.Types.Value (Value, flattenNonAdaAssets) -import Ctl.Internal.Types.Datum (Datum) -import Ctl.Internal.Types.Interval - ( POSIXTimeRange - , always - , intersection - , isEmpty - ) -import Ctl.Internal.Types.PlutusData (PlutusData) -import Ctl.Internal.Types.PubKeyHash (PaymentPubKeyHash, StakePubKeyHash) -import Ctl.Internal.Types.Redeemer (Redeemer, unitRedeemer) -import Ctl.Internal.Types.Scripts - ( MintingPolicyHash - , NativeScriptStakeValidator - , PlutusScriptStakeValidator - , StakeValidatorHash - , ValidatorHash - ) -import Ctl.Internal.Types.TokenName (TokenName) -import Ctl.Internal.Types.Transaction (DataHash, TransactionInput) +import Cardano.Types.Int as Int +import Cardano.Types.Mint as Mint +import Cardano.Types.RedeemerDatum (RedeemerDatum) +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Ctl.Internal.Types.Interval (POSIXTimeRange) +import Data.Array (singleton) import Data.Array as Array -import Data.Foldable (class Foldable, foldMap, foldl, foldr) +import Data.Foldable (class Foldable) import Data.Generic.Rep (class Generic) -import Data.Lattice (join) -import Data.Map (Map, fromFoldableWith, toUnfoldable) +import Data.Map (Map) import Data.Map (singleton) as Map import Data.Maybe (Maybe(Just, Nothing)) -import Data.Monoid (guard) -import Data.Newtype (class Newtype, over, unwrap) +import Data.Newtype (class Newtype) import Data.Show.Generic (genericShow) import Data.Tuple.Nested (type (/\), (/\)) -import JS.BigInt (BigInt) import Prim.TypeError (class Warn, Text) -------------------------------------------------------------------------------- @@ -156,43 +137,45 @@ import Prim.TypeError (class Warn, Text) -- | Constraints on transactions that want to spend script outputs data TxConstraint - = MustIncludeDatum Datum + = MustIncludeDatum PlutusData | MustValidateIn POSIXTimeRange | MustBeSignedBy PaymentPubKeyHash | MustSpendAtLeast Value | MustProduceAtLeast Value | MustSpendPubKeyOutput TransactionInput | MustSpendNativeScriptOutput TransactionInput NativeScript - | MustSpendScriptOutput TransactionInput Redeemer (Maybe InputWithScriptRef) + | MustSpendScriptOutput TransactionInput RedeemerDatum + (Maybe InputWithScriptRef) | MustReferenceOutput TransactionInput - | MustMintValue MintingPolicyHash Redeemer TokenName BigInt + | MustMintValue ScriptHash RedeemerDatum AssetName Int.Int (Maybe InputWithScriptRef) - | MustMintValueUsingNativeScript NativeScript TokenName BigInt + | MustMintValueUsingNativeScript NativeScript AssetName Int.Int | MustPayToPubKeyAddress PaymentPubKeyHash (Maybe StakePubKeyHash) - (Maybe (Datum /\ DatumPresence)) + (Maybe (PlutusData /\ DatumPresence)) (Maybe ScriptRef) Value - | MustPayToNativeScript NativeScriptHash (Maybe Credential) Value - | MustPayToScript ValidatorHash (Maybe Credential) Datum DatumPresence + | MustPayToNativeScript ScriptHash (Maybe Credential) Value + | MustPayToScript ScriptHash (Maybe Credential) PlutusData DatumPresence (Maybe ScriptRef) Value - | MustHashDatum DataHash Datum + | MustHashDatum DataHash PlutusData | MustRegisterStakePubKey StakePubKeyHash | MustDeregisterStakePubKey StakePubKeyHash - | MustRegisterStakeScript StakeValidatorHash - | MustDeregisterStakePlutusScript PlutusScriptStakeValidator Redeemer - | MustDeregisterStakeNativeScript NativeScriptStakeValidator - | MustRegisterPool PoolRegistrationParams + | MustRegisterStakeScript ScriptHash + | MustDeregisterStakePlutusScript PlutusScript RedeemerDatum + | MustDeregisterStakeNativeScript NativeScript + | MustRegisterPool PoolParams | MustRetirePool PoolPubKeyHash Epoch | MustDelegateStakePubKey StakePubKeyHash PoolPubKeyHash - | MustDelegateStakePlutusScript PlutusScriptStakeValidator Redeemer + | MustDelegateStakePlutusScript PlutusScript RedeemerDatum PoolPubKeyHash - | MustDelegateStakeNativeScript NativeScriptStakeValidator PoolPubKeyHash + | MustDelegateStakeNativeScript NativeScript PoolPubKeyHash | MustWithdrawStakePubKey StakePubKeyHash - | MustWithdrawStakePlutusScript PlutusScriptStakeValidator Redeemer - | MustWithdrawStakeNativeScript NativeScriptStakeValidator + | MustWithdrawStakePlutusScript PlutusScript RedeemerDatum + | MustWithdrawStakeNativeScript NativeScript | MustSatisfyAnyOf (Array (Array TxConstraint)) | MustNotBeValid + | MustRegisterDrep Credential (Maybe Anchor) derive instance Eq TxConstraint derive instance Generic TxConstraint _ @@ -218,7 +201,7 @@ instance Show InputWithScriptRef where show = genericShow utxoWithScriptRef - :: InputWithScriptRef -> Map TransactionInput TransactionOutputWithRefScript + :: InputWithScriptRef -> Map TransactionInput TransactionOutput utxoWithScriptRef inputWithRefScript = Map.singleton input output where TransactionUnspentOutput { input, output } = @@ -267,52 +250,40 @@ instance Show OutputConstraint where show = genericShow -- | Restrictions placed on the allocation of funds to outputs of transactions. -newtype TxConstraints = TxConstraints - { constraints :: Array TxConstraint - } +type TxConstraints = Array TxConstraint -derive instance Generic TxConstraints _ -derive instance Newtype TxConstraints _ -derive newtype instance Eq TxConstraints --- Array concatenation allowing duplicates like Plutus -derive newtype instance Semigroup TxConstraints -derive newtype instance Monoid TxConstraints - -instance Show TxConstraints where - show = genericShow +type TxConstraintsDeprecated = Text + "Contract.TxConstraints is deprecated. Use `purescript-cardano-transaction-builder`" -------------------------------------------------------------------------------- -- Helpers -------------------------------------------------------------------------------- -singleton - :: TxConstraint -> TxConstraints -singleton a = over TxConstraints _ { constraints = Array.singleton a } mempty - -- | `mustValidateIn r` requires the transaction's time range to be contained -- | in `r`. mustValidateIn - :: POSIXTimeRange -> TxConstraints + :: Warn TxConstraintsDeprecated => POSIXTimeRange -> TxConstraints mustValidateIn = singleton <<< MustValidateIn -- | Require the transaction to be signed by the public key. mustBeSignedBy - :: PaymentPubKeyHash -> TxConstraints + :: Warn TxConstraintsDeprecated => PaymentPubKeyHash -> TxConstraints mustBeSignedBy = singleton <<< MustBeSignedBy -- | Require the transaction to include a datum. -mustIncludeDatum :: Datum -> TxConstraints +mustIncludeDatum :: Warn TxConstraintsDeprecated => PlutusData -> TxConstraints mustIncludeDatum = singleton <<< MustIncludeDatum -- | Require the transaction to reference (not spend!) the given unspent -- | transaction output. mustReferenceOutput - :: TransactionInput -> TxConstraints + :: Warn TxConstraintsDeprecated => TransactionInput -> TxConstraints mustReferenceOutput = singleton <<< MustReferenceOutput -- | Lock the value with a public key address. (Base Address) mustPayToPubKeyAddress - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> StakePubKeyHash -> Value -> TxConstraints @@ -321,9 +292,10 @@ mustPayToPubKeyAddress pkh skh = -- | Lock the value and datum with a public key address. mustPayToPubKeyAddressWithDatum - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> StakePubKeyHash - -> Datum + -> PlutusData -> DatumPresence -> Value -> TxConstraints @@ -333,7 +305,8 @@ mustPayToPubKeyAddressWithDatum pkh skh datum dtp = -- | Lock the value and reference script with a public key address. mustPayToPubKeyAddressWithScriptRef - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> StakePubKeyHash -> ScriptRef -> Value @@ -343,9 +316,10 @@ mustPayToPubKeyAddressWithScriptRef pkh skh scriptRef = -- | Lock the value, datum and reference script with a public key address. mustPayToPubKeyAddressWithDatumAndScriptRef - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> StakePubKeyHash - -> Datum + -> PlutusData -> DatumPresence -> ScriptRef -> Value @@ -360,6 +334,7 @@ mustPayToPubKey ( Text "Some wallets may not recognize addresses without a staking key component. Consider using mustPayToPubKeyAddress" ) + => Warn TxConstraintsDeprecated => PaymentPubKeyHash -> Value -> TxConstraints @@ -368,8 +343,9 @@ mustPayToPubKey pkh = -- | Lock the value and datum with a payment public key hash. mustPayToPubKeyWithDatum - :: PaymentPubKeyHash - -> Datum + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash + -> PlutusData -> DatumPresence -> Value -> TxConstraints @@ -378,7 +354,8 @@ mustPayToPubKeyWithDatum pkh datum dtp = -- | Lock the value and reference script with a payment public key hash. mustPayToPubKeyWithScriptRef - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> ScriptRef -> Value -> TxConstraints @@ -388,7 +365,7 @@ mustPayToPubKeyWithScriptRef pkh scriptRef = -- | Lock the value, datum and reference script with a payment public key hash. mustPayToPubKeyWithDatumAndScriptRef :: PaymentPubKeyHash - -> Datum + -> PlutusData -> DatumPresence -> ScriptRef -> Value @@ -403,67 +380,66 @@ mustPayToPubKeyWithDatumAndScriptRef pkh datum dtp scriptRef = -- | `mustPayToScript`, and all scripts must be explicitly provided to build -- | the transaction. mustPayToScript - :: ValidatorHash - -> Datum + :: Warn TxConstraintsDeprecated + => ScriptHash + -> PlutusData -> DatumPresence -> Value -> TxConstraints -mustPayToScript vh dt dtp vl = - singleton (MustPayToScript vh Nothing dt dtp Nothing vl) - <> guard (dtp == DatumWitness) (singleton $ MustIncludeDatum dt) +mustPayToScript vhash dat datp = + singleton <<< MustPayToScript vhash Nothing dat datp Nothing mustPayToScriptAddress - :: ValidatorHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> Credential - -> Datum + -> PlutusData -> DatumPresence -> Value -> TxConstraints -mustPayToScriptAddress vh credential dt dtp vl = - singleton (MustPayToScript vh (Just credential) dt dtp Nothing vl) - <> guard (dtp == DatumWitness) (singleton $ MustIncludeDatum dt) +mustPayToScriptAddress vhash cred dat datp = + singleton <<< MustPayToScript vhash (Just cred) dat datp Nothing -- | Lock the value, datum and reference script with a script. -- | Note that the provided reference script does *not* necessarily need to -- | control the spending of the output, i.e. both scripts can be different. mustPayToScriptWithScriptRef - :: ValidatorHash - -> Datum + :: Warn TxConstraintsDeprecated + => ScriptHash + -> PlutusData -> DatumPresence -> ScriptRef -> Value -> TxConstraints -mustPayToScriptWithScriptRef vh dt dtp scriptRef vl = - singleton (MustPayToScript vh Nothing dt dtp (Just scriptRef) vl) - <> guard (dtp == DatumWitness) (singleton $ MustIncludeDatum dt) +mustPayToScriptWithScriptRef vhash dat datp scriptRef = + singleton <<< MustPayToScript vhash Nothing dat datp (Just scriptRef) -- | Lock the value, datum and reference script with a script. -- | Note that the provided reference script does *not* necessarily need to -- | control the spending of the output, i.e. both scripts can be different. mustPayToScriptAddressWithScriptRef - :: forall (i :: Type) (o :: Type) - . ValidatorHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> Credential - -> Datum + -> PlutusData -> DatumPresence -> ScriptRef -> Value -> TxConstraints -mustPayToScriptAddressWithScriptRef vh credential dt dtp scriptRef vl = - singleton (MustPayToScript vh (Just credential) dt dtp (Just scriptRef) vl) - <> guard (dtp == DatumWitness) (singleton $ MustIncludeDatum dt) +mustPayToScriptAddressWithScriptRef vhash cred dat datp scriptRef = + singleton <<< MustPayToScript vhash (Just cred) dat datp (Just scriptRef) mustPayToNativeScript - :: forall (i :: Type) (o :: Type) - . NativeScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> Value -> TxConstraints mustPayToNativeScript nsHash vl = singleton (MustPayToNativeScript nsHash Nothing vl) mustPayToNativeScriptAddress - :: forall (i :: Type) (o :: Type) - . NativeScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> Credential -> Value -> TxConstraints @@ -472,43 +448,40 @@ mustPayToNativeScriptAddress nsHash credential vl = -- | Mint the given `Value` -- | The amount to mint must not be zero. -mustMintValue :: Value -> TxConstraints -mustMintValue = mustMintValueWithRedeemer unitRedeemer +mustMintValue :: Warn TxConstraintsDeprecated => Mint -> TxConstraints +mustMintValue = mustMintValueWithRedeemer RedeemerDatum.unit -- | Mint the given `Value` by accessing non-Ada assets. -- | The amount to mint must not be zero. mustMintValueWithRedeemer - :: forall (i :: Type) (o :: Type) - . Redeemer - -> Value + :: Warn TxConstraintsDeprecated + => RedeemerDatum + -> Mint -> TxConstraints mustMintValueWithRedeemer redeemer = - Array.fold <<< map tokenConstraint <<< flattenNonAdaAssets + Array.fold <<< map tokenConstraint <<< Mint.flatten where tokenConstraint - :: CurrencySymbol /\ TokenName /\ BigInt -> TxConstraints + :: ScriptHash /\ AssetName /\ Int.Int -> TxConstraints tokenConstraint (cs /\ tn /\ amount) = - let - mintingPolicyHash = currencyMPSHash cs - in - mustMintCurrencyWithRedeemer mintingPolicyHash redeemer tn amount + mustMintCurrencyWithRedeemer cs redeemer tn amount -- | Create the given amount of the currency. -- | The amount to mint must not be zero. mustMintCurrency - :: forall (i :: Type) (o :: Type) - . MintingPolicyHash - -> TokenName - -> BigInt + :: Warn TxConstraintsDeprecated + => ScriptHash + -> AssetName + -> Int.Int -> TxConstraints mustMintCurrency mph = - mustMintCurrencyWithRedeemer mph unitRedeemer + mustMintCurrencyWithRedeemer mph RedeemerDatum.unit mustMintCurrencyUsingNativeScript - :: forall (i :: Type) (o :: Type) - . NativeScript - -> TokenName - -> BigInt + :: Warn TxConstraintsDeprecated + => NativeScript + -> AssetName + -> Int.Int -> TxConstraints mustMintCurrencyUsingNativeScript ns tk i = singleton (MustMintValueUsingNativeScript ns tk i) @@ -516,23 +489,23 @@ mustMintCurrencyUsingNativeScript ns tk i = singleton -- | Create the given amount of the currency using a reference minting policy. -- | The amount to mint must not be zero. mustMintCurrencyUsingScriptRef - :: forall (i :: Type) (o :: Type) - . MintingPolicyHash - -> TokenName - -> BigInt + :: Warn TxConstraintsDeprecated + => ScriptHash + -> AssetName + -> Int.Int -> InputWithScriptRef -> TxConstraints mustMintCurrencyUsingScriptRef mph = - mustMintCurrencyWithRedeemerUsingScriptRef mph unitRedeemer + mustMintCurrencyWithRedeemerUsingScriptRef mph RedeemerDatum.unit -- | Create the given amount of the currency. -- | The amount to mint must not be zero. mustMintCurrencyWithRedeemer - :: forall (i :: Type) (o :: Type) - . MintingPolicyHash - -> Redeemer - -> TokenName - -> BigInt + :: Warn TxConstraintsDeprecated + => ScriptHash + -> RedeemerDatum + -> AssetName + -> Int.Int -> TxConstraints mustMintCurrencyWithRedeemer mph red tn amount = singleton (MustMintValue mph red tn amount Nothing) @@ -540,34 +513,34 @@ mustMintCurrencyWithRedeemer mph red tn amount = -- | Create the given amount of the currency using a reference minting policy. -- | The amount to mint must not be zero. mustMintCurrencyWithRedeemerUsingScriptRef - :: forall (i :: Type) (o :: Type) - . MintingPolicyHash - -> Redeemer - -> TokenName - -> BigInt + :: Warn TxConstraintsDeprecated + => ScriptHash + -> RedeemerDatum + -> AssetName + -> Int.Int -> InputWithScriptRef -> TxConstraints mustMintCurrencyWithRedeemerUsingScriptRef mph red tn amount = singleton <<< MustMintValue mph red tn amount <<< Just -- | Requirement to spend inputs with at least the given value -mustSpendAtLeast :: Value -> TxConstraints +mustSpendAtLeast :: Warn TxConstraintsDeprecated => Value -> TxConstraints mustSpendAtLeast = singleton <<< MustSpendAtLeast -- | Requirement to produce outputs with at least the given value -mustProduceAtLeast :: Value -> TxConstraints +mustProduceAtLeast :: Warn TxConstraintsDeprecated => Value -> TxConstraints mustProduceAtLeast = singleton <<< MustProduceAtLeast -- | Spend the given unspent transaction public key output. mustSpendPubKeyOutput - :: TransactionInput -> TxConstraints + :: Warn TxConstraintsDeprecated => TransactionInput -> TxConstraints mustSpendPubKeyOutput = singleton <<< MustSpendPubKeyOutput -- | Spend the given unspent transaction script output. mustSpendScriptOutput - :: forall (i :: Type) (o :: Type) - . TransactionInput - -> Redeemer + :: Warn TxConstraintsDeprecated + => TransactionInput + -> RedeemerDatum -> TxConstraints mustSpendScriptOutput txOutRef red = singleton (MustSpendScriptOutput txOutRef red Nothing) @@ -575,103 +548,103 @@ mustSpendScriptOutput txOutRef red = -- | Spend the given unspent transaction script output, using a reference script -- | to satisfy the script witnessing requirement. mustSpendScriptOutputUsingScriptRef - :: forall (i :: Type) (o :: Type) - . TransactionInput - -> Redeemer + :: Warn TxConstraintsDeprecated + => TransactionInput + -> RedeemerDatum -> InputWithScriptRef -> TxConstraints mustSpendScriptOutputUsingScriptRef txOutRef red = singleton <<< MustSpendScriptOutput txOutRef red <<< Just mustSpendNativeScriptOutput - :: forall (i :: Type) (o :: Type) - . TransactionInput + :: Warn TxConstraintsDeprecated + => TransactionInput -> NativeScript -> TxConstraints mustSpendNativeScriptOutput txOutRef = singleton <<< MustSpendNativeScriptOutput txOutRef mustHashDatum - :: DataHash -> Datum -> TxConstraints + :: Warn TxConstraintsDeprecated => DataHash -> PlutusData -> TxConstraints mustHashDatum dhsh = singleton <<< MustHashDatum dhsh mustRegisterStakePubKey - :: StakePubKeyHash -> TxConstraints + :: Warn TxConstraintsDeprecated => StakePubKeyHash -> TxConstraints mustRegisterStakePubKey = singleton <<< MustRegisterStakePubKey mustDeregisterStakePubKey - :: StakePubKeyHash -> TxConstraints + :: Warn TxConstraintsDeprecated => StakePubKeyHash -> TxConstraints mustDeregisterStakePubKey = singleton <<< MustDeregisterStakePubKey mustRegisterStakeScript - :: StakeValidatorHash -> TxConstraints + :: Warn TxConstraintsDeprecated => ScriptHash -> TxConstraints mustRegisterStakeScript = singleton <<< MustRegisterStakeScript mustDeregisterStakePlutusScript - :: forall (i :: Type) (o :: Type) - . PlutusScriptStakeValidator - -> Redeemer + :: Warn TxConstraintsDeprecated + => PlutusScript + -> RedeemerDatum -> TxConstraints mustDeregisterStakePlutusScript sv = singleton <<< MustDeregisterStakePlutusScript sv mustDeregisterStakeNativeScript - :: forall (i :: Type) (o :: Type) - . NativeScriptStakeValidator + :: Warn TxConstraintsDeprecated + => NativeScript -> TxConstraints mustDeregisterStakeNativeScript = singleton <<< MustDeregisterStakeNativeScript mustRegisterPool - :: PoolRegistrationParams -> TxConstraints + :: Warn TxConstraintsDeprecated => PoolParams -> TxConstraints mustRegisterPool = singleton <<< MustRegisterPool mustRetirePool - :: forall (i :: Type) (o :: Type) - . PoolPubKeyHash + :: Warn TxConstraintsDeprecated + => PoolPubKeyHash -> Epoch -> TxConstraints mustRetirePool poolPubKeyHash = singleton <<< MustRetirePool poolPubKeyHash mustDelegateStakePubKey - :: forall (i :: Type) (o :: Type) - . StakePubKeyHash + :: Warn TxConstraintsDeprecated + => StakePubKeyHash -> PoolPubKeyHash -> TxConstraints mustDelegateStakePubKey spkh ppkh = singleton $ MustDelegateStakePubKey spkh ppkh mustDelegateStakePlutusScript - :: forall (i :: Type) (o :: Type) - . PlutusScriptStakeValidator - -> Redeemer + :: Warn TxConstraintsDeprecated + => PlutusScript + -> RedeemerDatum -> PoolPubKeyHash -> TxConstraints mustDelegateStakePlutusScript sv redeemer ppkh = singleton $ MustDelegateStakePlutusScript sv redeemer ppkh mustDelegateStakeNativeScript - :: forall (i :: Type) (o :: Type) - . NativeScriptStakeValidator + :: Warn TxConstraintsDeprecated + => NativeScript -> PoolPubKeyHash -> TxConstraints mustDelegateStakeNativeScript sv ppkh = singleton $ MustDelegateStakeNativeScript sv ppkh mustWithdrawStakePubKey - :: StakePubKeyHash -> TxConstraints + :: Warn TxConstraintsDeprecated => StakePubKeyHash -> TxConstraints mustWithdrawStakePubKey spkh = singleton $ MustWithdrawStakePubKey spkh mustWithdrawStakePlutusScript - :: forall (i :: Type) (o :: Type) - . PlutusScriptStakeValidator - -> Redeemer + :: Warn TxConstraintsDeprecated + => PlutusScript + -> RedeemerDatum -> TxConstraints mustWithdrawStakePlutusScript validator redeemer = singleton $ MustWithdrawStakePlutusScript validator redeemer mustWithdrawStakeNativeScript - :: forall (i :: Type) (o :: Type) - . NativeScriptStakeValidator + :: Warn TxConstraintsDeprecated + => NativeScript -> TxConstraints mustWithdrawStakeNativeScript = singleton <<< MustWithdrawStakeNativeScript @@ -681,90 +654,25 @@ mustWithdrawStakeNativeScript = -- | `mustSatisfyaAnyOf` is just a way to define a chain of try-catch expressions -- | in a declarative manner. It does not do any analysis of the constraints' semantics. mustSatisfyAnyOf - :: forall (f :: Type -> Type) (i :: Type) (o :: Type) + :: forall (f :: Type -> Type) . Foldable f + => Warn TxConstraintsDeprecated => f (TxConstraints) -> TxConstraints mustSatisfyAnyOf = Array.fromFoldable - >>> map (_.constraints <<< unwrap) >>> MustSatisfyAnyOf >>> singleton -- | Marks the transaction as invalid, requiring at least one script execution -- | to fail. Despite failure, the transaction can still be submitted into the -- | chain and collateral will be lost. -mustNotBeValid :: TxConstraints +mustNotBeValid :: Warn TxConstraintsDeprecated => TxConstraints mustNotBeValid = singleton $ MustNotBeValid --- | Are the constraints satisfiable given the time intervals? -isSatisfiable :: TxConstraints -> Boolean -isSatisfiable (TxConstraints { constraints }) = - let - intervals = - Array.mapMaybe - ( case _ of - MustValidateIn i -> Just i - _ -> Nothing - ) - constraints - itvl = foldl intersection always intervals - in - not (isEmpty itvl) - -pubKeyPayments - :: TxConstraints - -> Array (PaymentPubKeyHash /\ Value) -pubKeyPayments (TxConstraints { constraints }) = - toUnfoldable - $ fromFoldableWith (<>) - $ constraints >>= - case _ of - MustPayToPubKeyAddress pkh _ _ _ vl -> Array.singleton (pkh /\ vl) - _ -> [] - --- | The minimum `Value` that satisfies all `MustSpendAtLeast` constraints -mustSpendAtLeastTotal - :: TxConstraints -> Value -mustSpendAtLeastTotal = - foldr (join <<< f) mempty <<< _.constraints <<< unwrap - where - f :: TxConstraint -> Value - f (MustSpendAtLeast v) = v - f _ = mempty - --- | The minimum `Value` that satisfies all `MustProduceAtLeast` constraints -mustProduceAtLeastTotal - :: TxConstraints -> Value -mustProduceAtLeastTotal = - foldr (join <<< f) mempty <<< _.constraints <<< unwrap - where - f :: TxConstraint -> Value - f (MustProduceAtLeast v) = v - f _ = mempty - -requiredSignatories - :: TxConstraints - -> Array PaymentPubKeyHash -requiredSignatories = foldMap f <<< _.constraints <<< unwrap - where - f :: TxConstraint -> Array PaymentPubKeyHash - f (MustBeSignedBy pkh) = Array.singleton pkh - f _ = [] - -requiredMonetaryPolicies - :: TxConstraints - -> Array MintingPolicyHash -requiredMonetaryPolicies = foldMap f <<< _.constraints <<< unwrap - where - f :: TxConstraint -> Array MintingPolicyHash - f (MustMintValue mph _ _ _ _) = Array.singleton mph - f _ = [] - -requiredDatums - :: TxConstraints -> Array Datum -requiredDatums = foldMap f <<< _.constraints <<< unwrap - where - f :: TxConstraint -> Array Datum - f (MustIncludeDatum dt) = Array.singleton dt - f _ = [] +mustRegisterDrep + :: Warn TxConstraintsDeprecated + => Credential + -> Maybe Anchor + -> TxConstraints +mustRegisterDrep drepCred = singleton <<< MustRegisterDrep drepCred diff --git a/src/Internal/Types/UsedTxOuts.purs b/src/Internal/Types/UsedTxOuts.purs index abb8da6aa5..d18e864f81 100644 --- a/src/Internal/Types/UsedTxOuts.purs +++ b/src/Internal/Types/UsedTxOuts.purs @@ -18,6 +18,8 @@ module Ctl.Internal.Types.UsedTxOuts , withLockedTransactionInputs ) where +import Cardano.Types.Transaction (Transaction) +import Cardano.Types.TransactionHash (TransactionHash) import Control.Alt ((<$>)) import Control.Alternative (guard, pure) import Control.Applicative (unless) @@ -26,8 +28,6 @@ import Control.Category ((<<<), (>>>)) import Control.Monad.Error.Class (class MonadError, catchError, throwError) import Control.Monad.RWS (ask) import Control.Monad.Reader (class MonadAsk) -import Ctl.Internal.Cardano.Types.Transaction (Transaction) -import Ctl.Internal.Types.Transaction (TransactionHash) import Data.Array (concatMap) import Data.Foldable (class Foldable, all, foldr) import Data.Function (($)) @@ -226,4 +226,4 @@ isTxOutRefUsed ref = do txOutRefs :: Transaction -> Set { transactionId :: TransactionHash, index :: UInt } -txOutRefs tx = Set.map unwrap (unwrap (unwrap tx).body).inputs +txOutRefs tx = Set.fromFoldable $ map unwrap (unwrap (unwrap tx).body).inputs diff --git a/src/Internal/Types/VRFKeyHash.purs b/src/Internal/Types/VRFKeyHash.purs deleted file mode 100644 index 9df5541876..0000000000 --- a/src/Internal/Types/VRFKeyHash.purs +++ /dev/null @@ -1,39 +0,0 @@ -module Ctl.Internal.Types.VRFKeyHash - ( VRFKeyHash(VRFKeyHash) - , vrfKeyHashFromBytes - , vrfKeyHashToBytes - , unVRFKeyHash - ) where - -import Prelude - -import Aeson (class EncodeAeson, encodeAeson) -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.Serialization.Hash as Serialization -import Ctl.Internal.Serialization.ToBytes (toBytes) -import Ctl.Internal.Types.ByteArray (ByteArray, byteArrayToHex) -import Data.Function (on) -import Data.Maybe (Maybe) -import Data.Newtype (unwrap, wrap) - -newtype VRFKeyHash = VRFKeyHash Serialization.VRFKeyHash - -instance Show VRFKeyHash where - show (VRFKeyHash kh) = - "(VRFKeyHash " <> show (byteArrayToHex $ unwrap $ toBytes kh) <> ")" - -instance Eq VRFKeyHash where - eq = eq `on` vrfKeyHashToBytes - -instance EncodeAeson VRFKeyHash where - encodeAeson (VRFKeyHash kh) = - toBytes kh # unwrap >>> byteArrayToHex >>> encodeAeson - -unVRFKeyHash :: VRFKeyHash -> Serialization.VRFKeyHash -unVRFKeyHash (VRFKeyHash kh) = kh - -vrfKeyHashFromBytes :: ByteArray -> Maybe VRFKeyHash -vrfKeyHashFromBytes = wrap >>> fromBytes >>> map VRFKeyHash - -vrfKeyHashToBytes :: VRFKeyHash -> ByteArray -vrfKeyHashToBytes (VRFKeyHash kh) = unwrap $ toBytes kh diff --git a/src/Internal/Types/Val.purs b/src/Internal/Types/Val.purs new file mode 100644 index 0000000000..5ac1f1b823 --- /dev/null +++ b/src/Internal/Types/Val.purs @@ -0,0 +1,239 @@ +module Ctl.Internal.Types.Val where + +import Prelude + +import Cardano.AsCbor (encodeCbor) +import Cardano.Types + ( AssetClass(AssetClass) + , AssetName + , BigInt + , Coin + , MultiAsset(MultiAsset) + , ScriptHash + , Value(Value) + ) +import Cardano.Types.AssetName (fromAssetName) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Int as Int +import Cardano.Types.Mint (Mint(Mint)) +import Cardano.Types.MultiAsset as MultiAsset +import Data.Array (cons) +import Data.Bifunctor (bimap) +import Data.ByteArray (byteArrayToHex) +import Data.Foldable (all) +import Data.FoldableWithIndex (foldrWithIndex) +import Data.Generic.Rep (class Generic) +import Data.Lattice (class JoinSemilattice, class MeetSemilattice) +import Data.Log.Tag (TagSet, tag, tagSetTag) +import Data.Log.Tag as TagSet +import Data.Map (Map) +import Data.Map as Map +import Data.Maybe (Maybe, fromMaybe) +import Data.Newtype (unwrap, wrap) +import Data.Show.Generic (genericShow) +import Data.These (These(This, That, Both)) +import Data.Traversable (traverse) +import Data.Tuple.Nested (type (/\), (/\)) +import JS.BigInt as BigInt + +-- | A long-integer-backed Value that can be negative and does not overflow. +-- | Used in CTL internally instead of the ledger-style `Value` type to simplify +-- | overflow handling. +data Val = Val BigInt ValAssets + +instance Eq Val where + eq = checkBinRel (==) + +instance Semigroup Val where + append (Val a ma) (Val b mb) = Val (a + b) (unionWithNonAda add ma mb) + +instance Monoid Val where + mempty = Val zero Map.empty + +derive instance Generic Val _ + +instance Show Val where + show = genericShow + +instance JoinSemilattice Val where + join (Val c1 m1) (Val c2 m2) = Val (c1 `max` c2) (m1 `unionWithNonAda max` m2) + +instance MeetSemilattice Val where + meet (Val c1 m1) (Val c2 m2) = Val (c1 `min` c2) (m1 `unionWithNonAda min` m2) + +-- | Split a value into its positive and non-positive parts. The first element of +-- | the tuple contains the non-positive parts of the value, the second element +-- | contains the positive parts. The convention is non-positive parts are +-- | negated to make them positive in the output. +class Split (a :: Type) where + split :: a -> a /\ a + +instance Split BigInt where + split c = + if c <= zero then negate c /\ zero else zero /\ c + +instance Split Val where + split (Val c1 mp) = Val np npos /\ Val p pos + where + np /\ p = split c1 + + splitIntl + :: Map AssetName BigInt + -> These (Map AssetName BigInt) (Map AssetName BigInt) + splitIntl mp' = Both l r + where + l /\ r = mapThese (\i -> if i <= zero then This (negate i) else That i) + mp' + + npos /\ pos = mapThese splitIntl mp + +type ValAssets = Map ScriptHash (Map AssetName BigInt) + +leq :: Val -> Val -> Boolean +leq = checkBinRel (<=) + +-- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#checkBinRel +-- Check whether a binary relation holds for value pairs of two `Value` maps, +-- supplying 0 where a key is only present in one of them. +checkBinRel :: (BigInt -> BigInt -> Boolean) -> Val -> Val -> Boolean +checkBinRel f l r = + let + unThese :: These BigInt BigInt -> Boolean + unThese k' = case k' of + This a -> f a zero + That b -> f zero b + Both a b -> f a b + in + checkPred unThese l r + +-- https://playground.plutus.iohkdev.io/doc/haddock/plutus-ledger-api/html/src/Plutus.V1.Ledger.Value.html#checkPred +checkPred :: (These BigInt BigInt -> Boolean) -> Val -> Val -> Boolean +checkPred f (Val l ls) (Val r rs) = + let + inner :: Map AssetName (These BigInt BigInt) -> Boolean + inner = all f -- this "all" may need to be checked? + in + f (Both l r) && all inner (unionNonAda ls rs) -- this "all" may need to be checked? + +getCoin :: Val -> BigInt +getCoin (Val c _) = c + +getAssets :: Val -> Map ScriptHash (Map AssetName BigInt) +getAssets (Val _ ma) = ma + +getAssetQuantity :: AssetClass -> Val -> BigInt +getAssetQuantity (AssetClass sh tn) val = + fromMaybe zero $ Map.lookup sh (getAssets val) >>= Map.lookup tn + +valueAssets :: Val -> Array (AssetClass /\ BigInt) +valueAssets (Val _ ma) = + Map.toUnfoldable ma >>= \(scriptHash /\ mp) -> + Map.toUnfoldable mp >>= \(tokenName /\ amount) -> + [ AssetClass scriptHash tokenName /\ amount ] + +pprintVal :: Val -> TagSet +pprintVal (Val coin ma) = TagSet.fromArray $ + [ "Lovelace" `tag` BigInt.toString coin ] + <> + if ma /= Map.empty then + [ "Assets" `tagSetTag` pprintMultiAsset ma ] + else [] + where + + pprintMultiAsset :: Map ScriptHash (Map AssetName BigInt) -> TagSet + pprintMultiAsset mp = TagSet.fromArray $ + Map.toUnfoldable mp <#> \(scriptHash /\ tokens) -> + byteArrayToHex (unwrap $ encodeCbor scriptHash) `tagSetTag` + TagSet.fromArray + ( Map.toUnfoldable tokens <#> \(assetName /\ amount) -> + fromAssetName byteArrayToHex show assetName `tag` BigInt.toString + amount + ) + +fromCoin :: Coin -> Val +fromCoin = flip Val Map.empty <<< BigNum.toBigInt <<< unwrap + +fromValue :: Value -> Val +fromValue (Value coin ma) = Val (BigNum.toBigInt $ unwrap coin) + $ map (map BigNum.toBigInt) + $ unwrap ma + +toMultiAsset :: Map ScriptHash (Map AssetName BigInt) -> Maybe MultiAsset +toMultiAsset = map (map wrap) $ traverse $ traverse $ BigNum.fromBigInt + +toValue :: Val -> Maybe Value +toValue (Val coin ma) = do + ma' <- toMultiAsset ma + coin' <- BigNum.fromBigInt coin + pure $ Value (wrap coin') ma' + +fromMultiAsset :: MultiAsset -> Val +fromMultiAsset (MultiAsset ma) = Val zero $ map (map BigNum.toBigInt) ma + +fromMint :: Mint -> Val +fromMint (Mint ma) = Val zero $ map (map Int.toBigInt) $ ma + +minus :: Val -> Val -> Val +minus (Val a ma) (Val b mb) = Val (a - b) (unionWithNonAda (-) ma mb) + +-- Like `mapEither` that works with 'These'. +mapThese + :: forall (a :: Type) (b :: Type) (k :: Type) (v :: Type) + . Ord k + => (v -> These a b) + -> Map k v + -> Map k a /\ Map k b +mapThese f mps = + bimap Map.fromFoldable Map.fromFoldable $ foldrWithIndex f' ([] /\ []) mps' + where + mps' :: Map k (These a b) + mps' = map f mps + + f' + :: k + -> These a b + -> Array (k /\ a) /\ Array (k /\ b) + -> Array (k /\ a) /\ Array (k /\ b) + f' k v (as /\ bs) = case v of + This a -> (k /\ a) `cons` as /\ bs + That b -> as /\ (k /\ b) `cons` bs + Both a b -> (k /\ a) `cons` as /\ (k /\ b) `cons` bs + +unionWithNonAda + :: (BigInt -> BigInt -> BigInt) + -> Map ScriptHash (Map AssetName BigInt) + -> Map ScriptHash (Map AssetName BigInt) + -> Map ScriptHash (Map AssetName BigInt) +unionWithNonAda f ls rs = + let + combined :: Map ScriptHash (Map AssetName (These BigInt BigInt)) + combined = unionNonAda ls rs + + unBoth :: These BigInt BigInt -> BigInt + unBoth k' = case k' of + This a -> f a zero + That b -> f zero b + Both a b -> f a b + in + map (map unBoth) combined + +unionNonAda + :: Map ScriptHash (Map AssetName BigInt) + -> Map ScriptHash (Map AssetName BigInt) + -> Map ScriptHash (Map AssetName (These BigInt BigInt)) +unionNonAda l r = + let + combined + :: Map ScriptHash + (These (Map AssetName BigInt) (Map AssetName BigInt)) + combined = MultiAsset.union l r + + unBoth + :: These (Map AssetName BigInt) (Map AssetName BigInt) + -> Map AssetName (These BigInt BigInt) + unBoth k = case k of + This a -> This <$> a + That b -> That <$> b + Both a b -> MultiAsset.union a b + in + unBoth <$> combined diff --git a/src/Internal/Wallet.js b/src/Internal/Wallet.js index 99197ef234..925d4135ab 100644 --- a/src/Internal/Wallet.js +++ b/src/Internal/Wallet.js @@ -13,7 +13,7 @@ const checkNotNode = () => { } }; -const isWalletAvailable = walletName => () => { +export const isWalletAvailable = walletName => () => { checkNotNode(); return ( typeof getWindow().cardano != "undefined" && @@ -21,5 +21,3 @@ const isWalletAvailable = walletName => () => { typeof getWindow().cardano[walletName].enable == "function" ); }; - -export { isWalletAvailable as _isWalletAvailable }; diff --git a/src/Internal/Wallet.purs b/src/Internal/Wallet.purs index 30b7721ae6..51e1619189 100644 --- a/src/Internal/Wallet.purs +++ b/src/Internal/Wallet.purs @@ -1,15 +1,7 @@ module Ctl.Internal.Wallet - ( Wallet(KeyWallet, GenericCip30) + ( Cip30Extensions + , Wallet(KeyWallet, GenericCip30) , WalletExtension - ( NamiWallet - , LodeWallet - , GeroWallet - , FlintWallet - , EternlWallet - , NuFiWallet - , LaceWallet - , GenericCip30Wallet - ) , mkKeyWallet , mkWalletAff , actionBasedOnWallet @@ -18,23 +10,28 @@ module Ctl.Internal.Wallet import Prelude -import Cardano.Wallet.Cip30 as Cip30 -import Control.Monad.Error.Class (catchError, throwError) -import Ctl.Internal.Types.Natural (fromInt', minus) -import Ctl.Internal.Wallet.Cip30 (Cip30Wallet, mkCip30WalletAff) -import Ctl.Internal.Wallet.Key +import Cardano.Wallet.Cip30 (Api) +import Cardano.Wallet.Cip30 (enable) as Cip30 +import Cardano.Wallet.Cip95 (enable) as Cip95 +import Cardano.Wallet.Key ( KeyWallet + , PrivateDrepKey , PrivatePaymentKey , PrivateStakeKey , privateKeysToKeyWallet ) +import Control.Monad.Error.Class (catchError, throwError) +import Ctl.Internal.Wallet.Cip30 (Cip30Wallet, mkCip30WalletAff) import Data.Int (toNumber) import Data.Maybe (Maybe) import Data.Newtype (wrap) import Effect (Effect) -import Effect.Aff (Aff, delay, error) +import Effect.Aff (Aff, delay) import Effect.Aff.Class (class MonadAff, liftAff) import Effect.Class (liftEffect) +import Effect.Console as Console + +foreign import isWalletAvailable :: String -> Effect Boolean -- NOTE: this data type is defined like this on purpose, don't change it -- to `(Cip30Wallet /\ WalletExtension)`. The motivation is to make it simpler @@ -43,63 +40,46 @@ data Wallet = GenericCip30 Cip30Wallet | KeyWallet KeyWallet -data WalletExtension - = NamiWallet - | GeroWallet - | FlintWallet - | EternlWallet - | LodeWallet - | LaceWallet - | NuFiWallet - | GenericCip30Wallet String +type WalletExtension = + { name :: String + , exts :: Cip30Extensions + } -mkKeyWallet :: PrivatePaymentKey -> Maybe PrivateStakeKey -> Wallet -mkKeyWallet payKey mbStakeKey = KeyWallet $ privateKeysToKeyWallet - payKey - mbStakeKey +type Cip30Extensions = + { cip95 :: Boolean + } -foreign import _isWalletAvailable :: String -> Effect Boolean +mkKeyWallet + :: PrivatePaymentKey + -> Maybe PrivateStakeKey + -> Maybe PrivateDrepKey + -> Wallet +mkKeyWallet payKey mbStakeKey mbDrepKey = + KeyWallet $ privateKeysToKeyWallet payKey mbStakeKey mbDrepKey mkWalletAff :: WalletExtension -> Aff Wallet -mkWalletAff LodeWallet = _mkLodeWalletAff -mkWalletAff (GenericCip30Wallet "LodeWallet") = _mkLodeWalletAff -mkWalletAff walletExtension = - GenericCip30 <$> - ( mkCip30WalletAff =<< Cip30.enable (walletExtensionToName walletExtension) - [] - ) - --- Lode does not inject on page load, so this function retries up to set --- number of times, for Lode to become available. -_mkLodeWalletAff :: Aff Wallet -_mkLodeWalletAff = do - retryNWithIntervalUntil (fromInt' 10) (toNumber 100) - $ liftEffect (isWalletAvailable LodeWallet) - (GenericCip30 <$> (mkCip30WalletAff =<< Cip30.enable "LodeWallet" [])) - `catchError` - ( \e -> throwError <<< error $ show e <> - " Note: LodeWallet is injected asynchronously and may be unreliable." - ) +mkWalletAff walletExtension = do + retryNWithIntervalUntil 300 (toNumber 100) $ + liftEffect (isWalletAvailable walletExtension.name) + GenericCip30 <$> do + mkCip30WalletAff =<< do + enableWallet walletExtension `catchError` + \err -> do + liftEffect $ Console.error $ "Wallet extension " + <> walletExtension.name + <> " is not available!" + throwError err where retryNWithIntervalUntil n ms mBool = if n == zero then pure unit else mBool >>= if _ then pure unit - else delay (wrap ms) *> retryNWithIntervalUntil (n `minus` one) ms mBool - -isWalletAvailable :: WalletExtension -> Effect Boolean -isWalletAvailable = _isWalletAvailable <<< walletExtensionToName + else delay (wrap ms) *> retryNWithIntervalUntil (n - 1) ms mBool -walletExtensionToName :: WalletExtension -> String -walletExtensionToName = case _ of - NamiWallet -> "nami" - GeroWallet -> "gerowallet" - FlintWallet -> "flint" - EternlWallet -> "eternl" - LodeWallet -> "LodeWallet" - NuFiWallet -> "nufi" - LaceWallet -> "lace" - GenericCip30Wallet name' -> name' +enableWallet :: WalletExtension -> Aff Api +enableWallet { name, exts: { cip95 } } + | cip95 = Cip95.enable name + | otherwise = Cip30.enable name mempty actionBasedOnWallet :: forall (m :: Type -> Type) (a :: Type) diff --git a/src/Internal/Wallet/Bip32.js b/src/Internal/Wallet/Bip32.js deleted file mode 100644 index 9518c96977..0000000000 --- a/src/Internal/Wallet/Bip32.js +++ /dev/null @@ -1,38 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - -import bip39 from "bip39"; - -const HARDENED = 0x80000000; - -export function _bip32PrivateKeyFromMnemonic(left) { - return right => phrase => { - try { - return right( - lib.Bip32PrivateKey.from_bip39_entropy( - Uint8Array.from( - Buffer.from(bip39.mnemonicToEntropy(phrase.toLowerCase()), "hex") - ), - new Uint8Array() // passphrase (not currently implemented) - ) - ); - } catch (e) { - return left(e.toString()); - } - }; -} - -export function bip32ToPrivateKey(privateKey) { - return privateKey.to_raw_key(); -} - -export function derivePrivateKey(path) { - return hardened => privateKey => - privateKey.derive(path | (hardened ? HARDENED : 0)); -} diff --git a/src/Internal/Wallet/Bip32.purs b/src/Internal/Wallet/Bip32.purs deleted file mode 100644 index 6426648928..0000000000 --- a/src/Internal/Wallet/Bip32.purs +++ /dev/null @@ -1,75 +0,0 @@ -module Ctl.Internal.Wallet.Bip32 - ( Cip1852Account - , bip32ToPrivateKey - , bip32PrivateKeyFromMnemonic - , cip1852AccountFromBip32PrivateKey - , cip1852AccountFromMnemonic - , derivePaymentKey - , deriveChangeKey - , deriveStakeKey - ) where - -import Contract.Prelude - -import Ctl.Internal.Serialization.Types (Bip32PrivateKey, PrivateKey) -import Data.UInt (UInt) -import Data.UInt as UInt - -newtype Cip1852Account = Cip1852Account Bip32PrivateKey - -foreign import _bip32PrivateKeyFromMnemonic - :: (String -> Either String Bip32PrivateKey) - -> (Bip32PrivateKey -> Either String Bip32PrivateKey) - -> String - -> Either String Bip32PrivateKey - -foreign import derivePrivateKey - :: UInt - -- ^ path index - -> Boolean - -- ^ hardened - -> Bip32PrivateKey - -> Bip32PrivateKey - --- | Convert a BIP32 private key to a raw private key -foreign import bip32ToPrivateKey :: Bip32PrivateKey -> PrivateKey - --- | Derive a BIP32 private key given a mnemonic phrase -bip32PrivateKeyFromMnemonic :: String -> Either String Bip32PrivateKey -bip32PrivateKeyFromMnemonic = _bip32PrivateKeyFromMnemonic Left Right - --- | Derive a CIP1852 account from a BIP32 private key given an account index -cip1852AccountFromBip32PrivateKey :: UInt -> Bip32PrivateKey -> Cip1852Account -cip1852AccountFromBip32PrivateKey account key = - Cip1852Account - $ key - # derivePrivateKey (UInt.fromInt 1852) true - # derivePrivateKey (UInt.fromInt 1815) true - # derivePrivateKey account true - --- | Derive a CIP1852 account given a mnemonic phrase and account index -cip1852AccountFromMnemonic :: String -> UInt -> Either String Cip1852Account -cip1852AccountFromMnemonic phrase account = - cip1852AccountFromBip32PrivateKey account - <$> bip32PrivateKeyFromMnemonic phrase - --- | Derive a payment key for the given account -derivePaymentKey :: Cip1852Account -> UInt -> Bip32PrivateKey -derivePaymentKey (Cip1852Account key) index = - key - # derivePrivateKey zero false - # derivePrivateKey index false - --- | Derive a change key for the given account -deriveChangeKey :: Cip1852Account -> UInt -> Bip32PrivateKey -deriveChangeKey (Cip1852Account key) index = - key - # derivePrivateKey one false - # derivePrivateKey index false - --- | Derive the stake key for the given account -deriveStakeKey :: Cip1852Account -> Bip32PrivateKey -deriveStakeKey (Cip1852Account key) = - key - # derivePrivateKey (UInt.fromInt 2) false - # derivePrivateKey (UInt.fromInt 0) false diff --git a/src/Internal/Wallet/Cip30.purs b/src/Internal/Wallet/Cip30.purs index 977bc565d3..57e1436caa 100644 --- a/src/Internal/Wallet/Cip30.purs +++ b/src/Internal/Wallet/Cip30.purs @@ -6,55 +6,40 @@ module Ctl.Internal.Wallet.Cip30 import Prelude +import Cardano.AsCbor (decodeCbor, encodeCbor) +import Cardano.Serialization.Lib (fromBytes, toBytes) +import Cardano.Types.Address (Address) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.CborBytes (CborBytes) +import Cardano.Types.Coin (Coin(Coin)) +import Cardano.Types.PublicKey (PublicKey) +import Cardano.Types.PublicKey (fromRawBytes) as PublicKey +import Cardano.Types.RawBytes (RawBytes) +import Cardano.Types.Transaction (Transaction(Transaction)) +import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput) +import Cardano.Types.TransactionUnspentOutput as TransactionUnspentOuput +import Cardano.Types.TransactionUnspentOutput as UnspentOutput +import Cardano.Types.TransactionWitnessSet (TransactionWitnessSet) +import Cardano.Types.Value (Value) +import Cardano.Types.Value as Value import Cardano.Wallet.Cip30 (Api) import Cardano.Wallet.Cip30.TypeSafe (APIError) import Cardano.Wallet.Cip30.TypeSafe as Cip30 -import Control.Alt ((<|>)) +import Cardano.Wallet.Cip95.TypeSafe + ( getPubDrepKey + , getRegisteredPubStakeKeys + , getUnregisteredPubStakeKeys + ) as Cip95 import Control.Monad.Error.Class (catchError, liftMaybe, throwError) -import Ctl.Internal.Cardano.Types.Transaction - ( Transaction(Transaction) - , TransactionWitnessSet - ) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput - ) -import Ctl.Internal.Cardano.Types.Value (Coin(Coin), Value) -import Ctl.Internal.Deserialization.FromBytes (fromBytes, fromBytesEffect) -import Ctl.Internal.Deserialization.UnspentOutput (convertValue) -import Ctl.Internal.Deserialization.UnspentOutput as Deserialization.UnspentOuput -import Ctl.Internal.Deserialization.WitnessSet as Deserialization.WitnessSet import Ctl.Internal.Helpers (liftM) -import Ctl.Internal.Serialization (convertTransaction, toBytes) as Serialization -import Ctl.Internal.Serialization.Address - ( Address - , baseAddressBytes - , baseAddressFromAddress - , enterpriseAddressBytes - , enterpriseAddressFromAddress - , pointerAddressBytes - , pointerAddressFromAddress - , rewardAddressBytes - , rewardAddressFromAddress - ) -import Ctl.Internal.Serialization.ToBytes (toBytes) -import Ctl.Internal.Types.BigNum as BigNum -import Ctl.Internal.Types.ByteArray (byteArrayToHex) -import Ctl.Internal.Types.CborBytes - ( CborBytes - , cborBytesToHex - , hexToCborBytes - , rawBytesAsCborBytes - ) -import Ctl.Internal.Types.RawBytes (RawBytes, hexToRawBytes, rawBytesToHex) -import Data.Maybe (Maybe(Nothing), maybe) -import Data.Newtype (unwrap) +import Data.ByteArray (byteArrayToHex, hexToByteArray) +import Data.Maybe (Maybe(Nothing)) +import Data.Newtype (unwrap, wrap) import Data.Traversable (for, traverse) import Data.Variant (Variant, match) -import Effect (Effect) import Effect.Aff (Aff) import Effect.Class (liftEffect) import Effect.Exception (error, throw) -import JS.BigInt (fromInt) as BigInt type DataSignature = { key :: CborBytes @@ -101,36 +86,34 @@ type Cip30Wallet = , getRewardAddresses :: Aff (Array Address) , signTx :: Transaction -> Aff Transaction , signData :: Address -> RawBytes -> Aff DataSignature + , getPubDrepKey :: Aff PublicKey + , getRegisteredPubStakeKeys :: Aff (Array PublicKey) + , getUnregisteredPubStakeKeys :: Aff (Array PublicKey) } -mkCip30WalletAff - :: Api - -- ^ A function to get wallet connection - -> Aff Cip30Wallet -mkCip30WalletAff connection = do +mkCip30WalletAff :: Api -> Aff Cip30Wallet +mkCip30WalletAff conn = pure - { connection - , getNetworkId: Cip30.getNetworkId connection >>= handleApiError - , getUtxos: getUtxos connection - , getCollateral: getCollateral connection - , getBalance: getBalance connection - , getUsedAddresses: getUsedAddresses connection - , getUnusedAddresses: getUnusedAddresses connection - , getChangeAddress: getChangeAddress connection - , getRewardAddresses: getRewardAddresses connection - , signTx: signTx connection - , signData: signData connection + { connection: conn + , getNetworkId: Cip30.getNetworkId conn >>= handleApiError + , getUtxos: getUtxos conn + , getCollateral: getCollateral conn + , getBalance: getBalance conn + , getUsedAddresses: getUsedAddresses conn + , getUnusedAddresses: getUnusedAddresses conn + , getChangeAddress: getChangeAddress conn + , getRewardAddresses: getRewardAddresses conn + , signTx: signTx conn + , signData: signData conn + , getPubDrepKey: getPubDrepKey conn + , getRegisteredPubStakeKeys: getRegisteredPubStakeKeys conn + , getUnregisteredPubStakeKeys: getUnregisteredPubStakeKeys conn } ------------------------------------------------------------------------------- -- Helper functions ------------------------------------------------------------------------------- -txToHex :: Transaction -> Effect String -txToHex = - map (byteArrayToHex <<< unwrap <<< Serialization.toBytes) - <<< Serialization.convertTransaction - handleApiError :: forall a. Variant (apiError :: APIError, success :: a) -> Aff a handleApiError = match @@ -170,10 +153,10 @@ getUsedAddresses conn = do } hexStringToAddress :: String -> Maybe Address -hexStringToAddress = fromBytes <<< rawBytesAsCborBytes <=< hexToRawBytes +hexStringToAddress = decodeCbor <=< map wrap <<< hexToByteArray defaultCollateralAmount :: Coin -defaultCollateralAmount = Coin $ BigInt.fromInt 5_000_000 +defaultCollateralAmount = Coin $ BigNum.fromInt 5_000_000 -- | Get collateral using CIP-30 `getCollateral` method. -- | Throws on `Promise` rejection by wallet, returns `Nothing` if no collateral @@ -184,9 +167,10 @@ getCollateral conn = do liftEffect $ for mbUtxoStrs \utxoStrs -> do for utxoStrs \utxoStr -> do liftM (error $ "CIP-30 getCollateral returned bad UTxO: " <> utxoStr) $ - Deserialization.UnspentOuput.convertUnspentOutput - =<< fromBytes - =<< hexToCborBytes utxoStr + TransactionUnspentOuput.fromCsl <$> + ( fromBytes + =<< hexToByteArray utxoStr + ) getUtxos :: Api -> Aff (Maybe (Array TransactionUnspentOutput)) getUtxos conn = do @@ -195,29 +179,31 @@ getUtxos conn = do { success: \mbUtxoArray -> do liftEffect $ for mbUtxoArray $ \utxoArray -> for utxoArray \str -> do liftMaybe (error $ "CIP-30 getUtxos returned bad UTxO: " <> str) $ - hexToCborBytes str >>= fromBytes >>= - Deserialization.UnspentOuput.convertUnspentOutput + (hexToByteArray str >>= fromBytes) <#> UnspentOutput.fromCsl , paginateError: show >>> throw >>> liftEffect , apiError: show >>> throw >>> liftEffect } signTx :: Api -> Transaction -> Aff Transaction signTx conn tx = do - txHex <- liftEffect $ txToHex tx + let txHex = txToHex tx result <- Cip30.signTx conn txHex true liftEffect $ result `flip match` { success: \hexString -> do - bytes <- liftM (mkInvalidHexError hexString) $ hexToRawBytes - hexString - combineWitnessSet tx <$> - ( Deserialization.WitnessSet.convertWitnessSet - <$> fromBytesEffect (rawBytesAsCborBytes bytes) - ) + bytes <- liftM (mkInvalidHexError hexString) $ + hexToByteArray hexString + ws <- liftM (error "signTx: unable to decode WitnessSet cbor") + $ decodeCbor (wrap bytes) + pure $ combineWitnessSet tx ws , apiError: show >>> throw , txSignError: show >>> throw } where + + txToHex :: Transaction -> String + txToHex = encodeCbor >>> unwrap >>> byteArrayToHex + -- We have to combine the newly returned witness set with the existing one -- Otherwise, any datums, etc... won't be retained combineWitnessSet :: Transaction -> TransactionWitnessSet -> Transaction @@ -231,53 +217,58 @@ signTx conn tx = do -- | `PointerAddress` and `RewardAddress` signData :: Api -> Address -> RawBytes -> Aff DataSignature signData conn address dat = do - byteAddress <- - liftMaybe - (error "Can't convert Address to base, enterprise, pointer or reward") - (fromBase <|> fromEnterprise <|> fromPointer <|> fromReward) - result <- Cip30.signData conn (cborBytesToHex byteAddress) - (rawBytesToHex dat) + -- TODO: forbid byron addresses + let byteAddress = encodeCbor address + result <- Cip30.signData conn (byteArrayToHex $ unwrap byteAddress) + (byteArrayToHex $ unwrap dat) liftEffect $ result `flip match` { dataSignError: show >>> throw , apiError: show >>> throw , success: \signedData -> do - key <- liftM byteError $ hexToCborBytes signedData.key - signature <- liftM byteError $ hexToCborBytes signedData.signature - pure { key: key, signature: signature } + key <- liftM byteError $ hexToByteArray signedData.key + signature <- liftM byteError $ hexToByteArray signedData.signature + pure { key: wrap key, signature: wrap signature } } where byteError = error "signData: hexToCborBytes failure" - fromBase :: Maybe CborBytes - fromBase = baseAddressBytes <$> baseAddressFromAddress address - - fromEnterprise :: Maybe CborBytes - fromEnterprise = enterpriseAddressBytes <$> - enterpriseAddressFromAddress address - - fromPointer :: Maybe CborBytes - fromPointer = pointerAddressBytes <$> pointerAddressFromAddress address - - fromReward :: Maybe CborBytes - fromReward = rewardAddressBytes <$> rewardAddressFromAddress address - getBalance :: Api -> Aff Value getBalance conn = do Cip30.getBalance conn >>= handleApiError >>= liftM (error "CIP-30 getUsedAddresses returned non-address") <<< - (hexToCborBytes >=> fromBytes >=> convertValue) + (hexToByteArray >=> fromBytes >>> map Value.fromCsl) -getCip30Collateral - :: Api -> Coin -> Aff (Maybe (Array String)) -getCip30Collateral conn requiredValue = do - bigNumValue <- liftEffect $ maybe (throw convertError) pure - $ BigNum.fromBigInt - $ unwrap requiredValue - let requiredValueStr = byteArrayToHex $ unwrap $ toBytes bigNumValue +getCip30Collateral :: Api -> Coin -> Aff (Maybe (Array String)) +getCip30Collateral conn (Coin requiredValue) = do + let requiredValueStr = byteArrayToHex $ toBytes $ unwrap requiredValue (Cip30.getCollateral conn requiredValueStr >>= handleApiError) `catchError` \err -> throwError $ error $ "Failed to call `getCollateral`: " <> show err - where - convertError = - "Unable to convert CIP-30 getCollateral required value: " <> - show requiredValue + +getPubDrepKey :: Api -> Aff PublicKey +getPubDrepKey conn = do + drepKeyHex <- handleApiError =<< Cip95.getPubDrepKey conn + pubKeyFromHex drepKeyHex $ + "CIP-95 getPubDRepKey returned invalid DRep key: " + <> drepKeyHex + +getRegisteredPubStakeKeys :: Api -> Aff (Array PublicKey) +getRegisteredPubStakeKeys conn = do + keys <- handleApiError =<< Cip95.getRegisteredPubStakeKeys conn + for keys \pubStakeKeyHex -> + pubKeyFromHex pubStakeKeyHex $ + "CIP-95 getRegisteredPubStakeKeys returned invalid key: " + <> pubStakeKeyHex + +getUnregisteredPubStakeKeys :: Api -> Aff (Array PublicKey) +getUnregisteredPubStakeKeys conn = do + keys <- handleApiError =<< Cip95.getUnregisteredPubStakeKeys conn + for keys \pubStakeKeyHex -> + pubKeyFromHex pubStakeKeyHex $ + "CIP-95 getUnregisteredPubStakeKeys returned invalid key: " + <> pubStakeKeyHex + +pubKeyFromHex :: String -> String -> Aff PublicKey +pubKeyFromHex keyHex err = + liftM (error err) + (PublicKey.fromRawBytes <<< wrap =<< hexToByteArray keyHex) diff --git a/src/Internal/Wallet/Cip30/SignData.js b/src/Internal/Wallet/Cip30/SignData.js deleted file mode 100644 index b105a9ee30..0000000000 --- a/src/Internal/Wallet/Cip30/SignData.js +++ /dev/null @@ -1,131 +0,0 @@ -/* global BROWSER_RUNTIME */ - -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@emurgo/cardano-message-signing-browser"); -} else { - lib = await import("@emurgo/cardano-message-signing-nodejs"); -} - -// ----------------------------------------------------------------------------- -// COSESign1Builder -// ----------------------------------------------------------------------------- - -// newCoseSign1Builder :: ByteArray -> Headers -> Effect COSESign1Builder -export function newCoseSign1Builder(payload) { - return headers => () => { - return lib.COSESign1Builder.new(headers, payload, false); - }; -} - -// makeDataToSign :: COSESign1Builder -> ByteArray -export function makeDataToSign(builder) { - return builder.make_data_to_sign().to_bytes(); -} - -// sign :: PrivateKey -> ByteArray -> ByteArray -export function sign(privateKey) { - return message => { - return privateKey.sign(message).to_bytes(); - }; -} - -// buildSignature :: COSESign1Builder -> ByteArray -> ByteArray -export function buildSignature(builder) { - return signedSigStruct => { - return builder.build(signedSigStruct).to_bytes(); - }; -} - -// ----------------------------------------------------------------------------- -// Headers -// ----------------------------------------------------------------------------- - -// newHeaders :: HeaderMap -> ProtectedHeaderMap -> Headers -export function newHeaders(unprotectedHeaders) { - return protectedHeaders => { - return lib.Headers.new(protectedHeaders, unprotectedHeaders); - }; -} - -// ----------------------------------------------------------------------------- -// ProtectedHeaderMap -// ----------------------------------------------------------------------------- - -// newProtectedHeaderMap :: HeaderMap -> ProtectedHeaderMap -export function newProtectedHeaderMap(headerMap) { - return lib.ProtectedHeaderMap.new(headerMap); -} - -// ----------------------------------------------------------------------------- -// HeaderMap -// ----------------------------------------------------------------------------- - -// newHeaderMap :: Effect HeaderMap -export function newHeaderMap() { - return lib.HeaderMap.new(); -} - -// setAlgHeaderToEdDsa :: HeaderMap -> Effect Unit -export function setAlgHeaderToEdDsa(headerMap) { - return () => { - const label = lib.Label.from_algorithm_id(lib.AlgorithmId.EdDSA); - headerMap.set_algorithm_id(label); - }; -} - -// setAddressHeader :: ByteArray -> HeaderMap -> Effect Unit -export function setAddressHeader(addressBytes) { - return headerMap => () => { - const label = lib.Label.new_text("address"); - const value = lib.CBORValue.new_bytes(addressBytes); - headerMap.set_header(label, value); - }; -} - -// ----------------------------------------------------------------------------- -// COSEKey -// ----------------------------------------------------------------------------- - -// newCoseKeyWithOkpType :: Effect COSEKey -export function newCoseKeyWithOkpType() { - return lib.COSEKey.new(lib.Label.from_key_type(lib.KeyType.OKP)); -} - -// setCoseKeyAlgHeaderToEdDsa :: COSEKey -> Effect Unit -export function setCoseKeyAlgHeaderToEdDsa(key) { - return () => { - key.set_algorithm_id(lib.Label.from_algorithm_id(lib.AlgorithmId.EdDSA)); - }; -} - -// setCoseKeyCrvHeaderToEd25519 :: COSEKey -> Effect Unit -export function setCoseKeyCrvHeaderToEd25519(key) { - return () => { - key.set_header( - lib.Label.new_int( - lib.Int.new_negative(lib.BigNum.from_str("1")) // crv (-1) - ), - lib.CBORValue.new_int( - lib.Int.new_i32(6) // Ed25519 (6) - ) - ); - }; -} - -// setCoseKeyXHeader :: RawBytes -> COSEKey -> Effect Unit -export function setCoseKeyXHeader(publicKeyBytes) { - return key => () => { - key.set_header( - lib.Label.new_int( - lib.Int.new_negative(lib.BigNum.from_str("2")) // x (-2) - ), - lib.CBORValue.new_bytes(publicKeyBytes) // public key bytes - ); - }; -} - -// bytesFromCoseKey :: COSEKey -> CborBytes -export function bytesFromCoseKey(key) { - return key.to_bytes(); -} diff --git a/src/Internal/Wallet/Cip30/SignData.purs b/src/Internal/Wallet/Cip30/SignData.purs deleted file mode 100644 index b7c8741c4b..0000000000 --- a/src/Internal/Wallet/Cip30/SignData.purs +++ /dev/null @@ -1,77 +0,0 @@ -module Ctl.Internal.Wallet.Cip30.SignData (signData) where - -import Prelude - -import Ctl.Internal.Serialization.Address (Address) -import Ctl.Internal.Serialization.Keys - ( bytesFromPublicKey - , publicKeyFromPrivateKey - ) -import Ctl.Internal.Serialization.ToBytes (toBytes) -import Ctl.Internal.Serialization.Types (PrivateKey) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.CborBytes (CborBytes(CborBytes)) -import Ctl.Internal.Types.RawBytes (RawBytes(RawBytes)) -import Ctl.Internal.Wallet.Cip30 (DataSignature) -import Effect (Effect) - -foreign import data COSESign1Builder :: Type -foreign import newCoseSign1Builder - :: ByteArray -> Headers -> Effect COSESign1Builder - -foreign import makeDataToSign :: COSESign1Builder -> ByteArray -foreign import sign :: PrivateKey -> ByteArray -> ByteArray -foreign import buildSignature :: COSESign1Builder -> ByteArray -> ByteArray - -foreign import data Headers :: Type -foreign import newHeaders :: HeaderMap -> ProtectedHeaderMap -> Headers - -foreign import data ProtectedHeaderMap :: Type -foreign import newProtectedHeaderMap :: HeaderMap -> ProtectedHeaderMap - -foreign import data HeaderMap :: Type -foreign import newHeaderMap :: Effect HeaderMap -foreign import setAlgHeaderToEdDsa :: HeaderMap -> Effect Unit -foreign import setAddressHeader :: CborBytes -> HeaderMap -> Effect Unit - -foreign import data COSEKey :: Type -foreign import newCoseKeyWithOkpType :: Effect COSEKey -foreign import setCoseKeyAlgHeaderToEdDsa :: COSEKey -> Effect Unit -foreign import setCoseKeyCrvHeaderToEd25519 :: COSEKey -> Effect Unit -foreign import setCoseKeyXHeader :: RawBytes -> COSEKey -> Effect Unit -foreign import bytesFromCoseKey :: COSEKey -> CborBytes - -signData :: PrivateKey -> Address -> RawBytes -> Effect DataSignature -signData privatePaymentKey address (RawBytes payload) = - { key: _, signature: _ } <$> key <*> signature - where - key :: Effect CborBytes - key = do - coseKey <- newCoseKeyWithOkpType - setCoseKeyAlgHeaderToEdDsa coseKey - setCoseKeyCrvHeaderToEd25519 coseKey - setCoseKeyXHeader publicPaymentKeyBytes coseKey - pure $ bytesFromCoseKey coseKey - where - publicPaymentKeyBytes :: RawBytes - publicPaymentKeyBytes = - bytesFromPublicKey (publicKeyFromPrivateKey privatePaymentKey) - - signature :: Effect CborBytes - signature = CborBytes <$> (buildSignature <$> builder <*> signedSigStruct) - where - signedSigStruct :: Effect ByteArray - signedSigStruct = sign privatePaymentKey <<< makeDataToSign <$> builder - - builder :: Effect COSESign1Builder - builder = headers >>= newCoseSign1Builder payload - where - headers :: Effect Headers - headers = newHeaders <$> newHeaderMap <*> protectedHeaders - - protectedHeaders :: Effect ProtectedHeaderMap - protectedHeaders = do - headerMap <- newHeaderMap - setAlgHeaderToEdDsa headerMap - setAddressHeader (toBytes address) headerMap - pure $ newProtectedHeaderMap headerMap diff --git a/src/Internal/Wallet/Cip30Mock.js b/src/Internal/Wallet/Cip30Mock.js deleted file mode 100644 index 610baa03b4..0000000000 --- a/src/Internal/Wallet/Cip30Mock.js +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable no-global-assign */ - -export function injectCip30Mock(walletName) { - return mock => () => { - let window_ = typeof window != "undefined" ? window : (global.window = {}); - - if ( - typeof window_ == "object" && - typeof window_.cardano == "object" && - typeof window_.cardano[walletName] != "undefined" - ) { - throw ( - "injectCip30Mock: refusing to overwrite existing wallet (" + - walletName + - ")" - ); - } - - window_.cardano = {}; - window_.cardano[walletName] = { - enable: () => { - return new Promise((resolve, _reject) => - resolve({ - getNetworkId: mock.getNetworkId, - getUtxos: mock.getUtxos, - experimental: { - getCollateral: mock.getCollateral - }, - getBalance: mock.getBalance, - getUsedAddresses: mock.getUsedAddresses, - getUnusedAddresses: mock.getUnusedAddresses, - getChangeAddress: mock.getChangeAddress, - getRewardAddresses: mock.getRewardAddresses, - signTx: mock.signTx, - signData: mock.signData - }) - ); - } - }; - - return () => { - delete window_.cardano[walletName]; - }; - }; -} diff --git a/src/Internal/Wallet/Cip30Mock.purs b/src/Internal/Wallet/Cip30Mock.purs index 10b0324de3..c7e3b729f6 100644 --- a/src/Internal/Wallet/Cip30Mock.purs +++ b/src/Internal/Wallet/Cip30Mock.purs @@ -1,95 +1,57 @@ module Ctl.Internal.Wallet.Cip30Mock ( withCip30Mock - , WalletMock - ( MockFlint - , MockGero - , MockNami - , MockLode - , MockNuFi - , MockGenericCip30 - ) ) where import Prelude -import Contract.Monad (Contract) -import Control.Monad.Error.Class (liftMaybe, try) -import Control.Monad.Reader (ask) -import Control.Monad.Reader.Class (local) -import Control.Promise (Promise, fromAff) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - ) -import Ctl.Internal.Contract.Monad (getQueryHandle) -import Ctl.Internal.Deserialization.Transaction (deserializeTransaction) -import Ctl.Internal.Helpers (liftEither) -import Ctl.Internal.Serialization - ( convertTransactionUnspentOutput - , convertValue - , publicKeyHash - , toBytes +import Cardano.AsCbor (decodeCbor, encodeCbor) +import Cardano.Types + ( Credential(PubKeyHashCredential) + , StakeCredential(StakeCredential) ) -import Ctl.Internal.Serialization.Address - ( Address - , NetworkId(MainnetId, TestnetId) - ) -import Ctl.Internal.Serialization.Keys (publicKeyFromPrivateKey) -import Ctl.Internal.Serialization.WitnessSet (convertWitnessSet) -import Ctl.Internal.Types.ByteArray (byteArrayToHex, hexToByteArray) -import Ctl.Internal.Types.CborBytes (cborBytesFromByteArray, cborBytesToHex) -import Ctl.Internal.Types.PubKeyHash - ( PubKeyHash(PubKeyHash) - , StakePubKeyHash(StakePubKeyHash) - ) -import Ctl.Internal.Types.RewardAddress - ( rewardAddressToBytes - , stakePubKeyHashRewardAddress - ) -import Ctl.Internal.Wallet - ( Wallet - , WalletExtension - ( LodeWallet - , NamiWallet - , GeroWallet - , FlintWallet - , NuFiWallet - , GenericCip30Wallet - ) - , mkWalletAff - ) -import Ctl.Internal.Wallet.Key +import Cardano.Types.Address (Address(RewardAddress)) +import Cardano.Types.Address (fromBech32) as Address +import Cardano.Types.NetworkId (NetworkId(MainnetId, TestnetId)) +import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Types.PublicKey as PublicKey +import Cardano.Types.TransactionUnspentOutput as TransactionUnspentOutput +import Cardano.Wallet.Cip30Mock (Cip30Mock, injectCip30Mock) +import Cardano.Wallet.Key ( KeyWallet(KeyWallet) + , PrivateDrepKey , PrivatePaymentKey , PrivateStakeKey , privateKeysToKeyWallet ) +import Cardano.Wallet.Key (getPrivateDrepKey, getPrivateStakeKey) as KeyWallet +import Contract.Monad (Contract) +import Control.Alt ((<|>)) +import Control.Monad.Error.Class (liftMaybe, try) +import Control.Monad.Reader (ask) +import Control.Monad.Reader.Class (local) +import Control.Promise (fromAff) +import Ctl.Internal.BalanceTx.Collateral.Select (minRequiredCollateral) +import Ctl.Internal.Contract.Monad (getQueryHandle) +import Ctl.Internal.Helpers (liftEither) +import Ctl.Internal.Wallet (mkWalletAff) import Data.Array as Array +import Data.ByteArray (byteArrayToHex, hexToByteArray) import Data.Either (hush) import Data.Foldable (fold, foldMap) -import Data.Function.Uncurried (Fn2, mkFn2) +import Data.Function.Uncurried (mkFn2) import Data.Map as Map -import Data.Maybe (Maybe(Just), maybe) +import Data.Maybe (Maybe(Just, Nothing), maybe) import Data.Newtype (unwrap, wrap) -import Data.Traversable (traverse) -import Data.Tuple.Nested ((/\)) import Data.UInt as UInt -import Effect (Effect) import Effect.Aff (Aff) import Effect.Aff.Class (liftAff) import Effect.Class (liftEffect) import Effect.Exception (error) import Effect.Unsafe (unsafePerformEffect) +import Partial.Unsafe (unsafePartial) -data WalletMock - = MockFlint - | MockGero - | MockNami - | MockLode - | MockNuFi - | MockGenericCip30 String - --- | Construct a CIP-30 wallet mock that exposes `KeyWallet` functionality --- | behind a CIP-30 interface and uses Ogmios to submit Txs. +-- | Construct a CIP-30 + CIP-95 wallet mock that exposes `KeyWallet` +-- | functionality behind a CIP-30 interface and uses Ogmios to submit Txs. -- | The wallet is injected directly to `window.cardano` object, under the -- | name corresponding to provided `WalletMock`. It works even in NodeJS -- | (we introduce a global `window` object and delete it afterwards). @@ -101,96 +63,73 @@ data WalletMock -- | Note that this function implements single-address light wallet logic, so -- | it will have to be changed a lot to successfully mimic the behavior of -- | multi-address wallets, like Eternl. +-- | +-- | WARNING: KeyWallet does not distinguish between registered and +-- | unregistered stake keys due to the limitations of the underlying +-- | query layer. This means that all controlled stake keys are +-- | returned as part of getUnregisteredPubStakeKeys, and the response +-- | of getRegisteredPubStakeKeys is always an empty array. withCip30Mock :: forall (a :: Type) . KeyWallet - -> WalletMock + -> String -> Contract a -> Contract a withCip30Mock (KeyWallet keyWallet) mock contract = do - cip30Mock <- mkCip30Mock keyWallet.paymentKey - keyWallet.stakeKey - deleteMock <- liftEffect $ injectCip30Mock mockString cip30Mock - wallet <- liftAff mkWalletAff' + kwPaymentKey <- liftAff keyWallet.paymentKey + kwMStakeKey <- liftAff keyWallet.stakeKey + kwMDrepKey <- liftAff keyWallet.drepKey + cip30Mock <- mkCip30Mock kwPaymentKey kwMStakeKey kwMDrepKey + deleteMock <- liftEffect $ injectCip30Mock mock cip30Mock + wallet <- liftAff $ mkWalletAff { name: mock, exts: { cip95: true } } res <- try $ local _ { wallet = Just wallet } contract liftEffect deleteMock liftEither res - where - mkWalletAff' :: Aff Wallet - mkWalletAff' = case mock of - MockFlint -> mkWalletAff FlintWallet - MockGero -> mkWalletAff GeroWallet - MockNami -> mkWalletAff NamiWallet - MockLode -> mkWalletAff LodeWallet - MockNuFi -> mkWalletAff NuFiWallet - MockGenericCip30 name -> mkWalletAff (GenericCip30Wallet name) - - mockString :: String - mockString = case mock of - MockFlint -> "flint" - MockGero -> "gerowallet" - MockNami -> "nami" - MockLode -> "LodeWallet" - MockNuFi -> "nufi" - MockGenericCip30 name -> name - -type Cip30Mock = - { getNetworkId :: Effect (Promise Int) - -- we ignore both the amount parameter and pagination: - , getUtxos :: Effect (Promise (Array String)) - -- we ignore the amount parameter: - , getCollateral :: Effect (Promise (Array String)) - , getBalance :: Effect (Promise String) - -- we ignore pagination parameter: - , getUsedAddresses :: Effect (Promise (Array String)) - , getUnusedAddresses :: Effect (Promise (Array String)) - , getChangeAddress :: Effect (Promise String) - , getRewardAddresses :: Effect (Promise (Array String)) - -- we ignore the 'isPartial' parameter - , signTx :: String -> Promise String - , signData :: - Fn2 String String (Promise { key :: String, signature :: String }) - } mkCip30Mock - :: PrivatePaymentKey -> Maybe PrivateStakeKey -> Contract Cip30Mock -mkCip30Mock pKey mSKey = do + :: PrivatePaymentKey + -> Maybe PrivateStakeKey + -> Maybe PrivateDrepKey + -> Contract Cip30Mock +mkCip30Mock pKey mSKey mbDrepKey = do env <- ask queryHandle <- getQueryHandle let getCollateralUtxos utxos = do let pparams = unwrap env.ledgerConstants.pparams - coinsPerUtxoUnit = pparams.coinsPerUtxoUnit + coinsPerUtxoByte = pparams.coinsPerUtxoByte maxCollateralInputs = UInt.toInt $ pparams.maxCollateralInputs - liftEffect $ - (unwrap keyWallet).selectCollateral coinsPerUtxoUnit + coll <- liftAff $ + (unwrap keyWallet).selectCollateral + minRequiredCollateral + coinsPerUtxoByte maxCollateralInputs utxos - <#> fold - + pure $ fold coll ownUtxos = do - let ownAddress = (unwrap keyWallet).address env.networkId + ownAddress <- liftAff $ (unwrap keyWallet).address env.networkId liftMaybe (error "No UTxOs at address") <<< hush =<< do queryHandle.utxosAt ownAddress - keyWallet = privateKeysToKeyWallet pKey mSKey - - addressHex = - byteArrayToHex $ unwrap $ toBytes - ((unwrap keyWallet).address env.networkId :: Address) + keyWallet = privateKeysToKeyWallet pKey mSKey mbDrepKey + addressHex <- liftAff $ + (byteArrayToHex <<< unwrap <<< encodeCbor) <$> + ((unwrap keyWallet).address env.networkId :: Aff Address) + let mbRewardAddressHex = mSKey <#> \stakeKey -> let - stakePubKey = publicKeyFromPrivateKey (unwrap stakeKey) - stakePubKeyHash = publicKeyHash stakePubKey - rewardAddress = stakePubKeyHashRewardAddress env.networkId - $ StakePubKeyHash - $ PubKeyHash stakePubKeyHash + stakePubKey = PrivateKey.toPublicKey (unwrap stakeKey) + stakePubKeyHash = PublicKey.hash stakePubKey + rewardAddress = RewardAddress + { networkId: env.networkId + , stakeCredential: + StakeCredential $ PubKeyHashCredential stakePubKeyHash + } in - byteArrayToHex $ unwrap $ rewardAddressToBytes rewardAddress - + byteArrayToHex $ unwrap $ encodeCbor rewardAddress pure $ { getNetworkId: fromAff $ pure $ case env.networkId of @@ -202,27 +141,18 @@ mkCip30Mock pKey mSKey = do let collateralOutputs = collateralUtxos <#> unwrap >>> _.input -- filter out UTxOs that will be used as collateral - nonCollateralUtxos = + utxoMap = Map.filterKeys (not <<< flip Array.elem collateralOutputs) utxos - -- Convert to CSL representation and serialize - cslUtxos <- traverse (liftEffect <<< convertTransactionUnspentOutput) - $ Map.toUnfoldable nonCollateralUtxos <#> \(input /\ output) -> - TransactionUnspentOutput { input, output } - pure $ (byteArrayToHex <<< unwrap <<< toBytes) <$> cslUtxos + pure $ byteArrayToHex <<< unwrap <<< encodeCbor <$> + TransactionUnspentOutput.fromUtxoMap utxoMap , getCollateral: fromAff do utxos <- ownUtxos collateralUtxos <- getCollateralUtxos utxos - cslUnspentOutput <- liftEffect $ traverse - convertTransactionUnspentOutput - collateralUtxos - pure $ (byteArrayToHex <<< unwrap <<< toBytes) <$> - cslUnspentOutput - , getBalance: fromAff do + pure $ byteArrayToHex <<< unwrap <<< encodeCbor <$> collateralUtxos + , getBalance: unsafePartial $ fromAff do utxos <- ownUtxos - value <- liftEffect $ convertValue $ - (foldMap (_.amount <<< unwrap) <<< Map.values) - utxos - pure $ byteArrayToHex $ unwrap $ toBytes value + let value = foldMap (_.amount <<< unwrap) $ Map.values utxos + pure $ byteArrayToHex $ unwrap $ encodeCbor value , getUsedAddresses: fromAff do pure [ addressHex ] , getUnusedAddresses: fromAff $ pure [] @@ -234,19 +164,43 @@ mkCip30Mock pKey mSKey = do txBytes <- liftMaybe (error "Unable to convert CBOR") $ hexToByteArray str tx <- liftMaybe (error "Failed to decode Transaction CBOR") - $ hush - $ deserializeTransaction - $ cborBytesFromByteArray txBytes + $ decodeCbor + $ wrap txBytes witness <- (unwrap keyWallet).signTx tx - cslWitnessSet <- liftEffect $ convertWitnessSet witness - pure $ byteArrayToHex $ unwrap $ toBytes cslWitnessSet - , signData: mkFn2 \_addr msg -> unsafePerformEffect $ fromAff do - msgBytes <- liftMaybe (error "Unable to convert CBOR") $ - hexToByteArray msg - { key, signature } <- (unwrap keyWallet).signData env.networkId - (wrap msgBytes) - pure { key: cborBytesToHex key, signature: cborBytesToHex signature } + pure $ byteArrayToHex $ unwrap $ encodeCbor witness + , signData: mkFn2 \addrRaw msg -> unsafePerformEffect $ fromAff do + let addrFromHex = (decodeCbor <<< wrap) <=< hexToByteArray + addr <- + liftMaybe + (error "Failed to decode Address") + (addrFromHex addrRaw <|> Address.fromBech32 addrRaw) + msgBytes <- + liftMaybe + (error "Failed to decode payload") + (hexToByteArray msg) + mDataSig <- (unwrap keyWallet).signData addr (wrap msgBytes) + { key, signature } <- + liftMaybe + (error "Unable to sign data for the supplied address") + mDataSig + pure + { key: byteArrayToHex $ unwrap key + , signature: byteArrayToHex $ unwrap signature + } + , getPubDrepKey: fromAff do + drepKey <- liftMaybe (error "Unable to get DRep key") =<< + KeyWallet.getPrivateDrepKey keyWallet + let drepPubKey = PrivateKey.toPublicKey $ unwrap drepKey + pure $ byteArrayToHex $ unwrap $ PublicKey.toRawBytes drepPubKey + , getRegisteredPubStakeKeys: fromAff $ pure mempty + , getUnregisteredPubStakeKeys: fromAff do + KeyWallet.getPrivateStakeKey keyWallet <#> case _ of + Just stakeKey -> + let + stakePubKey = PrivateKey.toPublicKey $ unwrap stakeKey + in + Array.singleton $ byteArrayToHex $ unwrap $ PublicKey.toRawBytes + stakePubKey + Nothing -> + mempty } - --- returns an action that removes the mock. -foreign import injectCip30Mock :: String -> Cip30Mock -> Effect (Effect Unit) diff --git a/src/Internal/Wallet/Key.purs b/src/Internal/Wallet/Key.purs deleted file mode 100644 index 7b0a56ebff..0000000000 --- a/src/Internal/Wallet/Key.purs +++ /dev/null @@ -1,187 +0,0 @@ -module Ctl.Internal.Wallet.Key - ( KeyWallet(KeyWallet) - , PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey(PrivateStakeKey) - , privateKeysToAddress - , privateKeysToKeyWallet - , keyWalletPrivatePaymentKey - , keyWalletPrivateStakeKey - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , decodeAeson - , encodeAeson - ) -import Contract.Prelude (class Newtype) -import Ctl.Internal.BalanceTx.Collateral.Select (selectCollateral) as Collateral -import Ctl.Internal.Cardano.Types.Transaction - ( Transaction(Transaction) - , TransactionWitnessSet - , UtxoMap - , _vkeys - ) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput - ) -import Ctl.Internal.Deserialization.Keys - ( privateKeyFromBech32 - , privateKeyToBech32 - ) -import Ctl.Internal.Deserialization.WitnessSet as Deserialization.WitnessSet -import Ctl.Internal.Serialization - ( publicKeyHash - ) -import Ctl.Internal.Serialization as Serialization -import Ctl.Internal.Serialization.Address - ( Address - , NetworkId - , baseAddress - , baseAddressToAddress - , enterpriseAddress - , enterpriseAddressToAddress - , keyHashCredential - ) -import Ctl.Internal.Serialization.Keys (publicKeyFromPrivateKey) -import Ctl.Internal.Serialization.Types (PrivateKey) -import Ctl.Internal.Types.ProtocolParameters (CoinsPerUtxoUnit) -import Ctl.Internal.Types.RawBytes (RawBytes) -import Ctl.Internal.Wallet.Cip30 (DataSignature) -import Ctl.Internal.Wallet.Cip30.SignData (signData) as Cip30SignData -import Data.Array (fromFoldable) -import Data.Either (note) -import Data.Foldable (fold) -import Data.Lens (set) -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (unwrap) -import Data.Traversable (for) -import Effect (Effect) -import Effect.Aff (Aff) -import Effect.Class (liftEffect) - -------------------------------------------------------------------------------- --- Key backend -------------------------------------------------------------------------------- -newtype KeyWallet = KeyWallet - { address :: NetworkId -> Address - , selectCollateral :: - CoinsPerUtxoUnit - -> Int - -> UtxoMap - -> Effect (Maybe (Array TransactionUnspentOutput)) - , signTx :: Transaction -> Aff TransactionWitnessSet - , signData :: NetworkId -> RawBytes -> Aff DataSignature - , paymentKey :: PrivatePaymentKey - , stakeKey :: Maybe PrivateStakeKey - } - -derive instance Newtype KeyWallet _ - -newtype PrivatePaymentKey = PrivatePaymentKey PrivateKey - -derive instance Newtype PrivatePaymentKey _ - -instance Show PrivatePaymentKey where - show _ = "(PrivatePaymentKey )" - -instance EncodeAeson PrivatePaymentKey where - encodeAeson (PrivatePaymentKey pk) = encodeAeson (privateKeyToBech32 pk) - -instance DecodeAeson PrivatePaymentKey where - decodeAeson aeson = - decodeAeson aeson >>= - note (TypeMismatch "PrivateKey") - <<< map PrivatePaymentKey - <<< privateKeyFromBech32 - -newtype PrivateStakeKey = PrivateStakeKey PrivateKey - -derive instance Newtype PrivateStakeKey _ - -instance Show PrivateStakeKey where - show _ = "(PrivateStakeKey )" - -instance EncodeAeson PrivateStakeKey where - encodeAeson (PrivateStakeKey pk) = encodeAeson (privateKeyToBech32 pk) - -instance DecodeAeson PrivateStakeKey where - decodeAeson aeson = - decodeAeson aeson >>= - note (TypeMismatch "PrivateKey") - <<< map PrivateStakeKey - <<< privateKeyFromBech32 - -keyWalletPrivatePaymentKey :: KeyWallet -> PrivatePaymentKey -keyWalletPrivatePaymentKey = unwrap >>> _.paymentKey - -keyWalletPrivateStakeKey :: KeyWallet -> Maybe PrivateStakeKey -keyWalletPrivateStakeKey = unwrap >>> _.stakeKey - -privateKeysToAddress - :: PrivatePaymentKey -> Maybe PrivateStakeKey -> NetworkId -> Address -privateKeysToAddress payKey mbStakeKey network = do - let pubPayKey = publicKeyFromPrivateKey (unwrap payKey) - case mbStakeKey of - Just stakeKey -> - let - pubStakeKey = publicKeyFromPrivateKey (unwrap stakeKey) - in - baseAddressToAddress $ - baseAddress - { network - , paymentCred: keyHashCredential $ publicKeyHash $ pubPayKey - , delegationCred: keyHashCredential $ publicKeyHash $ pubStakeKey - } - - Nothing -> pubPayKey # publicKeyHash - >>> keyHashCredential - >>> { network, paymentCred: _ } - >>> enterpriseAddress - >>> enterpriseAddressToAddress - -privateKeysToKeyWallet - :: PrivatePaymentKey -> Maybe PrivateStakeKey -> KeyWallet -privateKeysToKeyWallet payKey mbStakeKey = - KeyWallet - { address - , selectCollateral - , signTx - , signData - , paymentKey: payKey - , stakeKey: mbStakeKey - } - where - address :: NetworkId -> Address - address = privateKeysToAddress payKey mbStakeKey - - selectCollateral - :: CoinsPerUtxoUnit - -> Int - -> UtxoMap - -> Effect (Maybe (Array TransactionUnspentOutput)) - selectCollateral coinsPerUtxoByte maxCollateralInputs utxos = map fromFoldable - <$> Collateral.selectCollateral coinsPerUtxoByte maxCollateralInputs utxos - - signTx :: Transaction -> Aff TransactionWitnessSet - signTx (Transaction tx) = liftEffect do - txBody <- Serialization.convertTxBody tx.body - hash <- Serialization.hashTransaction txBody - payWitness <- Deserialization.WitnessSet.convertVkeyWitness <$> - Serialization.makeVkeywitness hash (unwrap payKey) - mbStakeWitness <- for mbStakeKey \stakeKey -> do - Deserialization.WitnessSet.convertVkeyWitness <$> - Serialization.makeVkeywitness hash (unwrap stakeKey) - let - witnessSet' = set _vkeys - (pure $ [ payWitness ] <> fold (pure <$> mbStakeWitness)) - mempty - pure witnessSet' - - signData :: NetworkId -> RawBytes -> Aff DataSignature - signData networkId payload = do - liftEffect $ Cip30SignData.signData (unwrap payKey) (address networkId) - payload diff --git a/src/Internal/Wallet/KeyFile.purs b/src/Internal/Wallet/KeyFile.purs index b51afcec88..80b0a7d946 100644 --- a/src/Internal/Wallet/KeyFile.purs +++ b/src/Internal/Wallet/KeyFile.purs @@ -14,6 +14,12 @@ module Ctl.Internal.Wallet.KeyFile import Prelude import Aeson (encodeAeson) +import Cardano.Types.PrivateKey (PrivateKey) +import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Wallet.Key + ( PrivatePaymentKey(PrivatePaymentKey) + , PrivateStakeKey(PrivateStakeKey) + ) import Control.Monad.Error.Class (liftMaybe) import Control.Monad.Except (catchError) import Ctl.Internal.Cardano.TextEnvelope @@ -24,18 +30,10 @@ import Ctl.Internal.Cardano.TextEnvelope ) , decodeTextEnvelope ) -import Ctl.Internal.Deserialization.Keys (privateKeyFromBytes) import Ctl.Internal.Helpers (liftM) -import Ctl.Internal.Serialization.Keys (bytesFromPrivateKey) -import Ctl.Internal.Serialization.Types (PrivateKey) -import Ctl.Internal.Types.ByteArray (ByteArray) -import Ctl.Internal.Types.RawBytes (rawBytesToHex) -import Ctl.Internal.Wallet.Key - ( PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey(PrivateStakeKey) - ) +import Data.ByteArray (ByteArray, byteArrayToHex) import Data.Maybe (Maybe(Nothing)) -import Data.Newtype (wrap) +import Data.Newtype (unwrap, wrap) import Effect.Aff (Aff) import Effect.Class (liftEffect) import Effect.Exception (error, throw) @@ -66,25 +64,25 @@ privatePaymentKeyFromTextEnvelope :: TextEnvelope -> Maybe PrivatePaymentKey privatePaymentKeyFromTextEnvelope (TextEnvelope envelope) = do -- Check TextEnvelope type match to desirable unless (envelope.type_ == PaymentSigningKeyShelleyed25519) Nothing - PrivatePaymentKey <$> privateKeyFromBytes (wrap envelope.bytes) + PrivatePaymentKey <$> PrivateKey.fromRawBytes (wrap envelope.bytes) privateStakeKeyFromTextEnvelope :: TextEnvelope -> Maybe PrivateStakeKey privateStakeKeyFromTextEnvelope (TextEnvelope envelope) = do -- Check TextEnvelope type match to desirable unless (envelope.type_ == StakeSigningKeyShelleyed25519) Nothing - PrivateStakeKey <$> privateKeyFromBytes (wrap envelope.bytes) + PrivateStakeKey <$> PrivateKey.fromRawBytes (wrap envelope.bytes) privatePaymentKeyFromFile :: FilePath -> Aff PrivatePaymentKey privatePaymentKeyFromFile filePath = do bytes <- keyFromFile filePath PaymentSigningKeyShelleyed25519 liftM (error "Unable to decode private payment key") $ - PrivatePaymentKey <$> privateKeyFromBytes (wrap bytes) + PrivatePaymentKey <$> PrivateKey.fromRawBytes (wrap bytes) privateStakeKeyFromFile :: FilePath -> Aff PrivateStakeKey privateStakeKeyFromFile filePath = do bytes <- keyFromFile filePath StakeSigningKeyShelleyed25519 liftM (error "Unable to decode private stake key") $ - PrivateStakeKey <$> privateKeyFromBytes (wrap bytes) + PrivateStakeKey <$> PrivateKey.fromRawBytes (wrap bytes) -- | Write private payment key to file in cardano-cli envelope format privatePaymentKeyToFile :: FilePath -> PrivatePaymentKey -> Aff Unit @@ -115,7 +113,8 @@ formatStakeKey (PrivateStakeKey key) = encodeAeson >>> show } keyToCbor :: PrivateKey -> String -keyToCbor = (magicPrefix <> _) <<< rawBytesToHex <<< bytesFromPrivateKey +keyToCbor = + (magicPrefix <> _) <<< byteArrayToHex <<< unwrap <<< PrivateKey.toRawBytes magicPrefix :: String magicPrefix = "5820" diff --git a/src/Internal/Wallet/Spec.purs b/src/Internal/Wallet/Spec.purs index 8cb539eac3..ae440e2846 100644 --- a/src/Internal/Wallet/Spec.purs +++ b/src/Internal/Wallet/Spec.purs @@ -1,55 +1,40 @@ module Ctl.Internal.Wallet.Spec - ( WalletSpec - ( UseKeys - , UseMnemonic - , ConnectToNami - , ConnectToGero - , ConnectToFlint - , ConnectToEternl - , ConnectToLode - , ConnectToNuFi - , ConnectToLace - , ConnectToGenericCip30 - ) - , Cip1852DerivationPath - , StakeKeyPresence(WithStakeKey, WithoutStakeKey) + ( Cip1852DerivationPath + , KnownWallet(Nami, Gero, Flint, Eternl, Lode, Lace, NuFi) , MnemonicSource(MnemonicString, MnemonicFile) + , PrivateDrepKeySource(PrivateDrepKeyValue) , PrivateStakeKeySource(PrivateStakeKeyFile, PrivateStakeKeyValue) , PrivatePaymentKeySource(PrivatePaymentKeyFile, PrivatePaymentKeyValue) + , StakeKeyPresence(WithStakeKey, WithoutStakeKey) + , WalletSpec(UseKeys, UseMnemonic, ConnectToGenericCip30) , mkWalletBySpec , mkKeyWalletFromMnemonic + , walletName ) where import Prelude -import Control.Monad.Error.Class (liftEither) -import Ctl.Internal.Wallet - ( Wallet(KeyWallet) - , WalletExtension - ( NamiWallet - , GeroWallet - , FlintWallet - , EternlWallet - , LodeWallet - , NuFiWallet - , LaceWallet - , GenericCip30Wallet - ) - , mkKeyWallet - , mkWalletAff - ) -import Ctl.Internal.Wallet.Bip32 +import Cardano.Wallet.HD ( bip32ToPrivateKey , cip1852AccountFromMnemonic + , deriveDrepKey , derivePaymentKey , deriveStakeKey ) -import Ctl.Internal.Wallet.Key +import Cardano.Wallet.Key ( KeyWallet + , PrivateDrepKey(PrivateDrepKey) , PrivatePaymentKey(PrivatePaymentKey) , PrivateStakeKey(PrivateStakeKey) , privateKeysToKeyWallet ) +import Control.Monad.Error.Class (liftEither) +import Ctl.Internal.Wallet + ( Cip30Extensions + , Wallet(KeyWallet) + , mkKeyWallet + , mkWalletAff + ) import Ctl.Internal.Wallet.KeyFile ( privatePaymentKeyFromFile , privateStakeKeyFromFile @@ -85,6 +70,13 @@ derive instance Generic PrivateStakeKeySource _ instance Show PrivateStakeKeySource where show = genericShow +data PrivateDrepKeySource = PrivateDrepKeyValue PrivateDrepKey + +derive instance Generic PrivateDrepKeySource _ + +instance Show PrivateDrepKeySource where + show = genericShow + data MnemonicSource = MnemonicString String | MnemonicFile FilePath @@ -104,21 +96,27 @@ instance Show StakeKeyPresence where -- | A data type to describe instructions on how to initialize a wallet. data WalletSpec = UseKeys PrivatePaymentKeySource (Maybe PrivateStakeKeySource) + (Maybe PrivateDrepKeySource) | UseMnemonic MnemonicSource Cip1852DerivationPath StakeKeyPresence - | ConnectToNami - | ConnectToGero - | ConnectToFlint - | ConnectToEternl - | ConnectToLode - | ConnectToNuFi - | ConnectToLace - | ConnectToGenericCip30 String + | ConnectToGenericCip30 String Cip30Extensions derive instance Generic WalletSpec _ instance Show WalletSpec where show = genericShow +data KnownWallet = Nami | Gero | Flint | Eternl | Lode | Lace | NuFi + +walletName :: KnownWallet -> String +walletName = case _ of + Nami -> "nami" + Gero -> "gerowallet" + Flint -> "flint" + Eternl -> "eternl" + Lode -> "LodeWallet" + Lace -> "lace" + NuFi -> "nufi" + -- | Contains non-constant parameters for a CIP-1852 derivation path. -- | See https://cips.cardano.org/cips/cip1852/ and `doc/key-management.md`. type Cip1852DerivationPath = @@ -128,7 +126,7 @@ type Cip1852DerivationPath = mkWalletBySpec :: WalletSpec -> Aff Wallet mkWalletBySpec = case _ of - UseKeys paymentKeySpec mbStakeKeySpec -> do + UseKeys paymentKeySpec mbStakeKeySpec mbDrepKeySpec -> do privatePaymentKey <- case paymentKeySpec of PrivatePaymentKeyFile filePath -> privatePaymentKeyFromFile filePath @@ -136,7 +134,9 @@ mkWalletBySpec = case _ of mbPrivateStakeKey <- for mbStakeKeySpec case _ of PrivateStakeKeyFile filePath -> privateStakeKeyFromFile filePath PrivateStakeKeyValue key -> pure key - pure $ mkKeyWallet privatePaymentKey mbPrivateStakeKey + mbDrepKey <- for mbDrepKeySpec case _ of + PrivateDrepKeyValue key -> pure key + pure $ mkKeyWallet privatePaymentKey mbPrivateStakeKey mbDrepKey UseMnemonic (MnemonicString mnemonic) derivationPath stakeKeyPresence -> do map KeyWallet $ liftEither $ lmap error $ mkKeyWalletFromMnemonic mnemonic derivationPath stakeKeyPresence @@ -144,14 +144,7 @@ mkWalletBySpec = case _ of mnemonic <- readTextFile Encoding.UTF8 path map KeyWallet $ liftEither $ lmap error $ mkKeyWalletFromMnemonic mnemonic derivationPath stakeKeyPresence - ConnectToNami -> mkWalletAff NamiWallet - ConnectToGero -> mkWalletAff GeroWallet - ConnectToFlint -> mkWalletAff FlintWallet - ConnectToEternl -> mkWalletAff EternlWallet - ConnectToLode -> mkWalletAff LodeWallet - ConnectToNuFi -> mkWalletAff NuFiWallet - ConnectToLace -> mkWalletAff LaceWallet - ConnectToGenericCip30 name -> mkWalletAff (GenericCip30Wallet name) + ConnectToGenericCip30 name exts -> mkWalletAff { name, exts } -- | Create a wallet given a mnemonic phrase, account index, address index and -- | stake key presence flag. @@ -165,9 +158,14 @@ mkKeyWalletFromMnemonic phrase { accountIndex, addressIndex } stakeKeyPresence = do account <- cip1852AccountFromMnemonic phrase accountIndex let - paymentKey = derivePaymentKey account addressIndex # bip32ToPrivateKey - mbStakeKeySpec = case stakeKeyPresence of - WithStakeKey -> Just $ PrivateStakeKey $ deriveStakeKey account # - bip32ToPrivateKey + paymentKey = + PrivatePaymentKey $ bip32ToPrivateKey $ derivePaymentKey account + addressIndex + drepKey = Just $ PrivateDrepKey $ bip32ToPrivateKey $ deriveDrepKey + account + mbStakeKey = case stakeKeyPresence of + WithStakeKey -> Just $ PrivateStakeKey $ + deriveStakeKey account # + bip32ToPrivateKey WithoutStakeKey -> Nothing - pure $ privateKeysToKeyWallet (PrivatePaymentKey paymentKey) mbStakeKeySpec + pure $ privateKeysToKeyWallet paymentKey mbStakeKey drepKey diff --git a/templates/ctl-scaffold/Makefile b/templates/ctl-scaffold/Makefile index 3867c13199..0e6deadf47 100644 --- a/templates/ctl-scaffold/Makefile +++ b/templates/ctl-scaffold/Makefile @@ -13,7 +13,8 @@ js-sources := $(shell fd --no-ignore-parent -ejs -ecjs) ps-entrypoint := Scaffold.Test.E2E.Serve # The entry point function in the main PureScript module ps-entrypoint-function := main -# Whether to bundle for the browser +# Whether to bundle for the browser ("1") or the node ("") +# NOTE: bundling for the node is not necessary, see https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/doc/using-from-js.md browser-runtime := 1 # Use "1" for true and "" for false preview-node-ipc = $(shell docker volume inspect store_node-preview-ipc | jq -r '.[0].Mountpoint') @@ -57,9 +58,6 @@ webpack-serve: spago-build create-bundle-entrypoint create-html-entrypoint --port ${serve-port} \ -o dist/ --env entry=./dist/entrypoint.js -run-build: - @${ps-bundle} && BROWSER_RUNTIME=1 webpack --mode=production - check-format: @purs-tidy check ${ps-sources} @prettier --loglevel warn -c ${js-sources} diff --git a/templates/ctl-scaffold/esbuild/config.js b/templates/ctl-scaffold/esbuild/config.js index 996ca4335f..bf23f5fb4c 100755 --- a/templates/ctl-scaffold/esbuild/config.js +++ b/templates/ctl-scaffold/esbuild/config.js @@ -7,9 +7,6 @@ export const buildOptions = ({ entryPoint, outfile }) => { const config = { entryPoints: [entryPoint], outfile: outfile, - define: { - BROWSER_RUNTIME: isBrowser ? "true" : '""', - }, plugins: [ wasmLoader({ mode: "deferred", @@ -24,8 +21,10 @@ export const buildOptions = ({ entryPoint, outfile }) => { // https://esbuild.github.io/api/#packages if (!isBrowser) { + // Keep dependencies outside of the bundle for nodejs config.packages = "external"; } else { + // Provide browser polyfills for NodeJS modules config.plugins.push( polyfillNode({ polyfills: { diff --git a/templates/ctl-scaffold/exe/Main.purs b/templates/ctl-scaffold/exe/Main.purs index 40b33ba983..09189eb35e 100644 --- a/templates/ctl-scaffold/exe/Main.purs +++ b/templates/ctl-scaffold/exe/Main.purs @@ -11,5 +11,12 @@ import Scaffold as Scaffold main :: Effect Unit main = Contract.Monad.launchAff_ $ void - $ Contract.Monad.runContract Contract.Config.testnetNamiConfig + $ Contract.Monad.runContract contractParams $ Scaffold.contract + +contractParams :: Contract.Config.ContractParams +contractParams = + Contract.Config.testnetConfig + { walletSpec = + Just $ Contract.Config.ConnectToGenericCip30 "nami" { cip95: false } + } diff --git a/templates/ctl-scaffold/flake.lock b/templates/ctl-scaffold/flake.lock index 1c4daa222b..600f05c0bc 100644 --- a/templates/ctl-scaffold/flake.lock +++ b/templates/ctl-scaffold/flake.lock @@ -3,11 +3,11 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1702290471, - "narHash": "sha256-uivAP05RENSzQDbDjAU3Fbq+AiDDpcNaHAzvOZM1fik=", + "lastModified": 1721915212, + "narHash": "sha256-itkbLG6DUX/L5XuoSXFPgPBf+9lFOM3ufc1T4BU4MYM=", "owner": "input-output-hk", "repo": "cardano-haskell-packages", - "rev": "1ff7483a6d2670c8627de92779a2b92a989293cd", + "rev": "2126fa53c45842719ee38040f4d5bee8fb17a09d", "type": "github" }, "original": { @@ -18,6 +18,23 @@ } }, "CHaP_2": { + "flake": false, + "locked": { + "lastModified": 1702906471, + "narHash": "sha256-br+hVo3R6nfmiSEPXcLKhIX4Kg5gcK2PjzjmvQsuUp8=", + "owner": "IntersectMBO", + "repo": "cardano-haskell-packages", + "rev": "48a359ac3f1d437ebaa91126b20e15a65201f004", + "type": "github" + }, + "original": { + "owner": "IntersectMBO", + "ref": "repo", + "repo": "cardano-haskell-packages", + "type": "github" + } + }, + "CHaP_3": { "flake": false, "locked": { "lastModified": 1686070892, @@ -34,14 +51,14 @@ "type": "github" } }, - "CHaP_3": { + "CHaP_4": { "flake": false, "locked": { - "lastModified": 1695160702, - "narHash": "sha256-+Mfc6eGA1ZwQ/ZjKzMoMWkHzd+sgR1JbxY0i849HjEU=", + "lastModified": 1702593630, + "narHash": "sha256-IWu27+sfPtazjIZiWLUm8G4BKvjXmIL+/1XT/ETnfhg=", "owner": "input-output-hk", "repo": "cardano-haskell-packages", - "rev": "9932690af3713ef034c928850252eb1b88450ee6", + "rev": "9783a177efcea5beb8808aab7513098bdab185ba", "type": "github" }, "original": { @@ -51,18 +68,18 @@ "type": "github" } }, - "CHaP_4": { + "CHaP_5": { "flake": false, "locked": { - "lastModified": 1694601145, - "narHash": "sha256-p7ZxorrOvoow6N+JKvfrCiRYFtUSPiEMgt8MR+rcTT4=", - "owner": "input-output-hk", + "lastModified": 1721831314, + "narHash": "sha256-I1j5HPSbbh3l1D0C9oP/59YB4e+64K9NDRl7ueD1c/Y=", + "owner": "intersectmbo", "repo": "cardano-haskell-packages", - "rev": "e8298604717dbaa311c1e42e021b571670f4b039", + "rev": "8815ee7598bc39a02db8896b788f69accf892790", "type": "github" }, "original": { - "owner": "input-output-hk", + "owner": "intersectmbo", "ref": "repo", "repo": "cardano-haskell-packages", "type": "github" @@ -84,6 +101,22 @@ "type": "github" } }, + "HTTP_10": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, "HTTP_2": { "flake": false, "locked": { @@ -180,9 +213,41 @@ "type": "github" } }, + "HTTP_8": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, + "HTTP_9": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, "agenix": { "inputs": { - "nixpkgs": "nixpkgs_9" + "nixpkgs": "nixpkgs_38" }, "locked": { "lastModified": 1641576265, @@ -200,8 +265,8 @@ }, "agenix-cli": { "inputs": { - "flake-utils": "flake-utils_6", - "nixpkgs": "nixpkgs_10" + "flake-utils": "flake-utils_21", + "nixpkgs": "nixpkgs_39" }, "locked": { "lastModified": 1641404293, @@ -219,8 +284,8 @@ }, "agenix-cli_2": { "inputs": { - "flake-utils": "flake-utils_7", - "nixpkgs": "nixpkgs_12" + "flake-utils": "flake-utils_22", + "nixpkgs": "nixpkgs_41" }, "locked": { "lastModified": 1641404293, @@ -238,8 +303,8 @@ }, "agenix-cli_3": { "inputs": { - "flake-utils": "flake-utils_18", - "nixpkgs": "nixpkgs_41" + "flake-utils": "flake-utils_33", + "nixpkgs": "nixpkgs_70" }, "locked": { "lastModified": 1641404293, @@ -257,7 +322,7 @@ }, "agenix_2": { "inputs": { - "nixpkgs": "nixpkgs_11" + "nixpkgs": "nixpkgs_40" }, "locked": { "lastModified": 1641576265, @@ -353,7 +418,7 @@ }, "agenix_6": { "inputs": { - "nixpkgs": "nixpkgs_40" + "nixpkgs": "nixpkgs_69" }, "locked": { "lastModified": 1641576265, @@ -423,7 +488,7 @@ "alejandra": { "inputs": { "flakeCompat": "flakeCompat", - "nixpkgs": "nixpkgs_35" + "nixpkgs": "nixpkgs_64" }, "locked": { "lastModified": 1646360966, @@ -439,6 +504,52 @@ "type": "github" } }, + "ameba-src": { + "flake": false, + "locked": { + "lastModified": 1679041484, + "narHash": "sha256-pc9mtVR/PBhM5l1PnDkm+y+McxbrfAmQzxmLi761VF4=", + "owner": "crystal-ameba", + "repo": "ameba", + "rev": "7c74d196d6d9a496a81a0c7b79ef44f39faf41b8", + "type": "github" + }, + "original": { + "owner": "crystal-ameba", + "ref": "v1.4.3", + "repo": "ameba", + "type": "github" + } + }, + "auth-keys-hub": { + "inputs": { + "crystal": "crystal", + "flake-parts": "flake-parts_2", + "inclusive": "inclusive", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "nixpkgs" + ], + "statix": "statix", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1691483346, + "narHash": "sha256-wvn84eGcc+PMbq/qSCWcZ/kV7/bjwuGOVSn/9rGaaKw=", + "owner": "input-output-hk", + "repo": "auth-keys-hub", + "rev": "ab7c79f49886b8f24cfae4b967a59ea62af9156e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "auth-keys-hub", + "type": "github" + } + }, "bats-assert": { "flake": false, "locked": { @@ -487,6 +598,22 @@ "type": "github" } }, + "bats-assert_4": { + "flake": false, + "locked": { + "lastModified": 1636059754, + "narHash": "sha256-ewME0l27ZqfmAwJO4h5biTALc9bDLv7Bl3ftBzBuZwk=", + "owner": "bats-core", + "repo": "bats-assert", + "rev": "34551b1d7f8c7b677c1a66fc0ac140d6223409e5", + "type": "github" + }, + "original": { + "owner": "bats-core", + "repo": "bats-assert", + "type": "github" + } + }, "bats-support": { "flake": false, "locked": { @@ -535,28 +662,61 @@ "type": "github" } }, + "bats-support_4": { + "flake": false, + "locked": { + "lastModified": 1548869839, + "narHash": "sha256-Gr4ntadr42F2Ks8Pte2D4wNDbijhujuoJi4OPZnTAZU=", + "owner": "bats-core", + "repo": "bats-support", + "rev": "d140a65044b2d6810381935ae7f0c94c7023c8c3", + "type": "github" + }, + "original": { + "owner": "bats-core", + "repo": "bats-support", + "type": "github" + } + }, + "bdwgc-src": { + "flake": false, + "locked": { + "lastModified": 1661523039, + "narHash": "sha256-UYJQGeSykmfydGAmTlNJNyAPBasBkddOSoopBHiY7TI=", + "owner": "ivmai", + "repo": "bdwgc", + "rev": "cd1fbc1dbfd2cc888436944dd2784f39820698d7", + "type": "github" + }, + "original": { + "owner": "ivmai", + "ref": "v8.2.2", + "repo": "bdwgc", + "type": "github" + } + }, "bitte": { "inputs": { "agenix": "agenix", "agenix-cli": "agenix-cli", - "blank": "blank_2", + "blank": "blank_6", "capsules": "capsules", "data-merge": "data-merge", "deploy": "deploy_2", - "fenix": "fenix_4", - "hydra": "hydra_3", - "n2c": "n2c_2", - "nix": "nix_5", - "nixpkgs": "nixpkgs_29", + "fenix": "fenix_6", + "hydra": "hydra_7", + "n2c": "n2c_5", + "nix": "nix_10", + "nixpkgs": "nixpkgs_58", "nixpkgs-docker": "nixpkgs-docker", - "nixpkgs-unstable": "nixpkgs-unstable_3", + "nixpkgs-unstable": "nixpkgs-unstable_8", "nomad-driver-nix": "nomad-driver-nix_2", "nomad-follower": "nomad-follower_2", - "ops-lib": "ops-lib_3", + "ops-lib": "ops-lib_5", "ragenix": "ragenix_3", - "std": "std_2", - "terranix": "terranix_2", - "utils": "utils_12" + "std": "std_6", + "terranix": "terranix_3", + "utils": "utils_17" }, "locked": { "lastModified": 1661790449, @@ -642,20 +802,20 @@ "inputs": { "agenix": "agenix_2", "agenix-cli": "agenix-cli_2", - "blank": "blank_3", + "blank": "blank_7", "deploy": "deploy", - "fenix": "fenix_2", - "hydra": "hydra_2", - "nix": "nix_2", - "nixpkgs": "nixpkgs_15", - "nixpkgs-unstable": "nixpkgs-unstable_2", + "fenix": "fenix_4", + "hydra": "hydra_6", + "nix": "nix_7", + "nixpkgs": "nixpkgs_44", + "nixpkgs-unstable": "nixpkgs-unstable_7", "nomad": "nomad", "nomad-driver-nix": "nomad-driver-nix", "nomad-follower": "nomad-follower", - "ops-lib": "ops-lib_2", + "ops-lib": "ops-lib_4", "ragenix": "ragenix", - "terranix": "terranix", - "utils": "utils_7", + "terranix": "terranix_2", + "utils": "utils_12", "vulnix": "vulnix" }, "locked": { @@ -676,20 +836,20 @@ "inputs": { "agenix": "agenix_6", "agenix-cli": "agenix-cli_3", - "blank": "blank_4", + "blank": "blank_8", "deploy": "deploy_3", - "fenix": "fenix_6", - "hydra": "hydra_4", - "nix": "nix_9", - "nixpkgs": "nixpkgs_44", - "nixpkgs-unstable": "nixpkgs-unstable_4", + "fenix": "fenix_8", + "hydra": "hydra_8", + "nix": "nix_14", + "nixpkgs": "nixpkgs_73", + "nixpkgs-unstable": "nixpkgs-unstable_9", "nomad": "nomad_2", "nomad-driver-nix": "nomad-driver-nix_3", "nomad-follower": "nomad-follower_3", - "ops-lib": "ops-lib_4", + "ops-lib": "ops-lib_6", "ragenix": "ragenix_4", - "terranix": "terranix_3", - "utils": "utils_21", + "terranix": "terranix_4", + "utils": "utils_26", "vulnix": "vulnix_2" }, "locked": { @@ -781,6 +941,51 @@ "type": "github" } }, + "blank_6": { + "locked": { + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "blank", + "type": "github" + } + }, + "blank_7": { + "locked": { + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "blank", + "type": "github" + } + }, + "blank_8": { + "locked": { + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "blank", + "type": "github" + } + }, "blockfrost": { "inputs": { "nixpkgs": "nixpkgs" @@ -800,6 +1005,25 @@ "type": "github" } }, + "blockfrost_2": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1716466734, + "narHash": "sha256-h1LdfN/2KlD/XRjgj7rDNRInxSKZCOx6OF4jak/3c/E=", + "owner": "blockfrost", + "repo": "blockfrost-backend-ryo", + "rev": "7204204615be69b2f298ddf11f9a23dbbb184e55", + "type": "github" + }, + "original": { + "owner": "blockfrost", + "ref": "v2.0.3", + "repo": "blockfrost-backend-ryo", + "type": "github" + } + }, "blst": { "flake": false, "locked": { @@ -834,31 +1058,133 @@ "type": "github" } }, - "byron-chain": { + "blst_3": { "flake": false, "locked": { - "lastModified": 1557232434, - "narHash": "sha256-2rclcOjIVq0lFCdYAa8S9imzZZHqySn2LZ/O48hUofw=", - "owner": "input-output-hk", - "repo": "cardano-mainnet-mirror", - "rev": "a31ac7534ec855b715b9a6bb6a06861ee94935d9", + "lastModified": 1656163412, + "narHash": "sha256-xero1aTe2v4IhWIJaEDUsVDOfE77dOV5zKeHWntHogY=", + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "cardano-mainnet-mirror", + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", "type": "github" } }, - "cabal-32": { + "blst_4": { "flake": false, "locked": { - "lastModified": 1603716527, - "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", - "owner": "haskell", - "repo": "cabal", - "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", - "type": "github" + "lastModified": 1656163412, + "narHash": "sha256-xero1aTe2v4IhWIJaEDUsVDOfE77dOV5zKeHWntHogY=", + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", + "type": "github" + }, + "original": { + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", + "type": "github" + } + }, + "blst_5": { + "flake": false, + "locked": { + "lastModified": 1656163412, + "narHash": "sha256-xero1aTe2v4IhWIJaEDUsVDOfE77dOV5zKeHWntHogY=", + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", + "type": "github" + }, + "original": { + "owner": "supranational", + "repo": "blst", + "rev": "03b5124029979755c752eec45f3c29674b558446", + "type": "github" + } + }, + "blst_6": { + "flake": false, + "locked": { + "lastModified": 1691598027, + "narHash": "sha256-oqljy+ZXJAXEB/fJtmB8rlAr4UXM+Z2OkDa20gpILNA=", + "owner": "supranational", + "repo": "blst", + "rev": "3dd0f804b1819e5d03fb22ca2e6fac105932043a", + "type": "github" + }, + "original": { + "owner": "supranational", + "ref": "v0.3.11", + "repo": "blst", + "type": "github" + } + }, + "blst_7": { + "flake": false, + "locked": { + "lastModified": 1691598027, + "narHash": "sha256-oqljy+ZXJAXEB/fJtmB8rlAr4UXM+Z2OkDa20gpILNA=", + "owner": "supranational", + "repo": "blst", + "rev": "3dd0f804b1819e5d03fb22ca2e6fac105932043a", + "type": "github" + }, + "original": { + "owner": "supranational", + "ref": "v0.3.11", + "repo": "blst", + "type": "github" + } + }, + "byron-chain": { + "flake": false, + "locked": { + "lastModified": 1557232434, + "narHash": "sha256-2rclcOjIVq0lFCdYAa8S9imzZZHqySn2LZ/O48hUofw=", + "owner": "input-output-hk", + "repo": "cardano-mainnet-mirror", + "rev": "a31ac7534ec855b715b9a6bb6a06861ee94935d9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-mainnet-mirror", + "type": "github" + } + }, + "cabal-32": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-32_10": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" }, "original": { "owner": "haskell", @@ -969,6 +1295,40 @@ "type": "github" } }, + "cabal-32_8": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-32_9": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, "cabal-34": { "flake": false, "locked": { @@ -986,14 +1346,31 @@ "type": "github" } }, + "cabal-34_10": { + "flake": false, + "locked": { + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", + "owner": "haskell", + "repo": "cabal", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, "cabal-34_2": { "flake": false, "locked": { - "lastModified": 1640353650, - "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", "owner": "haskell", "repo": "cabal", - "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", "type": "github" }, "original": { @@ -1006,11 +1383,11 @@ "cabal-34_3": { "flake": false, "locked": { - "lastModified": 1640353650, - "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", "owner": "haskell", "repo": "cabal", - "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", "type": "github" }, "original": { @@ -1021,6 +1398,40 @@ } }, "cabal-34_4": { + "flake": false, + "locked": { + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", + "owner": "haskell", + "repo": "cabal", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34_5": { + "flake": false, + "locked": { + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", + "owner": "haskell", + "repo": "cabal", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34_6": { "flake": false, "locked": { "lastModified": 1640353650, @@ -1037,7 +1448,7 @@ "type": "github" } }, - "cabal-34_5": { + "cabal-34_7": { "flake": false, "locked": { "lastModified": 1640353650, @@ -1054,14 +1465,14 @@ "type": "github" } }, - "cabal-34_6": { + "cabal-34_8": { "flake": false, "locked": { - "lastModified": 1645834128, - "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", + "lastModified": 1640353650, + "narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=", "owner": "haskell", "repo": "cabal", - "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", + "rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd", "type": "github" }, "original": { @@ -1071,7 +1482,7 @@ "type": "github" } }, - "cabal-34_7": { + "cabal-34_9": { "flake": false, "locked": { "lastModified": 1640353650, @@ -1105,14 +1516,14 @@ "type": "github" } }, - "cabal-36_2": { + "cabal-36_10": { "flake": false, "locked": { - "lastModified": 1641652457, - "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "lastModified": 1669081697, + "narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=", "owner": "haskell", "repo": "cabal", - "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144", "type": "github" }, "original": { @@ -1122,14 +1533,14 @@ "type": "github" } }, - "cabal-36_3": { + "cabal-36_2": { "flake": false, "locked": { - "lastModified": 1641652457, - "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "lastModified": 1669081697, + "narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=", "owner": "haskell", "repo": "cabal", - "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144", "type": "github" }, "original": { @@ -1139,14 +1550,14 @@ "type": "github" } }, - "cabal-36_4": { + "cabal-36_3": { "flake": false, "locked": { - "lastModified": 1641652457, - "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "lastModified": 1669081697, + "narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=", "owner": "haskell", "repo": "cabal", - "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144", "type": "github" }, "original": { @@ -1156,14 +1567,14 @@ "type": "github" } }, - "cabal-36_5": { + "cabal-36_4": { "flake": false, "locked": { - "lastModified": 1641652457, - "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "lastModified": 1669081697, + "narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=", "owner": "haskell", "repo": "cabal", - "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144", "type": "github" }, "original": { @@ -1173,7 +1584,7 @@ "type": "github" } }, - "cabal-36_6": { + "cabal-36_5": { "flake": false, "locked": { "lastModified": 1669081697, @@ -1190,7 +1601,7 @@ "type": "github" } }, - "cabal-36_7": { + "cabal-36_6": { "flake": false, "locked": { "lastModified": 1641652457, @@ -1207,32 +1618,113 @@ "type": "github" } }, - "capsules": { - "inputs": { - "bitte": "bitte_2", - "iogo": "iogo", - "nixpkgs": "nixpkgs_23", - "ragenix": "ragenix_2" - }, + "cabal-36_7": { + "flake": false, "locked": { - "lastModified": 1658156716, - "narHash": "sha256-c1lH7PIN0rTKdGgosD5fCsHoAklAtGR/E1DFT2exIkM=", - "owner": "input-output-hk", - "repo": "devshell-capsules", - "rev": "88348a415130cee29ce187140e6f57d94d843d54", + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "devshell-capsules", - "type": "github" - } + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cabal-36_8": { + "flake": false, + "locked": { + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cabal-36_9": { + "flake": false, + "locked": { + "lastModified": 1641652457, + "narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=", + "owner": "haskell", + "repo": "cabal", + "rev": "f27667f8ec360c475027dcaee0138c937477b070", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "call-flake": { + "locked": { + "lastModified": 1687380775, + "narHash": "sha256-bmhE1TmrJG4ba93l9WQTLuYM53kwGQAjYHRvHOeuxWU=", + "owner": "divnix", + "repo": "call-flake", + "rev": "74061f6c241227cd05e79b702db9a300a2e4131a", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "call-flake", + "type": "github" + } + }, + "capkgs": { + "locked": { + "lastModified": 1697123727, + "narHash": "sha256-uSXZAELJF5EfivH9qyLssBUAvhcf3RM9sKhD3W2mdhc=", + "owner": "input-output-hk", + "repo": "capkgs", + "rev": "b197e225592dfe38afb80c94b628d99968c0541d", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "capkgs", + "type": "github" + } + }, + "capsules": { + "inputs": { + "bitte": "bitte_2", + "iogo": "iogo", + "nixpkgs": "nixpkgs_52", + "ragenix": "ragenix_2" + }, + "locked": { + "lastModified": 1658156716, + "narHash": "sha256-c1lH7PIN0rTKdGgosD5fCsHoAklAtGR/E1DFT2exIkM=", + "owner": "input-output-hk", + "repo": "devshell-capsules", + "rev": "88348a415130cee29ce187140e6f57d94d843d54", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "devshell-capsules", + "type": "github" + } }, "capsules_2": { "inputs": { "bitte": "bitte_3", "iogo": "iogo_2", - "nixpkgs": "nixpkgs_52", + "nixpkgs": "nixpkgs_81", "ragenix": "ragenix_5" }, "locked": { @@ -1251,20 +1743,23 @@ }, "cardano-automation": { "inputs": { - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_4", "haskellNix": [ "ctl", - "cardano-node", + "cardano-nix", + "cardano-node-8.1.1", "haskellNix" ], "nixpkgs": [ "ctl", - "cardano-node", + "cardano-nix", + "cardano-node-8.1.1", "nixpkgs" ], "tullia": [ "ctl", - "cardano-node", + "cardano-nix", + "cardano-node-8.1.1", "tullia" ] }, @@ -1282,970 +1777,1107 @@ "type": "github" } }, - "cardano-configurations": { - "flake": false, + "cardano-automation_2": { + "inputs": { + "flake-utils": "flake-utils_9", + "haskellNix": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "haskellNix" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "nixpkgs" + ], + "tullia": "tullia_2" + }, "locked": { - "lastModified": 1699561895, - "narHash": "sha256-bLNN6lJUe5dR1EOdtDspReE2fu2EV7hQMHFGDinxf5Y=", + "lastModified": 1679408951, + "narHash": "sha256-xM78upkrXjRu/739V/IxFrA9m+6rvgOiolt4ReKLAog=", "owner": "input-output-hk", - "repo": "cardano-configurations", - "rev": "d952529afdfdf6d53ce190b1bf8af990a7ae9590", + "repo": "cardano-automation", + "rev": "628f135d243d4a9e388c187e4c6179246038ee72", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-configurations", - "rev": "d952529afdfdf6d53ce190b1bf8af990a7ae9590", + "repo": "cardano-automation", "type": "github" } }, - "cardano-configurations_2": { - "flake": false, + "cardano-automation_3": { + "inputs": { + "flake-utils": "flake-utils_16", + "haskellNix": [ + "ctl", + "cardano-node", + "haskellNix" + ], + "nixpkgs": [ + "ctl", + "cardano-node", + "nixpkgs" + ], + "tullia": "tullia_3" + }, "locked": { - "lastModified": 1694019972, - "narHash": "sha256-TQEvb6W2VlOWxqIFa4r8UFBVbu82Bb2hRaDtN5Zbiuk=", + "lastModified": 1679408951, + "narHash": "sha256-xM78upkrXjRu/739V/IxFrA9m+6rvgOiolt4ReKLAog=", "owner": "input-output-hk", - "repo": "cardano-configurations", - "rev": "65ef979cf69f420efca0a7aaf0412a610bc48097", + "repo": "cardano-automation", + "rev": "628f135d243d4a9e388c187e4c6179246038ee72", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-configurations", + "repo": "cardano-automation", "type": "github" } }, - "cardano-explorer-app": { + "cardano-configurations": { "flake": false, "locked": { - "lastModified": 1655291958, - "narHash": "sha256-OByt95cIJrA8pXsvCztsWmFcDaQaSYGohSOHoaZWKJs=", + "lastModified": 1721870874, + "narHash": "sha256-qiReN+xxtbb4kEfdIWbBcqcJpPGD8he0p/TVD7U3CqM=", "owner": "input-output-hk", - "repo": "cardano-explorer-app", - "rev": "a65938afe159adb1d1e2808305a7316738f5e634", + "repo": "cardano-configurations", + "rev": "7969a73e5c7ee1f3b2a40274b34191fdd8de170b", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "fix-nix-system", - "repo": "cardano-explorer-app", + "repo": "cardano-configurations", + "rev": "7969a73e5c7ee1f3b2a40274b34191fdd8de170b", "type": "github" } }, - "cardano-graphql": { + "cardano-configurations-8.1.1": { "flake": false, "locked": { - "lastModified": 1657201429, - "narHash": "sha256-kx8Pe5HllnJceQHsBDB4hHcEQNSiq8D+OFFkRuuUFQE=", + "lastModified": 1692193634, + "narHash": "sha256-cKw+iXKoMNrfN8M34/CtUelUZVLktVtzNzOYHI20dC0=", "owner": "input-output-hk", - "repo": "cardano-graphql", - "rev": "ffb40028f51e23983c2ae27693bbdcd152208d9d", + "repo": "cardano-configurations", + "rev": "9b69b59ef2fb2838855017f19af57b38c5d4abe4", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-graphql", + "repo": "cardano-configurations", + "rev": "9b69b59ef2fb2838855017f19af57b38c5d4abe4", "type": "github" } }, - "cardano-mainnet-mirror": { - "inputs": { - "nixpkgs": "nixpkgs_2" - }, + "cardano-configurations-8.7.3": { + "flake": false, "locked": { - "lastModified": 1642701714, - "narHash": "sha256-SR3luE+ePX6U193EKE/KSEuVzWAW0YsyPYDC4hOvALs=", + "lastModified": 1702085095, + "narHash": "sha256-IJChESftdO2tj2pRB+82xMaLP/RqyKHzttE7QMLqvBQ=", "owner": "input-output-hk", - "repo": "cardano-mainnet-mirror", - "rev": "819488be9eabbba6aaa7c931559bc584d8071e3d", + "repo": "cardano-configurations", + "rev": "21249e0d5c68b4e8f3661b250aa8272a8785d678", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "nix", - "repo": "cardano-mainnet-mirror", + "repo": "cardano-configurations", + "rev": "21249e0d5c68b4e8f3661b250aa8272a8785d678", "type": "github" } }, - "cardano-node": { + "cardano-db-sync": { "inputs": { "CHaP": "CHaP_2", - "cardano-automation": "cardano-automation", - "cardano-mainnet-mirror": "cardano-mainnet-mirror", - "customConfig": "customConfig", - "em": "em", - "empty-flake": "empty-flake", - "flake-compat": "flake-compat", + "cardano-parts": "cardano-parts", + "flake-compat": "flake-compat_4", "hackageNix": "hackageNix", "haskellNix": "haskellNix", - "hostNixpkgs": [ - "ctl", - "cardano-node", - "nixpkgs" - ], "iohkNix": "iohkNix", - "nix2container": "nix2container", "nixpkgs": [ "ctl", - "cardano-node", + "cardano-nix", + "cardano-db-sync", "haskellNix", "nixpkgs-unstable" ], - "ops-lib": "ops-lib", - "std": [ - "ctl", - "cardano-node", - "tullia", - "std" - ], - "tullia": "tullia", - "utils": "utils_2" + "utils": "utils" }, "locked": { - "lastModified": 1687190129, - "narHash": "sha256-JCa9+QhZ2RVSIKkhz2WCZqTKCgdUSuezWS2YsQ5vhM4=", - "owner": "input-output-hk", - "repo": "cardano-node", - "rev": "6f79e5c3ea109a70cd01910368e011635767305a", + "lastModified": 1707925775, + "narHash": "sha256-z3YUrUImpV/wmJi+pfw6YuhBw+2Xd3jGlSWk7WI69/4=", + "owner": "intersectmbo", + "repo": "cardano-db-sync", + "rev": "ed3dc8bbb79f07c26ec43f10bad661b0bef3b915", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "8.1.1", - "repo": "cardano-node", + "owner": "intersectmbo", + "ref": "13.2.0.1", + "repo": "cardano-db-sync", "type": "github" } }, - "cardano-node_2": { + "cardano-db-sync-schema": { "flake": false, "locked": { - "lastModified": 1659625017, - "narHash": "sha256-4IrheFeoWfvkZQndEk4fGUkOiOjcVhcyXZ6IqmvkDgg=", + "lastModified": 1688568916, + "narHash": "sha256-XTGTi3PzCcbLL+63JSXTe7mQmGKB0YgEoW1VpqdX2d0=", "owner": "input-output-hk", - "repo": "cardano-node", - "rev": "950c4e222086fed5ca53564e642434ce9307b0b9", + "repo": "cardano-db-sync", + "rev": "6e69a80797f2d68423b25ca7787e81533b367e42", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "1.35.3", - "repo": "cardano-node", + "ref": "13.1.1.3", + "repo": "cardano-db-sync", "type": "github" } }, - "cardano-shell": { + "cardano-db-sync-schema-ng": { "flake": false, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1694078776, + "narHash": "sha256-QBnUDobTwWQmooCNr1WcaAzRbAKokon8lvAN6VQ1u34=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-db-sync", + "rev": "b44eb735fe64fe4e8079935df722d0a32a41c2a4", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "sancho-1-1-0", + "repo": "cardano-db-sync", "type": "github" } }, - "cardano-shell_2": { + "cardano-db-sync-service": { "flake": false, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1688568916, + "narHash": "sha256-XTGTi3PzCcbLL+63JSXTe7mQmGKB0YgEoW1VpqdX2d0=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-db-sync", + "rev": "6e69a80797f2d68423b25ca7787e81533b367e42", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "13.1.1.3", + "repo": "cardano-db-sync", "type": "github" } }, - "cardano-shell_3": { + "cardano-explorer-app": { "flake": false, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1655291958, + "narHash": "sha256-OByt95cIJrA8pXsvCztsWmFcDaQaSYGohSOHoaZWKJs=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-explorer-app", + "rev": "a65938afe159adb1d1e2808305a7316738f5e634", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "fix-nix-system", + "repo": "cardano-explorer-app", "type": "github" } }, - "cardano-shell_4": { + "cardano-graphql": { "flake": false, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1657201429, + "narHash": "sha256-kx8Pe5HllnJceQHsBDB4hHcEQNSiq8D+OFFkRuuUFQE=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-graphql", + "rev": "ffb40028f51e23983c2ae27693bbdcd152208d9d", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "repo": "cardano-graphql", "type": "github" } }, - "cardano-shell_5": { - "flake": false, + "cardano-mainnet-mirror": { + "inputs": { + "nixpkgs": "nixpkgs_15" + }, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1642701714, + "narHash": "sha256-SR3luE+ePX6U193EKE/KSEuVzWAW0YsyPYDC4hOvALs=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-mainnet-mirror", + "rev": "819488be9eabbba6aaa7c931559bc584d8071e3d", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "nix", + "repo": "cardano-mainnet-mirror", "type": "github" } }, - "cardano-shell_6": { - "flake": false, + "cardano-mainnet-mirror_2": { + "inputs": { + "nixpkgs": "nixpkgs_25" + }, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1642701714, + "narHash": "sha256-SR3luE+ePX6U193EKE/KSEuVzWAW0YsyPYDC4hOvALs=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-mainnet-mirror", + "rev": "819488be9eabbba6aaa7c931559bc584d8071e3d", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "nix", + "repo": "cardano-mainnet-mirror", "type": "github" } }, - "cardano-shell_7": { - "flake": false, + "cardano-mainnet-mirror_3": { + "inputs": { + "nixpkgs": "nixpkgs_34" + }, "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "lastModified": 1642701714, + "narHash": "sha256-SR3luE+ePX6U193EKE/KSEuVzWAW0YsyPYDC4hOvALs=", "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "repo": "cardano-mainnet-mirror", + "rev": "819488be9eabbba6aaa7c931559bc584d8071e3d", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-shell", + "ref": "nix", + "repo": "cardano-mainnet-mirror", "type": "github" } }, - "cardano-wallet": { + "cardano-nix": { "inputs": { - "customConfig": "customConfig_2", - "ema": "ema", - "emanote": "emanote", - "flake-compat": "flake-compat_8", - "flake-utils": "flake-utils_25", - "haskellNix": "haskellNix_2", - "hostNixpkgs": [ + "blockfrost": "blockfrost_2", + "cardano-configurations-8.1.1": "cardano-configurations-8.1.1", + "cardano-configurations-8.7.3": "cardano-configurations-8.7.3", + "cardano-db-sync": "cardano-db-sync", + "cardano-node-8.1.1": "cardano-node-8.1.1", + "cardano-node-8.7.3": "cardano-node-8.7.3", + "devour-flake": "devour-flake", + "devshell": "devshell_4", + "flake-parts": "flake-parts_5", + "flake-root": "flake-root", + "hercules-ci-effects": "hercules-ci-effects", + "nixpkgs": [ "ctl", - "db-sync", - "cardano-world", - "cardano-wallet", "nixpkgs" ], - "iohkNix": "iohkNix_2", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "cardano-wallet", - "haskellNix", - "nixpkgs-unstable" - ] + "pre-commit-hooks-nix": "pre-commit-hooks-nix", + "treefmt-nix": "treefmt-nix_3" }, "locked": { - "lastModified": 1656674685, - "narHash": "sha256-Uq02O758v7U61a9Ol6VzSDyx3S/CVHn0l/OUM1UYJkY=", - "owner": "input-output-hk", - "repo": "cardano-wallet", - "rev": "c0ece6ad1868682b074708ffb810bdc2ea96934f", + "lastModified": 1722438671, + "narHash": "sha256-Nb8bROKPjRWFMsaHIK4BOvsTceL9klpF3Ucp/zHqRzM=", + "owner": "mlabs-haskell", + "repo": "cardano.nix", + "rev": "7e696a77440d14f161c8b426d90fecfdb70ad8d8", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "v2022-07-01", - "repo": "cardano-wallet", + "owner": "mlabs-haskell", + "repo": "cardano.nix", "type": "github" } }, - "cardano-world": { + "cardano-node": { "inputs": { - "bitte": "bitte", - "bitte-cells": "bitte-cells", - "byron-chain": "byron-chain", - "capsules": "capsules_2", - "cardano-db-sync": [ + "CHaP": "CHaP_5", + "cardano-automation": "cardano-automation_3", + "cardano-mainnet-mirror": "cardano-mainnet-mirror_3", + "customConfig": "customConfig_3", + "em": "em_3", + "empty-flake": "empty-flake_4", + "flake-compat": "flake-compat_15", + "hackageNix": "hackageNix_4", + "haskellNix": "haskellNix_4", + "hostNixpkgs": [ "ctl", - "db-sync" + "cardano-node", + "nixpkgs" ], - "cardano-explorer-app": "cardano-explorer-app", - "cardano-graphql": "cardano-graphql", - "cardano-node": "cardano-node_2", - "cardano-wallet": "cardano-wallet", - "data-merge": "data-merge_3", - "flake-compat": "flake-compat_9", - "hackage": "hackage_3", - "haskell-nix": "haskell-nix_2", - "iohk-nix": "iohk-nix", - "n2c": "n2c_3", - "nix-inclusive": "nix-inclusive", - "nixpkgs": "nixpkgs_63", - "nixpkgs-haskell": [ + "iohkNix": "iohkNix_4", + "nix2container": "nix2container_6", + "nixpkgs": [ "ctl", - "db-sync", - "cardano-world", - "haskell-nix", + "cardano-node", + "haskellNix", "nixpkgs-unstable" ], - "ogmios": "ogmios", - "std": "std_3", - "tullia": "tullia_2" + "ops-lib": "ops-lib_3", + "std": "std_5", + "utils": "utils_7" }, "locked": { - "lastModified": 1662508244, - "narHash": "sha256-s8kroVd8VAZ/Lfv2gNt+RzIuSnWpQxAAL0y90tn1i0o=", + "lastModified": 1721843629, + "narHash": "sha256-F5wgRA820x16f+8c/LlEEBG0rMJIA1XWw6X0ZwX5UWs=", "owner": "input-output-hk", - "repo": "cardano-world", - "rev": "0b6dcb5b61a0f7a2c048cb757463cbc0dfa0fe24", + "repo": "cardano-node", + "rev": "176f99e51155cb3eaa0711db1c3c969d67438958", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "cardano-world", + "ref": "9.1.0", + "repo": "cardano-node", "type": "github" } }, - "cicero": { + "cardano-node-8.1.1": { "inputs": { - "alejandra": "alejandra", - "data-merge": "data-merge_2", - "devshell": "devshell_8", - "driver": "driver", - "follower": "follower", - "haskell-nix": "haskell-nix", - "inclusive": "inclusive_8", - "nix": "nix_8", - "nix-cache-proxy": "nix-cache-proxy", - "nixpkgs": "nixpkgs_39", - "poetry2nix": "poetry2nix", - "utils": "utils_16" + "CHaP": "CHaP_3", + "cardano-automation": "cardano-automation", + "cardano-mainnet-mirror": "cardano-mainnet-mirror", + "customConfig": "customConfig", + "em": "em", + "empty-flake": "empty-flake_2", + "flake-compat": "flake-compat_6", + "hackageNix": "hackageNix_2", + "haskellNix": "haskellNix_2", + "hostNixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "nixpkgs" + ], + "iohkNix": "iohkNix_2", + "nix2container": "nix2container", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "haskellNix", + "nixpkgs-unstable" + ], + "ops-lib": "ops-lib", + "std": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std" + ], + "tullia": "tullia", + "utils": "utils_3" }, "locked": { - "lastModified": 1647522107, - "narHash": "sha256-Kti1zv+GXnbujkJ0ODB2ukq4Eb2RVOpudZ1xVDhhbes=", - "owner": "input-output-hk", - "repo": "cicero", - "rev": "0fd8642fe437f6129fe6914f032d3fdc7591d4fe", + "lastModified": 1687190129, + "narHash": "sha256-JCa9+QhZ2RVSIKkhz2WCZqTKCgdUSuezWS2YsQ5vhM4=", + "owner": "intersectmbo", + "repo": "cardano-node", + "rev": "6f79e5c3ea109a70cd01910368e011635767305a", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "cicero", + "owner": "intersectmbo", + "ref": "8.1.1", + "repo": "cardano-node", "type": "github" } }, - "ctl": { + "cardano-node-8.7.3": { "inputs": { - "CHaP": "CHaP", - "blockfrost": "blockfrost", - "cardano-configurations": "cardano-configurations", - "cardano-node": "cardano-node", - "db-sync": "db-sync", - "easy-purescript-nix": "easy-purescript-nix", - "flake-compat": "flake-compat_11", - "hackage-nix": "hackage-nix", - "haskell-nix": "haskell-nix_3", - "hercules-ci-effects": "hercules-ci-effects", - "iohk-nix": "iohk-nix_2", - "kupo": "kupo", - "kupo-nixos": "kupo-nixos", + "CHaP": "CHaP_4", + "cardano-automation": "cardano-automation_2", + "cardano-mainnet-mirror": "cardano-mainnet-mirror_2", + "customConfig": "customConfig_2", + "em": "em_2", + "empty-flake": "empty-flake_3", + "flake-compat": "flake-compat_10", + "hackageNix": "hackageNix_3", + "haskellNix": "haskellNix_3", + "hostNixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "nixpkgs" + ], + "iohkNix": "iohkNix_3", + "nix2container": "nix2container_4", "nixpkgs": [ "ctl", - "haskell-nix", + "cardano-nix", + "cardano-node-8.7.3", + "haskellNix", "nixpkgs-unstable" ], - "ogmios": "ogmios_2", - "ogmios-nixos": "ogmios-nixos", - "plutip": "plutip" + "ops-lib": "ops-lib_2", + "std": "std_3", + "utils": "utils_5" }, "locked": { - "lastModified": 1702645636, - "narHash": "sha256-GiSImwp0QoKheOhX7aftGpYayPdRdu3W1TcXY1GMUuk=", - "owner": "Plutonomicon", - "repo": "cardano-transaction-lib", - "rev": "a742692d605aabd75043aee9eef0ecdfec63eacc", + "lastModified": 1702654749, + "narHash": "sha256-fIzSNSKWC7qMRjHUMHfrMnEzHiFu7ac/UUgfofXqaFY=", + "owner": "intersectmbo", + "repo": "cardano-node", + "rev": "a4a8119b59b1fbb9a69c79e1e6900e91292161e7", "type": "github" }, "original": { - "owner": "Plutonomicon", - "repo": "cardano-transaction-lib", - "rev": "a742692d605aabd75043aee9eef0ecdfec63eacc", + "owner": "intersectmbo", + "ref": "8.7.3", + "repo": "cardano-node", "type": "github" } }, - "customConfig": { + "cardano-node-service": { + "flake": false, "locked": { - "lastModified": 1630400035, - "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "lastModified": 1690209950, + "narHash": "sha256-d0V8N+y/OarYv6GQycGXnbPly7GeJRBEeE1017qj9eI=", "owner": "input-output-hk", - "repo": "empty-flake", - "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", + "repo": "cardano-node", + "rev": "d2d90b48c5577b4412d5c9c9968b55f8ab4b9767", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "empty-flake", + "ref": "8.1.2", + "repo": "cardano-node", "type": "github" } }, - "customConfig_2": { + "cardano-node_2": { + "flake": false, "locked": { - "lastModified": 1630400035, - "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "lastModified": 1659625017, + "narHash": "sha256-4IrheFeoWfvkZQndEk4fGUkOiOjcVhcyXZ6IqmvkDgg=", "owner": "input-output-hk", - "repo": "empty-flake", - "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", + "repo": "cardano-node", + "rev": "950c4e222086fed5ca53564e642434ce9307b0b9", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "empty-flake", + "ref": "1.35.3", + "repo": "cardano-node", "type": "github" } }, - "customConfig_3": { - "locked": { - "lastModified": 1, - "narHash": "sha256-Zd5w1I1Dwt783Q4WuBuCpedcwG1DrIgQGqabyF87prM=", - "path": "./custom-config", - "type": "path" - }, - "original": { - "path": "./custom-config", - "type": "path" - } - }, - "data-merge": { + "cardano-parts": { "inputs": { - "nixlib": "nixlib", - "yants": "yants_2" + "auth-keys-hub": "auth-keys-hub", + "capkgs": "capkgs", + "cardano-db-sync-schema": "cardano-db-sync-schema", + "cardano-db-sync-schema-ng": "cardano-db-sync-schema-ng", + "cardano-db-sync-service": "cardano-db-sync-service", + "cardano-node-service": "cardano-node-service", + "cardano-wallet-service": "cardano-wallet-service", + "colmena": "colmena", + "empty-flake": "empty-flake", + "flake-parts": "flake-parts_3", + "haskell-nix": "haskell-nix", + "inputs-check": "inputs-check", + "iohk-nix": "iohk-nix", + "iohk-nix-ng": "iohk-nix-ng", + "nix": "nix_2", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "nixpkgs" + ], + "nixpkgs-unstable": "nixpkgs-unstable_2", + "offchain-metadata-tools-service": "offchain-metadata-tools-service", + "sops-nix": "sops-nix", + "terraform-providers": "terraform-providers", + "terranix": "terranix", + "treefmt-nix": "treefmt-nix_2" }, "locked": { - "lastModified": 1648237091, - "narHash": "sha256-OtgcOt/CB0/9S0rh1eAog+AvAg9kF6GyAknyWOXiAZI=", - "owner": "divnix", - "repo": "data-merge", - "rev": "b21bcf7bd949ac92af3930ecb1d3df8786384722", + "lastModified": 1697147999, + "narHash": "sha256-mbSWIcmDnt2mlETCNL8MI97nDH1lkOxIxFHKXXfOV28=", + "owner": "input-output-hk", + "repo": "cardano-parts", + "rev": "af8993ee12f78ddfcc31eefe006391669cb11462", "type": "github" }, "original": { - "owner": "divnix", - "repo": "data-merge", + "owner": "input-output-hk", + "repo": "cardano-parts", "type": "github" } }, - "data-merge_2": { - "inputs": { - "nixlib": "nixlib_2" - }, + "cardano-shell": { + "flake": false, "locked": { - "lastModified": 1635967744, - "narHash": "sha256-01065dNad3BIepNzrpYuYInxq/ynqtGMSsIiNqjND7E=", - "owner": "divnix", - "repo": "data-merge", - "rev": "68bd71f980f75cf73bc5071982eddfe6bc089768", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "divnix", - "repo": "data-merge", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "data-merge_3": { - "inputs": { - "nixlib": "nixlib_3", - "yants": "yants_4" - }, + "cardano-shell_10": { + "flake": false, "locked": { - "lastModified": 1655854240, - "narHash": "sha256-j74ixD7Y0bF3h0fBJFKPR9botlrMu0fgG/YsiUKybko=", - "owner": "divnix", - "repo": "data-merge", - "rev": "0bbe0a68d4ee090b8bbad0c5e1e85060d2bdfe98", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "divnix", - "repo": "data-merge", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "db-sync": { - "inputs": { - "cardano-world": "cardano-world", - "customConfig": "customConfig_3", - "flake-compat": "flake-compat_10", - "haskellNix": "haskellNix_3", - "iohkNix": "iohkNix_3", - "nixpkgs": [ - "ctl", - "db-sync", - "haskellNix", - "nixpkgs-unstable" - ], - "utils": "utils_23" - }, + "cardano-shell_2": { + "flake": false, "locked": { - "lastModified": 1670313550, - "narHash": "sha256-Gkn/hyK0xiDJZY1O5JEwuosMzar+IskC9xxeBts+0H4=", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", "owner": "input-output-hk", - "repo": "cardano-db-sync", - "rev": "1040fa9ec85fd75ce9f02dae2006170136793d02", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "13.1.0.0", - "repo": "cardano-db-sync", + "repo": "cardano-shell", "type": "github" } }, - "deploy": { - "inputs": { - "fenix": "fenix", - "flake-compat": "flake-compat_4", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "capsules", - "bitte", - "deploy", - "fenix", - "nixpkgs" - ], - "utils": "utils_3" - }, + "cardano-shell_3": { + "flake": false, "locked": { - "lastModified": 1638318651, - "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", "owner": "input-output-hk", - "repo": "deploy-rs", - "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "deploy-rs", + "repo": "cardano-shell", "type": "github" } }, - "deploy_2": { - "inputs": { - "fenix": "fenix_3", - "flake-compat": "flake-compat_5", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "deploy", - "fenix", - "nixpkgs" - ], - "utils": "utils_9" - }, + "cardano-shell_4": { + "flake": false, "locked": { - "lastModified": 1638318651, - "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", "owner": "input-output-hk", - "repo": "deploy-rs", - "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "deploy-rs", + "repo": "cardano-shell", "type": "github" } }, - "deploy_3": { - "inputs": { - "fenix": "fenix_5", - "flake-compat": "flake-compat_6", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "capsules", - "bitte", - "deploy", - "fenix", - "nixpkgs" - ], - "utils": "utils_17" - }, + "cardano-shell_5": { + "flake": false, "locked": { - "lastModified": 1638318651, - "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", "owner": "input-output-hk", - "repo": "deploy-rs", - "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "deploy-rs", + "repo": "cardano-shell", "type": "github" } }, - "devshell": { - "inputs": { - "flake-utils": [ - "ctl", - "cardano-node", - "tullia", - "std", - "flake-utils" - ], - "nixpkgs": [ - "ctl", - "cardano-node", - "tullia", - "std", - "nixpkgs" - ] - }, + "cardano-shell_6": { + "flake": false, "locked": { - "lastModified": 1663445644, - "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", - "owner": "numtide", - "repo": "devshell", - "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "devshell_10": { + "cardano-shell_7": { + "flake": false, "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "devshell_11": { + "cardano-shell_8": { + "flake": false, "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "devshell_12": { + "cardano-shell_9": { + "flake": false, "locked": { - "lastModified": 1632436039, - "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", - "owner": "numtide", - "repo": "devshell", - "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "cardano-shell", "type": "github" } }, - "devshell_13": { + "cardano-wallet": { + "inputs": { + "customConfig": "customConfig_4", + "ema": "ema", + "emanote": "emanote", + "flake-compat": "flake-compat_21", + "flake-utils": "flake-utils_40", + "haskellNix": "haskellNix_5", + "hostNixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "cardano-wallet", + "nixpkgs" + ], + "iohkNix": "iohkNix_5", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "cardano-wallet", + "haskellNix", + "nixpkgs-unstable" + ] + }, "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", + "lastModified": 1656674685, + "narHash": "sha256-Uq02O758v7U61a9Ol6VzSDyx3S/CVHn0l/OUM1UYJkY=", + "owner": "input-output-hk", + "repo": "cardano-wallet", + "rev": "c0ece6ad1868682b074708ffb810bdc2ea96934f", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "ref": "v2022-07-01", + "repo": "cardano-wallet", "type": "github" } }, - "devshell_14": { + "cardano-wallet-service": { + "flake": false, "locked": { - "lastModified": 1637098489, - "narHash": "sha256-IWBYLSNSENI/fTrXdYDhuCavxcgN9+RERrPM81f6DXY=", - "owner": "numtide", - "repo": "devshell", - "rev": "e8c2d4967b5c498b12551d1bb49352dcf9efa3e4", + "lastModified": 1689751896, + "narHash": "sha256-ijflgIw+1FpLoxM4Rksf4MJvNqnEPAv3gNWE8zMuefU=", + "owner": "cardano-foundation", + "repo": "cardano-wallet", + "rev": "3f0d2f3abe706958fab8cdc528184068bd0453c9", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "cardano-foundation", + "ref": "v2023-07-18", + "repo": "cardano-wallet", "type": "github" } }, - "devshell_15": { + "cardano-world": { "inputs": { - "flake-utils": [ + "bitte": "bitte", + "bitte-cells": "bitte-cells", + "byron-chain": "byron-chain", + "capsules": "capsules_2", + "cardano-db-sync": [ + "ctl", + "db-sync" + ], + "cardano-explorer-app": "cardano-explorer-app", + "cardano-graphql": "cardano-graphql", + "cardano-node": "cardano-node_2", + "cardano-wallet": "cardano-wallet", + "data-merge": "data-merge_3", + "flake-compat": "flake-compat_22", + "hackage": "hackage_4", + "haskell-nix": "haskell-nix_3", + "iohk-nix": "iohk-nix_2", + "n2c": "n2c_6", + "nix-inclusive": "nix-inclusive", + "nixpkgs": "nixpkgs_92", + "nixpkgs-haskell": [ "ctl", "db-sync", "cardano-world", - "std", - "flake-utils" + "haskell-nix", + "nixpkgs-unstable" ], + "ogmios": "ogmios", + "std": "std_7", + "tullia": "tullia_4" + }, + "locked": { + "lastModified": 1662508244, + "narHash": "sha256-s8kroVd8VAZ/Lfv2gNt+RzIuSnWpQxAAL0y90tn1i0o=", + "owner": "input-output-hk", + "repo": "cardano-world", + "rev": "0b6dcb5b61a0f7a2c048cb757463cbc0dfa0fe24", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-world", + "type": "github" + } + }, + "cicero": { + "inputs": { + "alejandra": "alejandra", + "data-merge": "data-merge_2", + "devshell": "devshell_12", + "driver": "driver", + "follower": "follower", + "haskell-nix": "haskell-nix_2", + "inclusive": "inclusive_9", + "nix": "nix_13", + "nix-cache-proxy": "nix-cache-proxy", + "nixpkgs": "nixpkgs_68", + "poetry2nix": "poetry2nix", + "utils": "utils_21" + }, + "locked": { + "lastModified": 1647522107, + "narHash": "sha256-Kti1zv+GXnbujkJ0ODB2ukq4Eb2RVOpudZ1xVDhhbes=", + "owner": "input-output-hk", + "repo": "cicero", + "rev": "0fd8642fe437f6129fe6914f032d3fdc7591d4fe", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cicero", + "type": "github" + } + }, + "colmena": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", "nixpkgs": [ "ctl", - "db-sync", - "cardano-world", - "std", + "cardano-nix", + "cardano-db-sync", + "cardano-parts", "nixpkgs" - ] + ], + "stable": "stable" }, "locked": { - "lastModified": 1658746384, - "narHash": "sha256-CCJcoMOcXyZFrV1ag4XMTpAPjLWb4Anbv+ktXFI1ry0=", - "owner": "numtide", - "repo": "devshell", - "rev": "0ffc7937bb5e8141af03d462b468bd071eb18e1b", + "lastModified": 1684127108, + "narHash": "sha256-01bfuSY4gnshhtqA1EJCw2CMsKkAx+dHS+sEpQ2+EAQ=", + "owner": "zhaofengli", + "repo": "colmena", + "rev": "5fdd743a11e7291bd8ac1e169d62ba6156c99be4", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "zhaofengli", + "ref": "v0.4.0", + "repo": "colmena", "type": "github" } }, - "devshell_16": { + "crane": { "inputs": { - "flake-utils": "flake-utils_31", + "flake-compat": "flake-compat_12", + "flake-utils": "flake-utils_14", "nixpkgs": [ "ctl", - "db-sync", - "cardano-world", - "tullia", + "cardano-nix", + "cardano-node-8.7.3", "std", + "paisano-mdbook-preprocessor", "nixpkgs" - ] + ], + "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1650900878, - "narHash": "sha256-qhNncMBSa9STnhiLfELEQpYC1L4GrYHNIzyCZ/pilsI=", - "owner": "numtide", - "repo": "devshell", - "rev": "d97df53b5ddaa1cfbea7cddbd207eb2634304733", + "lastModified": 1676162383, + "narHash": "sha256-krUCKdz7ebHlFYm/A7IbKDnj2ZmMMm3yIEQcooqm7+E=", + "owner": "ipetkov", + "repo": "crane", + "rev": "6fb400ec631b22ccdbc7090b38207f7fb5cfb5f2", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "ipetkov", + "repo": "crane", "type": "github" } }, - "devshell_2": { + "crystal": { + "inputs": { + "ameba-src": "ameba-src", + "bdwgc-src": "bdwgc-src", + "crystal-aarch64-darwin": "crystal-aarch64-darwin", + "crystal-src": "crystal-src", + "crystal-x86_64-darwin": "crystal-x86_64-darwin", + "crystal-x86_64-linux": "crystal-x86_64-linux", + "crystalline-src": "crystalline-src", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs_3" + }, "locked": { - "lastModified": 1632436039, - "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", - "owner": "numtide", - "repo": "devshell", - "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", + "lastModified": 1683429373, + "narHash": "sha256-Mx5lwMyk2T40wFqOoYcJLs4srwO2UrsepTZhlHNuTrI=", + "owner": "manveru", + "repo": "crystal-flake", + "rev": "e7a443c20e2be6e5dd870586705dd27c91aa9c5c", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "manveru", + "repo": "crystal-flake", "type": "github" } }, - "devshell_3": { + "crystal-aarch64-darwin": { + "flake": false, "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", - "type": "github" + "narHash": "sha256-NqYaZHM3kHAgYbO0RDJtA8eHqp4vVe4MBpisTOGrRVw=", + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-darwin-universal.tar.gz" }, "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-darwin-universal.tar.gz" } }, - "devshell_4": { + "crystal-src": { + "flake": false, "locked": { - "lastModified": 1637098489, - "narHash": "sha256-IWBYLSNSENI/fTrXdYDhuCavxcgN9+RERrPM81f6DXY=", - "owner": "numtide", - "repo": "devshell", - "rev": "e8c2d4967b5c498b12551d1bb49352dcf9efa3e4", + "lastModified": 1681995387, + "narHash": "sha256-t+1vM1m62UftCvfa90Dg6nqt6Zseh/GP/Gc1VfOa4+c=", + "owner": "crystal-lang", + "repo": "crystal", + "rev": "a59a3dbd738269d5aad6051c3834fc70f482f469", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "crystal-lang", + "ref": "1.8.1", + "repo": "crystal", "type": "github" } }, - "devshell_5": { + "crystal-x86_64-darwin": { + "flake": false, "locked": { - "lastModified": 1632436039, - "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", - "owner": "numtide", - "repo": "devshell", - "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", - "type": "github" + "narHash": "sha256-NqYaZHM3kHAgYbO0RDJtA8eHqp4vVe4MBpisTOGrRVw=", + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-darwin-universal.tar.gz" }, "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-darwin-universal.tar.gz" } }, - "devshell_6": { + "crystal-x86_64-linux": { + "flake": false, "locked": { - "lastModified": 1636119665, - "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", - "owner": "numtide", - "repo": "devshell", - "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", + "narHash": "sha256-/Jk3uiglM/hzjygxmMUgVTvz+tuFFjBv8+uUIL05rXo=", + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-linux-x86_64.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/crystal-lang/crystal/releases/download/1.8.1/crystal-1.8.1-1-linux-x86_64.tar.gz" + } + }, + "crystalline-src": { + "flake": false, + "locked": { + "lastModified": 1681549124, + "narHash": "sha256-kx3rdGqIbrOaHY7V3uXLqIFEYzzsMKzNwZ6Neq8zM3c=", + "owner": "elbywan", + "repo": "crystalline", + "rev": "4ac0ae282c5f4172230fea1e93df51c2b380f475", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "elbywan", + "ref": "v0.9.0", + "repo": "crystalline", "type": "github" } }, - "devshell_7": { + "ctl": { "inputs": { - "flake-utils": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "std", - "flake-utils" - ], + "CHaP": "CHaP", + "blockfrost": "blockfrost", + "cardano-configurations": "cardano-configurations", + "cardano-nix": "cardano-nix", + "cardano-node": "cardano-node", + "db-sync": "db-sync", + "easy-purescript-nix": "easy-purescript-nix", + "flake-compat": "flake-compat_24", + "hackage-nix": "hackage-nix", + "haskell-nix": "haskell-nix_4", + "hercules-ci-effects": "hercules-ci-effects_2", + "iohk-nix": "iohk-nix_3", "nixpkgs": [ "ctl", - "db-sync", - "cardano-world", - "bitte", - "std", - "nixpkgs" - ] + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-arion": "nixpkgs-arion", + "ogmios": "ogmios_2" }, "locked": { - "lastModified": 1658746384, - "narHash": "sha256-CCJcoMOcXyZFrV1ag4XMTpAPjLWb4Anbv+ktXFI1ry0=", - "owner": "numtide", - "repo": "devshell", - "rev": "0ffc7937bb5e8141af03d462b468bd071eb18e1b", + "lastModified": 1722613689, + "narHash": "sha256-CACNiPCxPpKNUZpW9Mq7IDa3YwMUqymFIr2bzMWc5bA=", + "owner": "Plutonomicon", + "repo": "cardano-transaction-lib", + "rev": "01708d64e858a2ed3cbbc7a9a235d3acf79a7b91", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "Plutonomicon", + "repo": "cardano-transaction-lib", + "rev": "01708d64e858a2ed3cbbc7a9a235d3acf79a7b91", "type": "github" } }, - "devshell_8": { - "inputs": { - "flake-utils": "flake-utils_15", - "nixpkgs": "nixpkgs_36" - }, + "customConfig": { "locked": { - "lastModified": 1644227066, - "narHash": "sha256-FHcFZtpZEWnUh62xlyY3jfXAXHzJNEDLDzLsJxn+ve0=", - "owner": "numtide", - "repo": "devshell", - "rev": "7033f64dd9ef8d9d8644c5030c73913351d2b660", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "devshell_9": { + "customConfig_2": { "locked": { - "lastModified": 1632436039, - "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", - "owner": "numtide", - "repo": "devshell", - "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "dmerge": { - "inputs": { - "nixlib": [ - "ctl", - "cardano-node", - "tullia", - "std", - "nixpkgs" - ], - "yants": [ - "ctl", - "cardano-node", - "tullia", - "std", - "yants" - ] + "customConfig_3": { + "locked": { + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", + "type": "github" }, + "original": { + "owner": "input-output-hk", + "repo": "empty-flake", + "type": "github" + } + }, + "customConfig_4": { "locked": { - "lastModified": 1659548052, - "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "empty-flake", + "type": "github" + } + }, + "customConfig_5": { + "locked": { + "lastModified": 1, + "narHash": "sha256-Zd5w1I1Dwt783Q4WuBuCpedcwG1DrIgQGqabyF87prM=", + "path": "./custom-config", + "type": "path" + }, + "original": { + "path": "./custom-config", + "type": "path" + } + }, + "data-merge": { + "inputs": { + "nixlib": "nixlib", + "yants": "yants_6" + }, + "locked": { + "lastModified": 1648237091, + "narHash": "sha256-OtgcOt/CB0/9S0rh1eAog+AvAg9kF6GyAknyWOXiAZI=", "owner": "divnix", "repo": "data-merge", - "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", + "rev": "b21bcf7bd949ac92af3930ecb1d3df8786384722", "type": "github" }, "original": { @@ -2254,31 +2886,16 @@ "type": "github" } }, - "dmerge_2": { + "data-merge_2": { "inputs": { - "nixlib": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "std", - "nixpkgs" - ], - "yants": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "std", - "yants" - ] + "nixlib": "nixlib_2" }, "locked": { - "lastModified": 1659548052, - "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "lastModified": 1635967744, + "narHash": "sha256-01065dNad3BIepNzrpYuYInxq/ynqtGMSsIiNqjND7E=", "owner": "divnix", "repo": "data-merge", - "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", + "rev": "68bd71f980f75cf73bc5071982eddfe6bc089768", "type": "github" }, "original": { @@ -2287,29 +2904,17 @@ "type": "github" } }, - "dmerge_3": { + "data-merge_3": { "inputs": { - "nixlib": [ - "ctl", - "db-sync", - "cardano-world", - "std", - "nixpkgs" - ], - "yants": [ - "ctl", - "db-sync", - "cardano-world", - "std", - "yants" - ] + "nixlib": "nixlib_3", + "yants": "yants_8" }, "locked": { - "lastModified": 1659548052, - "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "lastModified": 1655854240, + "narHash": "sha256-j74ixD7Y0bF3h0fBJFKPR9botlrMu0fgG/YsiUKybko=", "owner": "divnix", "repo": "data-merge", - "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", + "rev": "0bbe0a68d4ee090b8bbad0c5e1e85060d2bdfe98", "type": "github" }, "original": { @@ -2318,1065 +2923,1340 @@ "type": "github" } }, - "driver": { + "db-sync": { "inputs": { - "devshell": "devshell_9", - "inclusive": "inclusive_6", - "nix": "nix_7", + "cardano-world": "cardano-world", + "customConfig": "customConfig_5", + "flake-compat": "flake-compat_23", + "haskellNix": "haskellNix_6", + "iohkNix": "iohkNix_6", "nixpkgs": [ "ctl", "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "nixpkgs" + "haskellNix", + "nixpkgs-unstable" ], - "utils": "utils_13" + "utils": "utils_28" }, "locked": { - "lastModified": 1644418487, - "narHash": "sha256-nzFmmBYjNjWVy25bHLLmZECfwJm3nxcAr/mYVYxWggA=", + "lastModified": 1670313550, + "narHash": "sha256-Gkn/hyK0xiDJZY1O5JEwuosMzar+IskC9xxeBts+0H4=", "owner": "input-output-hk", - "repo": "nomad-driver-nix", - "rev": "7f7adb6814b4bf926597e4b810b803140176122c", + "repo": "cardano-db-sync", + "rev": "1040fa9ec85fd75ce9f02dae2006170136793d02", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "nomad-driver-nix", + "ref": "13.1.0.0", + "repo": "cardano-db-sync", "type": "github" } }, - "easy-purescript-nix": { - "flake": false, + "deploy": { + "inputs": { + "fenix": "fenix_3", + "flake-compat": "flake-compat_17", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "capsules", + "bitte", + "deploy", + "fenix", + "nixpkgs" + ], + "utils": "utils_8" + }, "locked": { - "lastModified": 1696584097, - "narHash": "sha256-a9Hhqf/Fi0FkjRTcQr3pYDhrO9A9tdOkaeVgD23Cdrk=", - "owner": "justinwoo", - "repo": "easy-purescript-nix", - "rev": "d5fe5f4b210a0e4bac42ae0c159596a49c5eb016", + "lastModified": 1638318651, + "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "owner": "input-output-hk", + "repo": "deploy-rs", + "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", "type": "github" }, "original": { - "owner": "justinwoo", - "repo": "easy-purescript-nix", + "owner": "input-output-hk", + "repo": "deploy-rs", "type": "github" } }, - "em": { - "flake": false, + "deploy_2": { + "inputs": { + "fenix": "fenix_5", + "flake-compat": "flake-compat_18", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "deploy", + "fenix", + "nixpkgs" + ], + "utils": "utils_14" + }, "locked": { - "lastModified": 1684791668, - "narHash": "sha256-JyPm0RiWCfy/8rs7wd/IRSWIz+bTkD78uxIMnKktU2g=", - "owner": "deepfire", - "repo": "em", - "rev": "302cdf6d654fb18baff0213bdfa41a653774585a", + "lastModified": 1638318651, + "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "owner": "input-output-hk", + "repo": "deploy-rs", + "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", "type": "github" }, "original": { - "owner": "deepfire", - "repo": "em", + "owner": "input-output-hk", + "repo": "deploy-rs", "type": "github" } }, - "ema": { + "deploy_3": { "inputs": { - "flake-compat": "flake-compat_7", - "flake-utils": "flake-utils_22", - "nixpkgs": "nixpkgs_54", - "pre-commit-hooks": "pre-commit-hooks" + "fenix": "fenix_7", + "flake-compat": "flake-compat_19", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "capsules", + "bitte", + "deploy", + "fenix", + "nixpkgs" + ], + "utils": "utils_22" }, "locked": { - "lastModified": 1646661767, - "narHash": "sha256-5zxUr3nO4r04K5WGrW/+nW84qbOW8wNJLt902yQmyF4=", - "owner": "srid", - "repo": "ema", - "rev": "bcabc170b7de9cdd83b4bbcf59130b54933602ea", + "lastModified": 1638318651, + "narHash": "sha256-YsYBMa8Chtb6ccGZOVStReiZ33ZNmi7kNPLf/Ua2kY8=", + "owner": "input-output-hk", + "repo": "deploy-rs", + "rev": "1d3a4f4681a98479219c628165bb6b3a12eae843", "type": "github" }, "original": { - "owner": "srid", - "repo": "ema", + "owner": "input-output-hk", + "repo": "deploy-rs", "type": "github" } }, - "ema_2": { + "devour-flake": { "flake": false, "locked": { - "lastModified": 1655231448, - "narHash": "sha256-LmAnOFKiqOWW9cQNZCbqFF0N1Mx073908voXz+4Fzic=", + "lastModified": 1694098737, + "narHash": "sha256-O51F4YFOzlaQAc9b6xjkAqpvrvCtw/Os2M7TU0y4SKQ=", "owner": "srid", - "repo": "ema", - "rev": "da5b29f03c1edfb7f947666a5a818fb97cc3c229", + "repo": "devour-flake", + "rev": "30a34036b29b0d12989ef6c8be77aa949d85aef5", "type": "github" }, "original": { "owner": "srid", - "ref": "multisite", - "repo": "ema", + "repo": "devour-flake", "type": "github" } }, - "emanote": { + "devshell": { "inputs": { - "ema": "ema_2", - "flake-parts": "flake-parts", - "haskell-flake": "haskell-flake", - "nixpkgs": "nixpkgs_57", - "tailwind-haskell": "tailwind-haskell" + "flake-utils": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "flake-utils" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1655823900, - "narHash": "sha256-YEDJxa2gPf2+GGyrkFz4EliCml1FyDualZtbbZEmljA=", - "owner": "srid", - "repo": "emanote", - "rev": "147528d9df81b881214652ce0cefec0b3d52965e", - "type": "github" - }, - "original": { - "owner": "srid", - "repo": "emanote", - "type": "github" - } - }, - "empty-flake": { - "locked": { - "lastModified": 1630400035, - "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", - "owner": "input-output-hk", - "repo": "empty-flake", - "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", + "lastModified": 1663445644, + "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", + "owner": "numtide", + "repo": "devshell", + "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "empty-flake", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "fenix": { - "inputs": { - "nixpkgs": "nixpkgs_13", - "rust-analyzer-src": "rust-analyzer-src" - }, + "devshell_10": { "locked": { - "lastModified": 1645165506, - "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", - "owner": "nix-community", - "repo": "fenix", - "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", + "owner": "numtide", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "fenix_2": { + "devshell_11": { "inputs": { - "nixpkgs": [ + "flake-utils": [ "ctl", "db-sync", "cardano-world", "bitte", - "capsules", - "bitte", - "nixpkgs-unstable" + "std", + "flake-utils" ], - "rust-analyzer-src": "rust-analyzer-src_2" + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1649226351, - "narHash": "sha256-5fQwF5kYpPC7w0SOfdbE9Z7o5/i/dyo1BxMLVCA2h3E=", - "owner": "nix-community", - "repo": "fenix", - "rev": "c7e184561fe843abb861cd7d22c23066987078e2", + "lastModified": 1658746384, + "narHash": "sha256-CCJcoMOcXyZFrV1ag4XMTpAPjLWb4Anbv+ktXFI1ry0=", + "owner": "numtide", + "repo": "devshell", + "rev": "0ffc7937bb5e8141af03d462b468bd071eb18e1b", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "fenix_3": { + "devshell_12": { "inputs": { - "nixpkgs": "nixpkgs_26", - "rust-analyzer-src": "rust-analyzer-src_3" + "flake-utils": "flake-utils_30", + "nixpkgs": "nixpkgs_65" }, "locked": { - "lastModified": 1645165506, - "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", - "owner": "nix-community", - "repo": "fenix", - "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", + "lastModified": 1644227066, + "narHash": "sha256-FHcFZtpZEWnUh62xlyY3jfXAXHzJNEDLDzLsJxn+ve0=", + "owner": "numtide", + "repo": "devshell", + "rev": "7033f64dd9ef8d9d8644c5030c73913351d2b660", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "fenix_4": { - "inputs": { - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "nixpkgs-unstable" - ], - "rust-analyzer-src": "rust-analyzer-src_4" - }, + "devshell_13": { "locked": { - "lastModified": 1660631227, - "narHash": "sha256-LSXmaDhbPw+3ww63Rx5ewBNWwCQIrzQvzphCFm5BRbU=", - "owner": "nix-community", - "repo": "fenix", - "rev": "41731c1a7ba1441c7544e8a0387aaf58e48f26b8", + "lastModified": 1632436039, + "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", + "owner": "numtide", + "repo": "devshell", + "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "fenix_5": { - "inputs": { - "nixpkgs": "nixpkgs_42", - "rust-analyzer-src": "rust-analyzer-src_5" - }, + "devshell_14": { "locked": { - "lastModified": 1645165506, - "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", - "owner": "nix-community", - "repo": "fenix", - "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", + "owner": "numtide", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "fenix_6": { - "inputs": { - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "capsules", - "bitte", - "nixpkgs-unstable" - ], - "rust-analyzer-src": "rust-analyzer-src_6" - }, + "devshell_15": { "locked": { - "lastModified": 1649226351, - "narHash": "sha256-5fQwF5kYpPC7w0SOfdbE9Z7o5/i/dyo1BxMLVCA2h3E=", - "owner": "nix-community", - "repo": "fenix", - "rev": "c7e184561fe843abb861cd7d22c23066987078e2", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", + "owner": "numtide", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "fenix", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat": { - "flake": false, + "devshell_16": { "locked": { - "lastModified": 1647532380, - "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "7da118186435255a30b5ffeabba9629c344c0bec", + "lastModified": 1632436039, + "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", + "owner": "numtide", + "repo": "devshell", + "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "fixes", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_10": { - "flake": false, + "devshell_17": { "locked": { - "lastModified": 1647532380, - "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "7da118186435255a30b5ffeabba9629c344c0bec", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", + "owner": "numtide", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "fixes", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_11": { - "flake": false, + "devshell_18": { "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "lastModified": 1637098489, + "narHash": "sha256-IWBYLSNSENI/fTrXdYDhuCavxcgN9+RERrPM81f6DXY=", + "owner": "numtide", + "repo": "devshell", + "rev": "e8c2d4967b5c498b12551d1bb49352dcf9efa3e4", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_12": { - "flake": false, + "devshell_19": { + "inputs": { + "flake-utils": [ + "ctl", + "db-sync", + "cardano-world", + "std", + "flake-utils" + ], + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "std", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1672831974, - "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", + "lastModified": 1658746384, + "narHash": "sha256-CCJcoMOcXyZFrV1ag4XMTpAPjLWb4Anbv+ktXFI1ry0=", + "owner": "numtide", + "repo": "devshell", + "rev": "0ffc7937bb5e8141af03d462b468bd071eb18e1b", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "hkm/gitlab-fix", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_13": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" + "devshell_2": { + "inputs": { + "flake-utils": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "flake-utils" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_14": { - "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "lastModified": 1663445644, + "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", + "owner": "numtide", + "repo": "devshell", + "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_15": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" + "devshell_20": { + "inputs": { + "flake-utils": "flake-utils_46", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "tullia", + "std", + "nixpkgs" + ] }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_2": { - "flake": false, "locked": { - "lastModified": 1672831974, - "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", + "lastModified": 1650900878, + "narHash": "sha256-qhNncMBSa9STnhiLfELEQpYC1L4GrYHNIzyCZ/pilsI=", + "owner": "numtide", + "repo": "devshell", + "rev": "d97df53b5ddaa1cfbea7cddbd207eb2634304733", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "hkm/gitlab-fix", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_3": { - "flake": false, + "devshell_3": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" + ], + "systems": "systems_2" + }, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1686680692, + "narHash": "sha256-SsLZz3TDleraAiJq4EkmdyewSyiv5g0LZYc6vaLZOMQ=", + "owner": "numtide", + "repo": "devshell", + "rev": "fd6223370774dd9c33354e87a007004b5fd36442", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_4": { - "flake": false, + "devshell_4": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "nixpkgs" + ], + "systems": "systems_3" + }, "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", + "lastModified": 1695973661, + "narHash": "sha256-BP2H4c42GThPIhERtTpV1yCtwQHYHEKdRu7pjrmQAwo=", + "owner": "numtide", + "repo": "devshell", + "rev": "cd4e2fda3150dd2f689caeac07b7f47df5197c31", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_5": { - "flake": false, + "devshell_5": { + "inputs": { + "flake-utils": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "flake-utils" + ], + "nixpkgs": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", + "lastModified": 1663445644, + "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", + "owner": "numtide", + "repo": "devshell", + "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_6": { - "flake": false, + "devshell_6": { "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", + "lastModified": 1632436039, + "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", + "owner": "numtide", + "repo": "devshell", + "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_7": { - "flake": false, + "devshell_7": { "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "lastModified": 1636119665, + "narHash": "sha256-e11Z9PyH9hdgTm4Vyl8S5iTwrv0um6+srzb1Ba+YUHA=", + "owner": "numtide", + "repo": "devshell", + "rev": "ab14b1a3cb253f58e02f5f849d621292fbf81fad", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_8": { - "flake": false, + "devshell_8": { "locked": { - "lastModified": 1635892615, - "narHash": "sha256-harGbMZr4hzat2BWBU+Y5OYXlu+fVz7E4WeQzHi5o8A=", - "owner": "input-output-hk", - "repo": "flake-compat", - "rev": "eca47d3377946315596da653862d341ee5341318", + "lastModified": 1637098489, + "narHash": "sha256-IWBYLSNSENI/fTrXdYDhuCavxcgN9+RERrPM81f6DXY=", + "owner": "numtide", + "repo": "devshell", + "rev": "e8c2d4967b5c498b12551d1bb49352dcf9efa3e4", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-compat_9": { - "flake": false, + "devshell_9": { "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "lastModified": 1632436039, + "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", + "owner": "numtide", + "repo": "devshell", + "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-parts": { + "dmerge": { "inputs": { - "nixpkgs": "nixpkgs_56" + "nixlib": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "nixpkgs" + ], + "yants": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "yants" + ] }, "locked": { - "lastModified": 1655570068, - "narHash": "sha256-KUSd2a6KgYTHd2l3Goee/P+DrAC6n1Tau+7V68czSZU=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "6dbc77b9c0477f8a9a6a9081077bb38c6a3dbb3a", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "flake-parts_2": { + "dmerge_2": { "inputs": { - "nixpkgs-lib": [ + "nixlib": [ "ctl", - "hercules-ci-effects", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", "nixpkgs" + ], + "yants": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "yants" ] }, "locked": { - "lastModified": 1696343447, - "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "id": "flake-parts", - "type": "indirect" + "owner": "divnix", + "repo": "data-merge", + "type": "github" } }, - "flake-utils": { + "dmerge_3": { + "inputs": { + "haumea": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "haumea" + ], + "nixlib": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "haumea", + "nixpkgs" + ], + "yants": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "lastModified": 1686862774, + "narHash": "sha256-ojGtRQ9pIOUrxsQEuEPerUkqIJEuod9hIflfNkY+9CE=", + "owner": "divnix", + "repo": "dmerge", + "rev": "9f7f7a8349d33d7bd02e0f2b484b1f076e503a96", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "ref": "0.2.1", + "repo": "dmerge", "type": "github" } }, - "flake-utils_10": { + "dmerge_4": { + "inputs": { + "nixlib": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ], + "yants": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "flake-utils_11": { + "dmerge_5": { + "inputs": { + "haumea": [ + "ctl", + "cardano-node", + "std", + "haumea" + ], + "nixlib": [ + "ctl", + "cardano-node", + "std", + "lib" + ], + "yants": [ + "ctl", + "cardano-node", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1686862774, + "narHash": "sha256-ojGtRQ9pIOUrxsQEuEPerUkqIJEuod9hIflfNkY+9CE=", + "owner": "divnix", + "repo": "dmerge", + "rev": "9f7f7a8349d33d7bd02e0f2b484b1f076e503a96", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "ref": "0.2.1", + "repo": "dmerge", "type": "github" } }, - "flake-utils_12": { + "dmerge_6": { + "inputs": { + "nixlib": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "std", + "nixpkgs" + ], + "yants": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "flake-utils_13": { + "dmerge_7": { + "inputs": { + "nixlib": [ + "ctl", + "db-sync", + "cardano-world", + "std", + "nixpkgs" + ], + "yants": [ + "ctl", + "db-sync", + "cardano-world", + "std", + "yants" + ] + }, "locked": { - "lastModified": 1656928814, - "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", + "lastModified": 1659548052, + "narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=", + "owner": "divnix", + "repo": "data-merge", + "rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "divnix", + "repo": "data-merge", "type": "github" } }, - "flake-utils_14": { + "driver": { + "inputs": { + "devshell": "devshell_13", + "inclusive": "inclusive_7", + "nix": "nix_12", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "nixpkgs" + ], + "utils": "utils_18" + }, "locked": { - "lastModified": 1634851050, - "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "lastModified": 1644418487, + "narHash": "sha256-nzFmmBYjNjWVy25bHLLmZECfwJm3nxcAr/mYVYxWggA=", + "owner": "input-output-hk", + "repo": "nomad-driver-nix", + "rev": "7f7adb6814b4bf926597e4b810b803140176122c", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "nomad-driver-nix", "type": "github" } }, - "flake-utils_15": { + "easy-purescript-nix": { + "flake": false, "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "lastModified": 1710161569, + "narHash": "sha256-lcIRIOFCdIWEGyKyG/tB4KvxM9zoWuBRDxW+T+mvIb0=", + "owner": "justinwoo", + "repo": "easy-purescript-nix", + "rev": "117fd96acb69d7d1727df95b6fde9d8715e031fc", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "justinwoo", + "repo": "easy-purescript-nix", "type": "github" } }, - "flake-utils_16": { + "em": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1684791668, + "narHash": "sha256-JyPm0RiWCfy/8rs7wd/IRSWIz+bTkD78uxIMnKktU2g=", + "owner": "deepfire", + "repo": "em", + "rev": "302cdf6d654fb18baff0213bdfa41a653774585a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "deepfire", + "repo": "em", "type": "github" } }, - "flake-utils_17": { + "em_2": { + "flake": false, "locked": { - "lastModified": 1610051610, - "narHash": "sha256-U9rPz/usA1/Aohhk7Cmc2gBrEEKRzcW4nwPWMPwja4Y=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3982c9903e93927c2164caa727cd3f6a0e6d14cc", + "lastModified": 1684791668, + "narHash": "sha256-JyPm0RiWCfy/8rs7wd/IRSWIz+bTkD78uxIMnKktU2g=", + "owner": "deepfire", + "repo": "em", + "rev": "302cdf6d654fb18baff0213bdfa41a653774585a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "deepfire", + "repo": "em", "type": "github" } }, - "flake-utils_18": { + "em_3": { + "flake": false, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", - "type": "github" + "lastModified": 1685015066, + "narHash": "sha256-etAdEoYhtvjTw1ITh28WPNfwvvb5t/fpwCP6s7odSiQ=", + "owner": "deepfire", + "repo": "em", + "rev": "af69bb5c2ac2161434d8fea45f920f8f359587ce", + "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "deepfire", + "repo": "em", "type": "github" } }, - "flake-utils_19": { + "ema": { + "inputs": { + "flake-compat": "flake-compat_20", + "flake-utils": "flake-utils_37", + "nixpkgs": "nixpkgs_83", + "pre-commit-hooks": "pre-commit-hooks" + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1646661767, + "narHash": "sha256-5zxUr3nO4r04K5WGrW/+nW84qbOW8wNJLt902yQmyF4=", + "owner": "srid", + "repo": "ema", + "rev": "bcabc170b7de9cdd83b4bbcf59130b54933602ea", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "srid", + "repo": "ema", "type": "github" } }, - "flake-utils_2": { + "ema_2": { + "flake": false, "locked": { - "lastModified": 1679360468, - "narHash": "sha256-LGnza3cfXF10Biw3ZTg0u9o9t7s680Ww200t5KkHTh8=", - "owner": "hamishmack", - "repo": "flake-utils", - "rev": "e1ea268ff47ad475443dbabcd54744b4e5b9d4f5", + "lastModified": 1655231448, + "narHash": "sha256-LmAnOFKiqOWW9cQNZCbqFF0N1Mx073908voXz+4Fzic=", + "owner": "srid", + "repo": "ema", + "rev": "da5b29f03c1edfb7f947666a5a818fb97cc3c229", "type": "github" }, "original": { - "owner": "hamishmack", - "ref": "hkm/nested-hydraJobs", - "repo": "flake-utils", + "owner": "srid", + "ref": "multisite", + "repo": "ema", "type": "github" } }, - "flake-utils_20": { + "emanote": { + "inputs": { + "ema": "ema_2", + "flake-parts": "flake-parts_6", + "haskell-flake": "haskell-flake", + "nixpkgs": "nixpkgs_86", + "tailwind-haskell": "tailwind-haskell" + }, "locked": { - "lastModified": 1634851050, - "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "lastModified": 1655823900, + "narHash": "sha256-YEDJxa2gPf2+GGyrkFz4EliCml1FyDualZtbbZEmljA=", + "owner": "srid", + "repo": "emanote", + "rev": "147528d9df81b881214652ce0cefec0b3d52965e", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "srid", + "repo": "emanote", "type": "github" } }, - "flake-utils_21": { + "empty-flake": { "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "flake-utils_22": { + "empty-flake_2": { "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "flake-utils_23": { + "empty-flake_3": { "locked": { - "lastModified": 1619345332, - "narHash": "sha256-qHnQkEp1uklKTpx3MvKtY6xzgcqXDsz5nLilbbuL+3A=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "2ebf2558e5bf978c7fb8ea927dfaed8fefab2e28", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "flake-utils_24": { + "empty-flake_4": { "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "lastModified": 1630400035, + "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", + "owner": "input-output-hk", + "repo": "empty-flake", + "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", "type": "github" }, "original": { - "owner": "numtide", - "ref": "v1.0.0", - "repo": "flake-utils", + "owner": "input-output-hk", + "repo": "empty-flake", "type": "github" } }, - "flake-utils_25": { + "fenix": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "auth-keys-hub", + "statix", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "lastModified": 1645251813, + "narHash": "sha256-cQ66tGjnZclBCS3nD26mZ5fUH+3/HnysGffBiWXUSHk=", + "owner": "nix-community", + "repo": "fenix", + "rev": "9892337b588c38ec59466a1c89befce464aae7f8", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_26": { + "fenix_2": { + "inputs": { + "nixpkgs": "nixpkgs_30", + "rust-analyzer-src": "rust-analyzer-src_2" + }, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1677306201, + "narHash": "sha256-VZ9x7qdTosFvVsrpgFHrtYfT6PU3yMIs7NRYn9ELapI=", + "owner": "nix-community", + "repo": "fenix", + "rev": "0923f0c162f65ae40261ec940406049726cfeab4", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_27": { + "fenix_3": { + "inputs": { + "nixpkgs": "nixpkgs_42", + "rust-analyzer-src": "rust-analyzer-src_3" + }, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1645165506, + "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", + "owner": "nix-community", + "repo": "fenix", + "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_28": { + "fenix_4": { + "inputs": { + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "capsules", + "bitte", + "nixpkgs-unstable" + ], + "rust-analyzer-src": "rust-analyzer-src_4" + }, "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "lastModified": 1649226351, + "narHash": "sha256-5fQwF5kYpPC7w0SOfdbE9Z7o5/i/dyo1BxMLVCA2h3E=", + "owner": "nix-community", + "repo": "fenix", + "rev": "c7e184561fe843abb861cd7d22c23066987078e2", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_29": { + "fenix_5": { + "inputs": { + "nixpkgs": "nixpkgs_55", + "rust-analyzer-src": "rust-analyzer-src_5" + }, "locked": { - "lastModified": 1656928814, - "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", + "lastModified": 1645165506, + "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", + "owner": "nix-community", + "repo": "fenix", + "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_3": { + "fenix_6": { + "inputs": { + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "nixpkgs-unstable" + ], + "rust-analyzer-src": "rust-analyzer-src_6" + }, "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "lastModified": 1660631227, + "narHash": "sha256-LSXmaDhbPw+3ww63Rx5ewBNWwCQIrzQvzphCFm5BRbU=", + "owner": "nix-community", + "repo": "fenix", + "rev": "41731c1a7ba1441c7544e8a0387aaf58e48f26b8", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_30": { + "fenix_7": { + "inputs": { + "nixpkgs": "nixpkgs_71", + "rust-analyzer-src": "rust-analyzer-src_7" + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1645165506, + "narHash": "sha256-PClhTeC1EhkHUQQmP9XyiR7y1d6hlEc7QY8nN1GuAzQ=", + "owner": "nix-community", + "repo": "fenix", + "rev": "380b82e3d3381b32f11dfe024cb7d135e36d0168", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_31": { + "fenix_8": { + "inputs": { + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "capsules", + "bitte", + "nixpkgs-unstable" + ], + "rust-analyzer-src": "rust-analyzer-src_8" + }, "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "lastModified": 1649226351, + "narHash": "sha256-5fQwF5kYpPC7w0SOfdbE9Z7o5/i/dyo1BxMLVCA2h3E=", + "owner": "nix-community", + "repo": "fenix", + "rev": "c7e184561fe843abb861cd7d22c23066987078e2", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", "type": "github" } }, - "flake-utils_32": { + "flake-compat": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_33": { + "flake-compat_10": { + "flake": false, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", + "owner": "input-output-hk", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_4": { + "flake-compat_11": { + "flake": false, "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", + "owner": "input-output-hk", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_5": { + "flake-compat_12": { + "flake": false, "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_6": { + "flake-compat_13": { + "flake": false, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_7": { + "flake-compat_14": { + "flake": false, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_8": { + "flake-compat_15": { + "flake": false, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", + "owner": "input-output-hk", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_9": { + "flake-compat_16": { + "flake": false, "locked": { - "lastModified": 1634851050, - "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", + "owner": "input-output-hk", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "input-output-hk", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "flakeCompat": { + "flake-compat_17": { "flake": false, "locked": { - "lastModified": 1641205782, - "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", + "lastModified": 1627913399, + "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", "owner": "edolstra", "repo": "flake-compat", - "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", "type": "github" }, "original": { @@ -3385,3558 +4265,7650 @@ "type": "github" } }, - "follower": { - "inputs": { - "devshell": "devshell_10", - "inclusive": "inclusive_7", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "nixpkgs" - ], - "utils": "utils_14" - }, + "flake-compat_18": { + "flake": false, "locked": { - "lastModified": 1642008295, - "narHash": "sha256-yx3lLN/hlvEeKItHJ5jH0KSm84IruTWMo78IItVPji4=", - "owner": "input-output-hk", - "repo": "nomad-follower", - "rev": "b1b0b00e940026f72d16bdf13e36ad20f1826e8a", + "lastModified": 1627913399, + "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nomad-follower", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk": { + "flake-compat_19": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", - "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "lastModified": 1627913399, + "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_2": { + "flake-compat_2": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_3": { + "flake-compat_20": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", - "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "lastModified": 1641205782, + "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_4": { + "flake-compat_21": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1635892615, + "narHash": "sha256-harGbMZr4hzat2BWBU+Y5OYXlu+fVz7E4WeQzHi5o8A=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "flake-compat", + "rev": "eca47d3377946315596da653862d341ee5341318", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_5": { + "flake-compat_22": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", - "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_6": { + "flake-compat_23": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "ghc-8.6.5-iohk_7": { + "flake-compat_24": { "flake": false, "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", - "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { - "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "ghc98X": { + "flake-compat_25": { "flake": false, "locked": { - "lastModified": 1696643148, - "narHash": "sha256-E02DfgISH7EvvNAu0BHiPvl1E5FGMDi0pWdNZtIBC9I=", - "ref": "ghc-9.8", - "rev": "443e870d977b1ab6fc05f47a9a17bc49296adbd6", - "revCount": 61642, - "submodules": true, - "type": "git", - "url": "https://gitlab.haskell.org/ghc/ghc" + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", + "owner": "input-output-hk", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", + "type": "github" }, "original": { - "ref": "ghc-9.8", - "submodules": true, - "type": "git", - "url": "https://gitlab.haskell.org/ghc/ghc" + "owner": "input-output-hk", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", + "type": "github" } }, - "ghc99": { + "flake-compat_26": { "flake": false, "locked": { - "lastModified": 1701580282, - "narHash": "sha256-drA01r3JrXnkKyzI+owMZGxX0JameMzjK0W5jJE/+V4=", - "ref": "refs/heads/master", - "rev": "f5eb0f2982e9cf27515e892c4bdf634bcfb28459", - "revCount": 62197, - "submodules": true, - "type": "git", - "url": "https://gitlab.haskell.org/ghc/ghc" + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" }, "original": { - "submodules": true, - "type": "git", - "url": "https://gitlab.haskell.org/ghc/ghc" + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" } }, - "gomod2nix": { - "inputs": { - "nixpkgs": "nixpkgs_5", - "utils": "utils" - }, + "flake-compat_3": { + "flake": false, "locked": { - "lastModified": 1655245309, - "narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=", - "owner": "tweag", - "repo": "gomod2nix", - "rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58", + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "type": "github" }, "original": { - "owner": "tweag", - "repo": "gomod2nix", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "hackage": { + "flake-compat_4": { "flake": false, "locked": { - "lastModified": 1646097829, - "narHash": "sha256-PcHDDV8NuUxZhPV/p++IkZC+SDZ1Db7m7K+9HN4/0S4=", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "283f096976b48e54183905e7bdde7f213c6ee5cd", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "hackage.nix", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "hackage-nix": { + "flake-compat_5": { "flake": false, "locked": { - "lastModified": 1702426969, - "narHash": "sha256-rbhpiqSBFwLxTO4Qx2sJm7BzBQo9MidVWlL9W21HHy4=", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "524b4a4d0e06119cd226aa9f5d57986547bd29b4", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "hackage.nix", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "hackageNix": { + "flake-compat_6": { "flake": false, "locked": { - "lastModified": 1685492843, - "narHash": "sha256-X8dNs5Gfc2ucfaWAgZ1VmkpBB4Cb44EQZu0b7tkvz2Y=", + "lastModified": 1647532380, + "narHash": "sha256-wswAxyO8AJTH7d5oU8VK82yBCpqwA+p6kLgpb1f1PAY=", "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "e7407bab324eb2445bda58c5ffac393e80dda1e4", + "repo": "flake-compat", + "rev": "7da118186435255a30b5ffeabba9629c344c0bec", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "hackage.nix", + "ref": "fixes", + "repo": "flake-compat", "type": "github" } }, - "hackage_2": { + "flake-compat_7": { "flake": false, "locked": { - "lastModified": 1655342080, - "narHash": "sha256-mF/clPxSJJkKAq6Y+0oYXrU3rGOuQXFN9btSde3uvvE=", + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "567e2e865d42d8e5cfe796bf03b6b38e42bc00ab", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "hackage.nix", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", "type": "github" } }, - "hackage_3": { + "flake-compat_8": { "flake": false, "locked": { - "lastModified": 1659489414, - "narHash": "sha256-AghgUkUv0hIBh+PvODngYL+ejwhCn2O2OUkVaAZYkCU=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "056c6ce7014adaf887b8e4cad15ef6fd926ea568", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "hackage_4": { + "flake-compat_9": { "flake": false, "locked": { - "lastModified": 1650935983, - "narHash": "sha256-wZTCKzA4f7nk5sIdP2BhGz5qkt6ex5VTC/53U2Y4i9Y=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "b65addc81b03406b3ee8b139549980591ed15be5", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "hackage_5": { - "flake": false, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, "locked": { - "lastModified": 1654219082, - "narHash": "sha256-sm59eg5wSrfIAjNXfBaaOBQ8daghF3g1NiGazYfj+no=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "fc90e7c5dea0483bacb01fc00bd2ab8f8e72500d", + "lastModified": 1672152762, + "narHash": "sha256-U8iWWHgabN07zfbgedogMVWrEP1Zywyf3Yx3OYHSSgE=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "19e0f88324d90509141e192664ded98bb88ef9b2", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "haskell-flake": { + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, "locked": { - "lastModified": 1654001497, - "narHash": "sha256-GfrpyoQrVT9Z/j9its8BQs3I5O5X5Lc2IkK922bz7zg=", - "owner": "srid", - "repo": "haskell-flake", - "rev": "4c0b0ff295f0b97238a600d2381c37ee46b67f9c", + "lastModified": 1682984683, + "narHash": "sha256-fSMthG+tp60AHhNmaHc4StT3ltfHkQsJtN8GhfLWmtI=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "86684881e184f41aa322e653880e497b66429f3e", "type": "github" }, "original": { - "owner": "srid", - "repo": "haskell-flake", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "haskell-nix": { + "flake-parts_3": { "inputs": { - "HTTP": "HTTP_2", - "cabal-32": "cabal-32_2", - "cabal-34": "cabal-34_2", - "cabal-36": "cabal-36_2", - "cardano-shell": "cardano-shell_2", - "flake-utils": "flake-utils_16", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_2", - "hackage": "hackage", - "hpc-coveralls": "hpc-coveralls_2", - "nix-tools": "nix-tools", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "haskell-nix", - "nixpkgs-unstable" - ], + "nixpkgs-lib": "nixpkgs-lib_3" + }, + "locked": { + "lastModified": 1690933134, + "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_4": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_4" + }, + "locked": { + "lastModified": 1690933134, + "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_5": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_5" + }, + "locked": { + "lastModified": 1696343447, + "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_6": { + "inputs": { + "nixpkgs": "nixpkgs_85" + }, + "locked": { + "lastModified": 1655570068, + "narHash": "sha256-KUSd2a6KgYTHd2l3Goee/P+DrAC6n1Tau+7V68czSZU=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "6dbc77b9c0477f8a9a6a9081077bb38c6a3dbb3a", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_7": { + "inputs": { + "nixpkgs-lib": [ + "ctl", + "hercules-ci-effects", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "id": "flake-parts", + "type": "indirect" + } + }, + "flake-root": { + "locked": { + "lastModified": 1692742795, + "narHash": "sha256-f+Y0YhVCIJ06LemO+3Xx00lIcqQxSKJHXT/yk1RTKxw=", + "owner": "srid", + "repo": "flake-root", + "rev": "d9a70d9c7a5fd7f3258ccf48da9335e9b47c3937", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "flake-root", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_10": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_11": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_12": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_13": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_14": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_15": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_16": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_17": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_18": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_19": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1679360468, + "narHash": "sha256-LGnza3cfXF10Biw3ZTg0u9o9t7s680Ww200t5KkHTh8=", + "owner": "hamishmack", + "repo": "flake-utils", + "rev": "e1ea268ff47ad475443dbabcd54744b4e5b9d4f5", + "type": "github" + }, + "original": { + "owner": "hamishmack", + "ref": "hkm/nested-hydraJobs", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_20": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_21": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_22": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_23": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_24": { + "locked": { + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_25": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_26": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_27": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_28": { + "locked": { + "lastModified": 1656928814, + "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_29": { + "locked": { + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "locked": { + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_30": { + "locked": { + "lastModified": 1642700792, + "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_31": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_32": { + "locked": { + "lastModified": 1610051610, + "narHash": "sha256-U9rPz/usA1/Aohhk7Cmc2gBrEEKRzcW4nwPWMPwja4Y=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3982c9903e93927c2164caa727cd3f6a0e6d14cc", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_33": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_34": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_35": { + "locked": { + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_36": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_37": { + "locked": { + "lastModified": 1642700792, + "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_38": { + "locked": { + "lastModified": 1619345332, + "narHash": "sha256-qHnQkEp1uklKTpx3MvKtY6xzgcqXDsz5nLilbbuL+3A=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "2ebf2558e5bf978c7fb8ea927dfaed8fefab2e28", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_39": { + "locked": { + "lastModified": 1652776076, + "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "v1.0.0", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_40": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_41": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_42": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_43": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_44": { + "locked": { + "lastModified": 1656928814, + "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_45": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_46": { + "locked": { + "lastModified": 1642700792, + "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_47": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "locked": { + "lastModified": 1679360468, + "narHash": "sha256-LGnza3cfXF10Biw3ZTg0u9o9t7s680Ww200t5KkHTh8=", + "owner": "hamishmack", + "repo": "flake-utils", + "rev": "e1ea268ff47ad475443dbabcd54744b4e5b9d4f5", + "type": "github" + }, + "original": { + "owner": "hamishmack", + "ref": "hkm/nested-hydraJobs", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_7": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_8": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_9": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flakeCompat": { + "flake": false, + "locked": { + "lastModified": 1641205782, + "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "follower": { + "inputs": { + "devshell": "devshell_14", + "inclusive": "inclusive_8", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "nixpkgs" + ], + "utils": "utils_19" + }, + "locked": { + "lastModified": 1642008295, + "narHash": "sha256-yx3lLN/hlvEeKItHJ5jH0KSm84IruTWMo78IItVPji4=", + "owner": "input-output-hk", + "repo": "nomad-follower", + "rev": "b1b0b00e940026f72d16bdf13e36ad20f1826e8a", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nomad-follower", + "type": "github" + } + }, + "ghc-8.6.5-iohk": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc-8.6.5-iohk_10": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc-8.6.5-iohk_2": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc-8.6.5-iohk_3": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc-8.6.5-iohk_4": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc-8.6.5-iohk_5": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc-8.6.5-iohk_6": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc-8.6.5-iohk_7": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc-8.6.5-iohk_8": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc-8.6.5-iohk_9": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "ghc910X": { + "flake": false, + "locked": { + "lastModified": 1714520650, + "narHash": "sha256-4uz6RA1hRr0RheGNDM49a/B3jszqNNU8iHIow4mSyso=", + "ref": "ghc-9.10", + "rev": "2c6375b9a804ac7fca1e82eb6fcfc8594c67c5f5", + "revCount": 62663, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + }, + "original": { + "ref": "ghc-9.10", + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + } + }, + "ghc911": { + "flake": false, + "locked": { + "lastModified": 1714817013, + "narHash": "sha256-m2je4UvWfkgepMeUIiXHMwE6W+iVfUY38VDGkMzjCcc=", + "ref": "refs/heads/master", + "rev": "fc24c5cf6c62ca9e3c8d236656e139676df65034", + "revCount": 62816, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + }, + "original": { + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + } + }, + "ghc98X": { + "flake": false, + "locked": { + "lastModified": 1696643148, + "narHash": "sha256-E02DfgISH7EvvNAu0BHiPvl1E5FGMDi0pWdNZtIBC9I=", + "ref": "ghc-9.8", + "rev": "443e870d977b1ab6fc05f47a9a17bc49296adbd6", + "revCount": 61642, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + }, + "original": { + "ref": "ghc-9.8", + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + } + }, + "ghc98X_2": { + "flake": false, + "locked": { + "lastModified": 1696643148, + "narHash": "sha256-E02DfgISH7EvvNAu0BHiPvl1E5FGMDi0pWdNZtIBC9I=", + "ref": "ghc-9.8", + "rev": "443e870d977b1ab6fc05f47a9a17bc49296adbd6", + "revCount": 61642, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + }, + "original": { + "ref": "ghc-9.8", + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + } + }, + "ghc99": { + "flake": false, + "locked": { + "lastModified": 1697054644, + "narHash": "sha256-kKarOuXUaAH3QWv7ASx+gGFMHaHKe0pK5Zu37ky2AL4=", + "ref": "refs/heads/master", + "rev": "f383a242c76f90bcca8a4d7ee001dcb49c172a9a", + "revCount": 62040, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + }, + "original": { + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + } + }, + "ghc99_2": { + "flake": false, + "locked": { + "lastModified": 1697054644, + "narHash": "sha256-kKarOuXUaAH3QWv7ASx+gGFMHaHKe0pK5Zu37ky2AL4=", + "ref": "refs/heads/master", + "rev": "f383a242c76f90bcca8a4d7ee001dcb49c172a9a", + "revCount": 62040, + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + }, + "original": { + "submodules": true, + "type": "git", + "url": "https://gitlab.haskell.org/ghc/ghc" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "pre-commit-hooks-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703887061, + "narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gomod2nix": { + "inputs": { + "nixpkgs": "nixpkgs_18", + "utils": "utils_2" + }, + "locked": { + "lastModified": 1655245309, + "narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "gomod2nix", + "type": "github" + } + }, + "gomod2nix_2": { + "inputs": { + "nixpkgs": "nixpkgs_22", + "utils": "utils_4" + }, + "locked": { + "lastModified": 1655245309, + "narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "gomod2nix", + "type": "github" + } + }, + "gomod2nix_3": { + "inputs": { + "nixpkgs": "nixpkgs_31", + "utils": "utils_6" + }, + "locked": { + "lastModified": 1655245309, + "narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "gomod2nix", + "type": "github" + } + }, + "hackage": { + "flake": false, + "locked": { + "lastModified": 1692145451, + "narHash": "sha256-kqfyD3Mu5kgiH5W2ZshUhzO46H0zYDpwD1SWz+POMrk=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "9d2daeca0e09002bc6fb552a097a1802a2f3a4e3", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackage-nix": { + "flake": false, + "locked": { + "lastModified": 1721953589, + "narHash": "sha256-ctYOxCvXQS5MPILV8YPyUhylKhgIhOM4Dc5g0vGNFbM=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "3f0675337984f15834fcd52b97fc766e30f4d684", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackageNix": { + "flake": false, + "locked": { + "lastModified": 1702945378, + "narHash": "sha256-mo1MlOphO4bRwZ8T3mDwU5LOtdQcWSA+93lT1HkCcyw=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "e59b9616a744727e8e64f605f9f216464f12f89b", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackageNix_2": { + "flake": false, + "locked": { + "lastModified": 1685492843, + "narHash": "sha256-X8dNs5Gfc2ucfaWAgZ1VmkpBB4Cb44EQZu0b7tkvz2Y=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "e7407bab324eb2445bda58c5ffac393e80dda1e4", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackageNix_3": { + "flake": false, + "locked": { + "lastModified": 1701303758, + "narHash": "sha256-8XqVEQwmJBxRPFa7SizJuZxbG+NFEZKWdhtYPTQ7ZKM=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "8a0e3ae9295b7ef8431b9be208dd06aa2789be53", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackageNix_4": { + "flake": false, + "locked": { + "lastModified": 1719794527, + "narHash": "sha256-qHo/KumtwAzPkfLWODu/6EFY/LeK+C7iPJyAUdT8tGA=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "da2a3bc9bd1b3dd41bb147279529c471c615fd3e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackage_2": { + "flake": false, + "locked": { + "lastModified": 1646097829, + "narHash": "sha256-PcHDDV8NuUxZhPV/p++IkZC+SDZ1Db7m7K+9HN4/0S4=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "283f096976b48e54183905e7bdde7f213c6ee5cd", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackage_3": { + "flake": false, + "locked": { + "lastModified": 1655342080, + "narHash": "sha256-mF/clPxSJJkKAq6Y+0oYXrU3rGOuQXFN9btSde3uvvE=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "567e2e865d42d8e5cfe796bf03b6b38e42bc00ab", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackage_4": { + "flake": false, + "locked": { + "lastModified": 1659489414, + "narHash": "sha256-AghgUkUv0hIBh+PvODngYL+ejwhCn2O2OUkVaAZYkCU=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "056c6ce7014adaf887b8e4cad15ef6fd926ea568", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "hackage_5": { + "flake": false, + "locked": { + "lastModified": 1650935983, + "narHash": "sha256-wZTCKzA4f7nk5sIdP2BhGz5qkt6ex5VTC/53U2Y4i9Y=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "b65addc81b03406b3ee8b139549980591ed15be5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "haskell-flake": { + "locked": { + "lastModified": 1654001497, + "narHash": "sha256-GfrpyoQrVT9Z/j9its8BQs3I5O5X5Lc2IkK922bz7zg=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "4c0b0ff295f0b97238a600d2381c37ee46b67f9c", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "haskell-flake", + "type": "github" + } + }, + "haskell-nix": { + "inputs": { + "HTTP": "HTTP", + "cabal-32": "cabal-32", + "cabal-34": "cabal-34", + "cabal-36": "cabal-36", + "cardano-shell": "cardano-shell", + "flake-compat": "flake-compat_2", + "flake-utils": "flake-utils_2", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", + "hackage": "hackage", + "hls-1.10": "hls-1.10", + "hls-2.0": "hls-2.0", + "hpc-coveralls": "hpc-coveralls", + "hydra": "hydra", + "iserv-proxy": "iserv-proxy", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003", + "nixpkgs-2105": "nixpkgs-2105", + "nixpkgs-2111": "nixpkgs-2111", + "nixpkgs-2205": "nixpkgs-2205", + "nixpkgs-2211": "nixpkgs-2211", + "nixpkgs-2305": "nixpkgs-2305", + "nixpkgs-unstable": "nixpkgs-unstable", + "old-ghc-nix": "old-ghc-nix", + "stackage": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "empty-flake" + ] + }, + "locked": { + "lastModified": 1692147008, + "narHash": "sha256-ZiRaryaboJbNZ7y7XKZs2xuSfydZyGeupJNOfYpgQSw=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "1970bb2d5b0eb8152f89b305f32d055dbd6857d9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskell-nix_2": { + "inputs": { + "HTTP": "HTTP_6", + "cabal-32": "cabal-32_6", + "cabal-34": "cabal-34_6", + "cabal-36": "cabal-36_6", + "cardano-shell": "cardano-shell_6", + "flake-utils": "flake-utils_31", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_6", + "hackage": "hackage_2", + "hpc-coveralls": "hpc-coveralls_6", + "nix-tools": "nix-tools", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_6", + "nixpkgs-2105": "nixpkgs-2105_6", + "nixpkgs-2111": "nixpkgs-2111_6", + "nixpkgs-unstable": [ + "ctl", + "db-sync", + "cardano-world", + "bitte-cells", + "cicero", + "nixpkgs" + ], + "old-ghc-nix": "old-ghc-nix_6", + "stackage": "stackage_5" + }, + "locked": { + "lastModified": 1646097976, + "narHash": "sha256-EiyrBqayw67dw8pr1XCVU9tIZ+/jzXCQycW1S9a+KFA=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "f0308ed1df3ce9f10f9da1a7c0c8591921d0b4e5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskell-nix_3": { + "inputs": { + "HTTP": "HTTP_8", + "cabal-32": "cabal-32_8", + "cabal-34": "cabal-34_8", + "cabal-36": "cabal-36_8", + "cardano-shell": "cardano-shell_8", + "flake-utils": "flake-utils_42", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_8", + "hackage": [ + "ctl", + "db-sync", + "cardano-world", + "hackage" + ], + "hpc-coveralls": "hpc-coveralls_8", + "hydra": "hydra_10", + "nix-tools": "nix-tools_3", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "haskell-nix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_8", + "nixpkgs-2105": "nixpkgs-2105_8", + "nixpkgs-2111": "nixpkgs-2111_8", + "nixpkgs-2205": "nixpkgs-2205_6", + "nixpkgs-unstable": "nixpkgs-unstable_11", + "old-ghc-nix": "old-ghc-nix_8", + "stackage": "stackage_7" + }, + "locked": { + "lastModified": 1659439444, + "narHash": "sha256-qUK7OVpM8/piOImpPgzSUvOFHQq19sQpvOSns2nW8es=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "ee6a6559e16a603677d7cbef7c4fe18ca801b48e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskell-nix_4": { + "inputs": { + "HTTP": "HTTP_10", + "cabal-32": "cabal-32_10", + "cabal-34": "cabal-34_10", + "cabal-36": "cabal-36_10", + "cardano-shell": "cardano-shell_10", + "flake-compat": "flake-compat_25", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_10", + "hackage": [ + "ctl", + "hackage-nix" + ], + "hls-1.10": "hls-1.10_6", + "hls-2.0": "hls-2.0_5", + "hls-2.2": "hls-2.2_4", + "hls-2.3": "hls-2.3_4", + "hls-2.4": "hls-2.4_4", + "hls-2.5": "hls-2.5_2", + "hls-2.6": "hls-2.6_2", + "hls-2.7": "hls-2.7_2", + "hls-2.8": "hls-2.8_2", + "hls-2.9": "hls-2.9", + "hpc-coveralls": "hpc-coveralls_10", + "hydra": "hydra_12", + "iserv-proxy": "iserv-proxy_6", + "nixpkgs": [ + "ctl", + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_10", + "nixpkgs-2105": "nixpkgs-2105_10", + "nixpkgs-2111": "nixpkgs-2111_10", + "nixpkgs-2205": "nixpkgs-2205_7", + "nixpkgs-2211": "nixpkgs-2211_6", + "nixpkgs-2305": "nixpkgs-2305_5", + "nixpkgs-2311": "nixpkgs-2311_2", + "nixpkgs-2405": "nixpkgs-2405", + "nixpkgs-unstable": "nixpkgs-unstable_13", + "old-ghc-nix": "old-ghc-nix_10", + "stackage": "stackage_9" + }, + "locked": { + "lastModified": 1721956799, + "narHash": "sha256-FU09PlekhkuocxDO2UN2aARdUflIGA36VP1EUra4b7c=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "ccbd8ed7d4aff11e0507d19dc7c40601487c0bea", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix": { + "inputs": { + "HTTP": "HTTP_2", + "cabal-32": "cabal-32_2", + "cabal-34": "cabal-34_2", + "cabal-36": "cabal-36_2", + "cardano-shell": "cardano-shell_2", + "flake-compat": "flake-compat_5", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_2", + "ghc98X": "ghc98X", + "ghc99": "ghc99", + "hackage": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "hackageNix" + ], + "hls-1.10": "hls-1.10_2", + "hls-2.0": "hls-2.0_2", + "hls-2.2": "hls-2.2", + "hls-2.3": "hls-2.3", + "hls-2.4": "hls-2.4", + "hpc-coveralls": "hpc-coveralls_2", + "hydra": "hydra_2", + "iserv-proxy": "iserv-proxy_2", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "haskellNix", + "nixpkgs-unstable" + ], "nixpkgs-2003": "nixpkgs-2003_2", "nixpkgs-2105": "nixpkgs-2105_2", "nixpkgs-2111": "nixpkgs-2111_2", - "nixpkgs-unstable": [ + "nixpkgs-2205": "nixpkgs-2205_2", + "nixpkgs-2211": "nixpkgs-2211_2", + "nixpkgs-2305": "nixpkgs-2305_2", + "nixpkgs-unstable": "nixpkgs-unstable_3", + "old-ghc-nix": "old-ghc-nix_2", + "stackage": "stackage" + }, + "locked": { + "lastModified": 1701053834, + "narHash": "sha256-4sH4//POARjeKJv1mu8aU4W4A28GYqrj9KB3PqusHis=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "7c491c55157208575c70c7b8434e9d4a1cf173a6", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_2": { + "inputs": { + "HTTP": "HTTP_3", + "cabal-32": "cabal-32_3", + "cabal-34": "cabal-34_3", + "cabal-36": "cabal-36_3", + "cardano-shell": "cardano-shell_3", + "flake-compat": "flake-compat_7", + "flake-utils": "flake-utils_5", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_3", + "hackage": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "hackageNix" + ], + "hls-1.10": "hls-1.10_3", + "hpc-coveralls": "hpc-coveralls_3", + "hydra": "hydra_3", + "iserv-proxy": "iserv-proxy_3", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_3", + "nixpkgs-2105": "nixpkgs-2105_3", + "nixpkgs-2111": "nixpkgs-2111_3", + "nixpkgs-2205": "nixpkgs-2205_3", + "nixpkgs-2211": "nixpkgs-2211_3", + "nixpkgs-unstable": "nixpkgs-unstable_4", + "old-ghc-nix": "old-ghc-nix_3", + "stackage": "stackage_2" + }, + "locked": { + "lastModified": 1685495397, + "narHash": "sha256-BwbWroS1Qm8BiHatG5+iHMHN5U6kqOccewBROUYuMKw=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "d07c42cdb1cf88d0cab27d3090b00cb3899643c9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_3": { + "inputs": { + "HTTP": "HTTP_4", + "cabal-32": "cabal-32_4", + "cabal-34": "cabal-34_4", + "cabal-36": "cabal-36_4", + "cardano-shell": "cardano-shell_4", + "flake-compat": "flake-compat_11", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_4", + "ghc98X": "ghc98X_2", + "ghc99": "ghc99_2", + "hackage": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "hackageNix" + ], + "hls-1.10": "hls-1.10_4", + "hls-2.0": "hls-2.0_3", + "hls-2.2": "hls-2.2_2", + "hls-2.3": "hls-2.3_2", + "hls-2.4": "hls-2.4_2", + "hpc-coveralls": "hpc-coveralls_4", + "hydra": "hydra_4", + "iserv-proxy": "iserv-proxy_4", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_4", + "nixpkgs-2105": "nixpkgs-2105_4", + "nixpkgs-2111": "nixpkgs-2111_4", + "nixpkgs-2205": "nixpkgs-2205_4", + "nixpkgs-2211": "nixpkgs-2211_4", + "nixpkgs-2305": "nixpkgs-2305_3", + "nixpkgs-unstable": "nixpkgs-unstable_5", + "old-ghc-nix": "old-ghc-nix_4", + "stackage": "stackage_3" + }, + "locked": { + "lastModified": 1700441391, + "narHash": "sha256-oJqP1AUskUvr3GNUH97eKwaIUHdYgENS2kQ7GI9RI+c=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "3b6056f3866f88d1d16eaeb2e810d3ac0df0e7cd", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_4": { + "inputs": { + "HTTP": "HTTP_5", + "cabal-32": "cabal-32_5", + "cabal-34": "cabal-34_5", + "cabal-36": "cabal-36_5", + "cardano-shell": "cardano-shell_5", + "flake-compat": "flake-compat_16", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_5", + "ghc910X": "ghc910X", + "ghc911": "ghc911", + "hackage": [ + "ctl", + "cardano-node", + "hackageNix" + ], + "hls-1.10": "hls-1.10_5", + "hls-2.0": "hls-2.0_4", + "hls-2.2": "hls-2.2_3", + "hls-2.3": "hls-2.3_3", + "hls-2.4": "hls-2.4_3", + "hls-2.5": "hls-2.5", + "hls-2.6": "hls-2.6", + "hls-2.7": "hls-2.7", + "hls-2.8": "hls-2.8", + "hpc-coveralls": "hpc-coveralls_5", + "hydra": "hydra_5", + "iserv-proxy": "iserv-proxy_5", + "nixpkgs": [ + "ctl", + "cardano-node", + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_5", + "nixpkgs-2105": "nixpkgs-2105_5", + "nixpkgs-2111": "nixpkgs-2111_5", + "nixpkgs-2205": "nixpkgs-2205_5", + "nixpkgs-2211": "nixpkgs-2211_5", + "nixpkgs-2305": "nixpkgs-2305_4", + "nixpkgs-2311": "nixpkgs-2311", + "nixpkgs-unstable": "nixpkgs-unstable_6", + "old-ghc-nix": "old-ghc-nix_5", + "stackage": "stackage_4" + }, + "locked": { + "lastModified": 1718797200, + "narHash": "sha256-ueFxTuZrQ3ZT/Fj5sSeUWlqKa4+OkUU1xW0E+q/XTfw=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "cb139fa956158397aa398186bb32dd26f7318784", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_5": { + "inputs": { + "HTTP": "HTTP_7", + "cabal-32": "cabal-32_7", + "cabal-34": "cabal-34_7", + "cabal-36": "cabal-36_7", + "cardano-shell": "cardano-shell_7", + "flake-utils": "flake-utils_41", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_7", + "hackage": "hackage_3", + "hpc-coveralls": "hpc-coveralls_7", + "hydra": "hydra_9", + "nix-tools": "nix-tools_2", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "cardano-wallet", + "nixpkgs" + ], + "nixpkgs-2003": "nixpkgs-2003_7", + "nixpkgs-2105": "nixpkgs-2105_7", + "nixpkgs-2111": "nixpkgs-2111_7", + "nixpkgs-unstable": "nixpkgs-unstable_10", + "old-ghc-nix": "old-ghc-nix_7", + "stackage": "stackage_6" + }, + "locked": { + "lastModified": 1655369909, + "narHash": "sha256-Z3d17WvaXY2kWdfsOE6yPKViQ1RBfGi4d7XZgXA/j2I=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "5a310b0b3904d9b90239390eb2dfb59e4dcb0d96", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haskellNix_6": { + "inputs": { + "HTTP": "HTTP_9", + "cabal-32": "cabal-32_9", + "cabal-34": "cabal-34_9", + "cabal-36": "cabal-36_9", + "cardano-shell": "cardano-shell_9", + "flake-utils": "flake-utils_47", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_9", + "hackage": "hackage_5", + "hpc-coveralls": "hpc-coveralls_9", + "hydra": "hydra_11", + "nix-tools": "nix-tools_4", + "nixpkgs": [ + "ctl", + "db-sync", + "haskellNix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003_9", + "nixpkgs-2105": "nixpkgs-2105_9", + "nixpkgs-2111": "nixpkgs-2111_9", + "nixpkgs-unstable": "nixpkgs-unstable_12", + "old-ghc-nix": "old-ghc-nix_9", + "stackage": "stackage_8" + }, + "locked": { + "lastModified": 1650936156, + "narHash": "sha256-B58b4OCSc6ohRjGEdbQ78r+TK/OZYsBXION90kfQDC4=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "9a502b8c8aac4d7b8033bc9affb87fd03d4740fc", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "haumea": { + "inputs": { + "nixpkgs": "nixpkgs_28" + }, + "locked": { + "lastModified": 1685133229, + "narHash": "sha256-FePm/Gi9PBSNwiDFq3N+DWdfxFq0UKsVVTJS3cQPn94=", + "owner": "nix-community", + "repo": "haumea", + "rev": "34dd58385092a23018748b50f9b23de6266dffc2", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "v0.2.2", + "repo": "haumea", + "type": "github" + } + }, + "haumea_2": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-node", + "std", + "lib" + ] + }, + "locked": { + "lastModified": 1685133229, + "narHash": "sha256-FePm/Gi9PBSNwiDFq3N+DWdfxFq0UKsVVTJS3cQPn94=", + "owner": "nix-community", + "repo": "haumea", + "rev": "34dd58385092a23018748b50f9b23de6266dffc2", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "v0.2.2", + "repo": "haumea", + "type": "github" + } + }, + "hercules-ci-effects": { + "inputs": { + "flake-parts": [ + "ctl", + "cardano-nix", + "flake-parts" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1710396488, + "narHash": "sha256-yniBB5i1un44uzR4+luTWvZ6uGvsHSYIBiDZ8Xox4nQ=", + "owner": "mlabs-haskell", + "repo": "hercules-ci-effects", + "rev": "f5ed263ab0585dfb7b067301419fb80d64e8c021", + "type": "github" + }, + "original": { + "owner": "mlabs-haskell", + "ref": "push-cache-effect", + "repo": "hercules-ci-effects", + "type": "github" + } + }, + "hercules-ci-effects_2": { + "inputs": { + "flake-parts": "flake-parts_7", + "nixpkgs": "nixpkgs_99" + }, + "locked": { + "lastModified": 1719226092, + "narHash": "sha256-YNkUMcCUCpnULp40g+svYsaH1RbSEj6s4WdZY/SHe38=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "11e4b8dc112e2f485d7c97e1cee77f9958f498f5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "type": "github" + } + }, + "hls-1.10": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_2": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_3": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_4": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_5": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-1.10_6": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0_2": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0_3": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0_4": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0_5": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.2": { + "flake": false, + "locked": { + "lastModified": 1693064058, + "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.2.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.2_2": { + "flake": false, + "locked": { + "lastModified": 1693064058, + "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.2.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.2_3": { + "flake": false, + "locked": { + "lastModified": 1693064058, + "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.2.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.2_4": { + "flake": false, + "locked": { + "lastModified": 1693064058, + "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.2.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.3": { + "flake": false, + "locked": { + "lastModified": 1695910642, + "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.3.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.3_2": { + "flake": false, + "locked": { + "lastModified": 1695910642, + "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.3.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.3_3": { + "flake": false, + "locked": { + "lastModified": 1695910642, + "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.3.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.3_4": { + "flake": false, + "locked": { + "lastModified": 1695910642, + "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.3.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.4": { + "flake": false, + "locked": { + "lastModified": 1696939266, + "narHash": "sha256-VOMf5+kyOeOmfXTHlv4LNFJuDGa7G3pDnOxtzYR40IU=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "362fdd1293efb4b82410b676ab1273479f6d17ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.4.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.4_2": { + "flake": false, + "locked": { + "lastModified": 1696939266, + "narHash": "sha256-VOMf5+kyOeOmfXTHlv4LNFJuDGa7G3pDnOxtzYR40IU=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "362fdd1293efb4b82410b676ab1273479f6d17ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.4.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.4_3": { + "flake": false, + "locked": { + "lastModified": 1699862708, + "narHash": "sha256-YHXSkdz53zd0fYGIYOgLt6HrA0eaRJi9mXVqDgmvrjk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "54507ef7e85fa8e9d0eb9a669832a3287ffccd57", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.4.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.4_4": { + "flake": false, + "locked": { + "lastModified": 1699862708, + "narHash": "sha256-YHXSkdz53zd0fYGIYOgLt6HrA0eaRJi9mXVqDgmvrjk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "54507ef7e85fa8e9d0eb9a669832a3287ffccd57", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.4.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.5": { + "flake": false, + "locked": { + "lastModified": 1701080174, + "narHash": "sha256-fyiR9TaHGJIIR0UmcCb73Xv9TJq3ht2ioxQ2mT7kVdc=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "27f8c3d3892e38edaef5bea3870161815c4d014c", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.5.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.5_2": { + "flake": false, + "locked": { + "lastModified": 1701080174, + "narHash": "sha256-fyiR9TaHGJIIR0UmcCb73Xv9TJq3ht2ioxQ2mT7kVdc=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "27f8c3d3892e38edaef5bea3870161815c4d014c", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.5.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.6": { + "flake": false, + "locked": { + "lastModified": 1705325287, + "narHash": "sha256-+P87oLdlPyMw8Mgoul7HMWdEvWP/fNlo8jyNtwME8E8=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "6e0b342fa0327e628610f2711f8c3e4eaaa08b1e", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.6.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.6_2": { + "flake": false, + "locked": { + "lastModified": 1705325287, + "narHash": "sha256-+P87oLdlPyMw8Mgoul7HMWdEvWP/fNlo8jyNtwME8E8=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "6e0b342fa0327e628610f2711f8c3e4eaaa08b1e", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.6.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.7": { + "flake": false, + "locked": { + "lastModified": 1708965829, + "narHash": "sha256-LfJ+TBcBFq/XKoiNI7pc4VoHg4WmuzsFxYJ3Fu+Jf+M=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "50322b0a4aefb27adc5ec42f5055aaa8f8e38001", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.7.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.7_2": { + "flake": false, + "locked": { + "lastModified": 1708965829, + "narHash": "sha256-LfJ+TBcBFq/XKoiNI7pc4VoHg4WmuzsFxYJ3Fu+Jf+M=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "50322b0a4aefb27adc5ec42f5055aaa8f8e38001", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.7.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.8": { + "flake": false, + "locked": { + "lastModified": 1715153580, + "narHash": "sha256-Vi/iUt2pWyUJlo9VrYgTcbRviWE0cFO6rmGi9rmALw0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "dd1be1beb16700de59e0d6801957290bcf956a0a", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.8.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.8_2": { + "flake": false, + "locked": { + "lastModified": 1715153580, + "narHash": "sha256-Vi/iUt2pWyUJlo9VrYgTcbRviWE0cFO6rmGi9rmALw0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "dd1be1beb16700de59e0d6801957290bcf956a0a", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.8.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.9": { + "flake": false, + "locked": { + "lastModified": 1718469202, + "narHash": "sha256-THXSz+iwB1yQQsr/PY151+2GvtoJnTIB2pIQ4OzfjD4=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "40891bccb235ebacce020b598b083eab9dda80f1", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.9.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hpc-coveralls": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_10": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_2": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_3": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_4": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_5": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_6": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_7": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_8": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hpc-coveralls_9": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hydra": { + "inputs": { + "nix": "nix", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_10": { + "inputs": { + "nix": "nix_18", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_11": { + "inputs": { + "nix": "nix_19", + "nixpkgs": [ + "ctl", + "db-sync", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_12": { + "inputs": { + "nix": "nix_20", + "nixpkgs": [ + "ctl", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_2": { + "inputs": { + "nix": "nix_3", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_3": { + "inputs": { + "nix": "nix_4", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_4": { + "inputs": { + "nix": "nix_5", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_5": { + "inputs": { + "nix": "nix_6", + "nixpkgs": [ + "ctl", + "cardano-node", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "hydra_6": { + "inputs": { + "nix": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "capsules", + "bitte", + "nix" + ], + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "capsules", + "bitte", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1631062883, + "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", + "owner": "kreisys", + "repo": "hydra", + "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "type": "github" + }, + "original": { + "owner": "kreisys", + "ref": "hydra-server-includes", + "repo": "hydra", + "type": "github" + } + }, + "hydra_7": { + "inputs": { + "nix": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "nix" + ], + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1631062883, + "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", + "owner": "kreisys", + "repo": "hydra", + "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "type": "github" + }, + "original": { + "owner": "kreisys", + "ref": "hydra-server-includes", + "repo": "hydra", + "type": "github" + } + }, + "hydra_8": { + "inputs": { + "nix": [ + "ctl", + "db-sync", + "cardano-world", + "capsules", + "bitte", + "nix" + ], + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "capsules", + "bitte", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1631062883, + "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", + "owner": "kreisys", + "repo": "hydra", + "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "type": "github" + }, + "original": { + "owner": "kreisys", + "ref": "hydra-server-includes", + "repo": "hydra", + "type": "github" + } + }, + "hydra_9": { + "inputs": { + "nix": "nix_17", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "cardano-wallet", + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "incl": { + "inputs": { + "nixlib": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1669263024, + "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", + "owner": "divnix", + "repo": "incl", + "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "incl", + "type": "github" + } + }, + "incl_2": { + "inputs": { + "nixlib": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1669263024, + "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", + "owner": "divnix", + "repo": "incl", + "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "incl", + "type": "github" + } + }, + "incl_3": { + "inputs": { + "nixlib": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "haumea", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1669263024, + "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", + "owner": "divnix", + "repo": "incl", + "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "incl", + "type": "github" + } + }, + "incl_4": { + "inputs": { + "nixlib": [ + "ctl", + "cardano-node", + "std", + "lib" + ] + }, + "locked": { + "lastModified": 1669263024, + "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", + "owner": "divnix", + "repo": "incl", + "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "incl", + "type": "github" + } + }, + "inclusive": { + "inputs": { + "stdlib": "stdlib" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_10": { + "inputs": { + "stdlib": "stdlib_10" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_11": { + "inputs": { + "stdlib": "stdlib_11" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_12": { + "inputs": { + "stdlib": "stdlib_12" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_2": { + "inputs": { + "stdlib": "stdlib_2" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_3": { + "inputs": { + "stdlib": "stdlib_3" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_4": { + "inputs": { + "stdlib": "stdlib_4" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_5": { + "inputs": { + "stdlib": "stdlib_5" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_6": { + "inputs": { + "stdlib": "stdlib_6" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_7": { + "inputs": { + "stdlib": "stdlib_7" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_8": { + "inputs": { + "stdlib": "stdlib_8" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inclusive_9": { + "inputs": { + "stdlib": "stdlib_9" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "inputs-check": { + "inputs": { + "flake-parts": "flake-parts_4", + "nixpkgs": "nixpkgs_7" + }, + "locked": { + "lastModified": 1692633913, + "narHash": "sha256-f80/49lt2hIapc9AEaTBC93jnRZe5zxlm21JXXewkko=", + "owner": "input-output-hk", + "repo": "inputs-check", + "rev": "1e9f65e56140f4e357c9abaf5311e3ea979d33e9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "inputs-check", + "type": "github" + } + }, + "iogo": { + "inputs": { + "devshell": "devshell_8", + "inclusive": "inclusive_4", + "nixpkgs": "nixpkgs_51", + "utils": "utils_13" + }, + "locked": { + "lastModified": 1652212694, + "narHash": "sha256-baAY5wKzccNsm7OCEYuySrkXRmlshokCHQjs4EdYShM=", + "owner": "input-output-hk", + "repo": "bitte-iogo", + "rev": "e465975aa368b2d919e865f71eeed02828e55471", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "bitte-iogo", + "type": "github" + } + }, + "iogo_2": { + "inputs": { + "devshell": "devshell_18", + "inclusive": "inclusive_12", + "nixpkgs": "nixpkgs_80", + "utils": "utils_27" + }, + "locked": { + "lastModified": 1658302707, + "narHash": "sha256-E0FA1CEMQlfAsmtLBRoQE7IY4ItKlBdxZ44YX0tK5Hg=", + "owner": "input-output-hk", + "repo": "bitte-iogo", + "rev": "8751660009202bc95ea3a29e304c393c140a4231", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "bitte-iogo", + "type": "github" + } + }, + "iohk-nix": { + "inputs": { + "blst": "blst", + "nixpkgs": "nixpkgs_8", + "secp256k1": "secp256k1", + "sodium": "sodium" + }, + "locked": { + "lastModified": 1691469905, + "narHash": "sha256-TV0p1dFGYAMl1dLJEfe/tNFjxvV2H7VgHU1I43q+b84=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "2f3760f135616ebc477d3ed74eba9b63c22f83a0", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "2f3760f135616ebc477d3ed74eba9b63c22f83a0", + "type": "github" + } + }, + "iohk-nix-ng": { + "inputs": { + "blst": "blst_2", + "nixpkgs": "nixpkgs_9", + "secp256k1": "secp256k1_2", + "sodium": "sodium_2" + }, + "locked": { + "lastModified": 1696471795, + "narHash": "sha256-aNNvjUtCGXaXSp5M/HSj1SOeLjqLyTRWYbIHqAEeUp0=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "91f16fa8acb58b312f94977715c630d8bf77e33e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohk-nix_2": { + "inputs": { + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1658222743, + "narHash": "sha256-yFH01psqx30y5Ws4dBElLkxYpIxxqZx4G+jCVhsXpnA=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "9a604d01bd4420ab7f396f14d1947fbe2ce7db8b", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohk-nix_3": { + "inputs": { + "blst": "blst_7", + "nixpkgs": [ + "ctl", + "nixpkgs" + ], + "secp256k1": "secp256k1_7", + "sodium": "sodium_7" + }, + "locked": { + "lastModified": 1721825987, + "narHash": "sha256-PPcma4tjozwXJAWf+YtHUQUulmxwulVlwSQzKItx/n8=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "eb61f2c14e1f610ec59117ad40f8690cddbf80cb", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix": { + "inputs": { + "blst": "blst_3", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "nixpkgs" + ], + "secp256k1": "secp256k1_3", + "sodium": "sodium_3" + }, + "locked": { + "lastModified": 1698999258, + "narHash": "sha256-42D1BMbdyZD+lT+pWUzb5zDQyasNbMJtH/7stuPuPfE=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "73dc2bb45af6f20cfe1d962f1334eed5e84ae764", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_2": { + "inputs": { + "blst": "blst_4", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "nixpkgs" + ], + "secp256k1": "secp256k1_4", + "sodium": "sodium_4" + }, + "locked": { + "lastModified": 1684223806, + "narHash": "sha256-IyLoP+zhuyygLtr83XXsrvKyqqLQ8FHXTiySFf4FJOI=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "86421fdd89b3af43fa716ccd07638f96c6ecd1e4", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_3": { + "inputs": { + "blst": "blst_5", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "nixpkgs" + ], + "secp256k1": "secp256k1_5", + "sodium": "sodium_5" + }, + "locked": { + "lastModified": 1698746924, + "narHash": "sha256-8og+vqQPEoB2KLUtN5esGMDymT+2bT/rCHZt1NAe7y0=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "af551ca93d969d9715fa9bf86691d9a0a19e89d9", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_4": { + "inputs": { + "blst": "blst_6", + "nixpkgs": [ + "ctl", + "cardano-node", + "nixpkgs" + ], + "secp256k1": "secp256k1_6", + "sodium": "sodium_6" + }, + "locked": { + "lastModified": 1721825987, + "narHash": "sha256-PPcma4tjozwXJAWf+YtHUQUulmxwulVlwSQzKItx/n8=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "eb61f2c14e1f610ec59117ad40f8690cddbf80cb", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_5": { + "inputs": { + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "cardano-wallet", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1653579289, + "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iohkNix_6": { + "inputs": { + "nixpkgs": [ + "ctl", + "db-sync", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1667394105, + "narHash": "sha256-YhS7zGd6jK/QM/+wWyj0zUBZmE3HOXAL/kpJptGYIWg=", + "owner": "input-output-hk", + "repo": "iohk-nix", + "rev": "7fc7625a9ab2ba137bc70ddbc89a13d3fdb78c8b", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "iohk-nix", + "type": "github" + } + }, + "iserv-proxy": { + "flake": false, + "locked": { + "lastModified": 1688517130, + "narHash": "sha256-hUqfxSlo+ffqVdkSZ1EDoB7/ILCL25eYkcCXW9/P3Wc=", + "ref": "hkm/remote-iserv", + "rev": "9151db2a9a61d7f5fe52ff8836f18bbd0fd8933c", + "revCount": 13, + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + }, + "original": { + "ref": "hkm/remote-iserv", + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + } + }, + "iserv-proxy_2": { + "flake": false, + "locked": { + "lastModified": 1691634696, + "narHash": "sha256-MZH2NznKC/gbgBu8NgIibtSUZeJ00HTLJ0PlWKCBHb0=", + "ref": "hkm/remote-iserv", + "rev": "43a979272d9addc29fbffc2e8542c5d96e993d73", + "revCount": 14, + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + }, + "original": { + "ref": "hkm/remote-iserv", + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + } + }, + "iserv-proxy_3": { + "flake": false, + "locked": { + "lastModified": 1670983692, + "narHash": "sha256-avLo34JnI9HNyOuauK5R69usJm+GfW3MlyGlYxZhTgY=", + "ref": "hkm/remote-iserv", + "rev": "50d0abb3317ac439a4e7495b185a64af9b7b9300", + "revCount": 10, + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + }, + "original": { + "ref": "hkm/remote-iserv", + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + } + }, + "iserv-proxy_4": { + "flake": false, + "locked": { + "lastModified": 1691634696, + "narHash": "sha256-MZH2NznKC/gbgBu8NgIibtSUZeJ00HTLJ0PlWKCBHb0=", + "ref": "hkm/remote-iserv", + "rev": "43a979272d9addc29fbffc2e8542c5d96e993d73", + "revCount": 14, + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + }, + "original": { + "ref": "hkm/remote-iserv", + "type": "git", + "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + } + }, + "iserv-proxy_5": { + "flake": false, + "locked": { + "lastModified": 1717479972, + "narHash": "sha256-7vE3RQycHI1YT9LHJ1/fUaeln2vIpYm6Mmn8FTpYeVo=", + "owner": "stable-haskell", + "repo": "iserv-proxy", + "rev": "2ed34002247213fc435d0062350b91bab920626e", + "type": "github" + }, + "original": { + "owner": "stable-haskell", + "ref": "iserv-syms", + "repo": "iserv-proxy", + "type": "github" + } + }, + "iserv-proxy_6": { + "flake": false, + "locked": { + "lastModified": 1717479972, + "narHash": "sha256-7vE3RQycHI1YT9LHJ1/fUaeln2vIpYm6Mmn8FTpYeVo=", + "owner": "stable-haskell", + "repo": "iserv-proxy", + "rev": "2ed34002247213fc435d0062350b91bab920626e", + "type": "github" + }, + "original": { + "owner": "stable-haskell", + "ref": "iserv-syms", + "repo": "iserv-proxy", + "type": "github" + } + }, + "lib": { + "locked": { + "lastModified": 1694306727, + "narHash": "sha256-26fkTOJOI65NOTNKFvtcJF9mzzf/kK9swHzfYt1Dl6Q=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "c30b6a84c0b84ec7aecbe74466033facc9ed103f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "lowdown-src": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_10": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_11": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_12": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_13": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_14": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_15": { + "flake": false, + "locked": { + "lastModified": 1598695561, + "narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_16": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_17": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_18": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_19": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_2": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_20": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_3": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_4": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_5": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_6": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_7": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_8": { + "flake": false, + "locked": { + "lastModified": 1598695561, + "narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lowdown-src_9": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "mdbook-kroki-preprocessor": { + "flake": false, + "locked": { + "lastModified": 1661755005, + "narHash": "sha256-1TJuUzfyMycWlOQH67LR63/ll2GDZz25I3JfScy/Jnw=", + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "rev": "93adb5716d035829efed27f65f2f0833a7d3e76f", + "type": "github" + }, + "original": { + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "type": "github" + } + }, + "mdbook-kroki-preprocessor_2": { + "flake": false, + "locked": { + "lastModified": 1655670640, + "narHash": "sha256-JjqdxftHBjABTkOpFl3cWUJtc/KGwkQ3NRWGLjH2oUs=", + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "rev": "bb6e607437ecc3f22fd9036acee6b797a5b45dbc", + "type": "github" + }, + "original": { + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "type": "github" + } + }, + "mdbook-kroki-preprocessor_3": { + "flake": false, + "locked": { + "lastModified": 1655670640, + "narHash": "sha256-JjqdxftHBjABTkOpFl3cWUJtc/KGwkQ3NRWGLjH2oUs=", + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "rev": "bb6e607437ecc3f22fd9036acee6b797a5b45dbc", + "type": "github" + }, + "original": { + "owner": "JoelCourtney", + "repo": "mdbook-kroki-preprocessor", + "type": "github" + } + }, + "n2c": { + "inputs": { + "flake-utils": [ "ctl", - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "flake-utils" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", "nixpkgs" + ] + }, + "locked": { + "lastModified": 1665039323, + "narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "n2c_2": { + "inputs": { + "flake-utils": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "flake-utils" ], - "old-ghc-nix": "old-ghc-nix_2", - "stackage": "stackage_2" + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1677330646, + "narHash": "sha256-hUYCwJneMjnxTvj30Fjow6UMJUITqHlpUGpXMPXUJsU=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "ebca8f58d450cae1a19c07701a5a8ae40afc9efc", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "n2c_3": { + "inputs": { + "flake-utils": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "flake-utils" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1685771919, + "narHash": "sha256-3lVKWrhNXjHJB6QkZ2SJaOs4X/mmYXtY6ovPVpDMOHc=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "95e2220911874064b5d809f8d35f7835184c4ddf", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "n2c_4": { + "inputs": { + "flake-utils": "flake-utils_19", + "nixpkgs": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1665039323, + "narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "n2c_5": { + "inputs": { + "flake-utils": "flake-utils_26", + "nixpkgs": "nixpkgs_56" }, "locked": { - "lastModified": 1646097976, - "narHash": "sha256-EiyrBqayw67dw8pr1XCVU9tIZ+/jzXCQycW1S9a+KFA=", - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "f0308ed1df3ce9f10f9da1a7c0c8591921d0b4e5", + "lastModified": 1650568002, + "narHash": "sha256-CciO5C3k/a7sbA+lW4jeiU6WGletujMjWcRzc1513tI=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "2cd391fc65847ea54e3657a491c379854b556262", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "haskell.nix", + "owner": "nlewo", + "repo": "nix2container", "type": "github" } }, - "haskell-nix_2": { + "n2c_6": { "inputs": { - "HTTP": "HTTP_4", - "cabal-32": "cabal-32_4", - "cabal-34": "cabal-34_4", - "cabal-36": "cabal-36_4", - "cardano-shell": "cardano-shell_4", - "flake-utils": "flake-utils_27", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_4", - "hackage": [ + "flake-utils": "flake-utils_43", + "nixpkgs": "nixpkgs_91" + }, + "locked": { + "lastModified": 1655533513, + "narHash": "sha256-MAqvv2AZbyNYGJMpV5l9ydN7k66jDErFpaKOvZ1Y7f8=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "2d47dbe633a059d75c7878f554420158712481cb", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "nix": { + "inputs": { + "lowdown-src": "lowdown-src", + "nixpkgs": "nixpkgs_6", + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "owner": "NixOS", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" + } + }, + "nix-cache-proxy": { + "inputs": { + "devshell": "devshell_15", + "inclusive": [ "ctl", "db-sync", "cardano-world", - "hackage" + "bitte-cells", + "cicero", + "inclusive" ], - "hpc-coveralls": "hpc-coveralls_4", - "hydra": "hydra_6", - "nix-tools": "nix-tools_3", "nixpkgs": [ "ctl", "db-sync", "cardano-world", - "haskell-nix", - "nixpkgs-unstable" + "bitte-cells", + "cicero", + "nixpkgs" ], - "nixpkgs-2003": "nixpkgs-2003_4", - "nixpkgs-2105": "nixpkgs-2105_4", - "nixpkgs-2111": "nixpkgs-2111_4", - "nixpkgs-2205": "nixpkgs-2205_2", - "nixpkgs-unstable": "nixpkgs-unstable_6", - "old-ghc-nix": "old-ghc-nix_4", - "stackage": "stackage_4" + "utils": "utils_20" }, "locked": { - "lastModified": 1659439444, - "narHash": "sha256-qUK7OVpM8/piOImpPgzSUvOFHQq19sQpvOSns2nW8es=", + "lastModified": 1644317729, + "narHash": "sha256-R9R1XHv69VvZ/c7lXYs18PHcnEBXS+hDfhjdkZ96lgw=", "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "ee6a6559e16a603677d7cbef7c4fe18ca801b48e", + "repo": "nix-cache-proxy", + "rev": "378617d6b9865be96f7dfa16e0ce3f329da844ec", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "haskell.nix", + "repo": "nix-cache-proxy", "type": "github" } }, - "haskell-nix_3": { + "nix-inclusive": { "inputs": { - "HTTP": "HTTP_6", - "cabal-32": "cabal-32_6", - "cabal-34": "cabal-34_6", - "cabal-36": "cabal-36_6", - "cardano-shell": "cardano-shell_6", - "flake-compat": "flake-compat_12", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_6", - "ghc98X": "ghc98X", - "ghc99": "ghc99", - "hackage": [ + "stdlib": "stdlib_13" + }, + "locked": { + "lastModified": 1628098927, + "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", + "owner": "input-output-hk", + "repo": "nix-inclusive", + "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-inclusive", + "type": "github" + } + }, + "nix-nomad": { + "inputs": { + "flake-compat": "flake-compat_8", + "flake-utils": [ "ctl", - "hackage-nix" + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "nix2container", + "flake-utils" ], - "hls-1.10": "hls-1.10_2", - "hls-2.0": "hls-2.0", - "hls-2.2": "hls-2.2", - "hls-2.3": "hls-2.3", - "hls-2.4": "hls-2.4", - "hpc-coveralls": "hpc-coveralls_6", - "hydra": "hydra_8", - "iserv-proxy": "iserv-proxy_2", + "gomod2nix": "gomod2nix", "nixpkgs": [ "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", "nixpkgs" ], - "nixpkgs-2003": "nixpkgs-2003_6", - "nixpkgs-2105": "nixpkgs-2105_6", - "nixpkgs-2111": "nixpkgs-2111_6", - "nixpkgs-2205": "nixpkgs-2205_3", - "nixpkgs-2211": "nixpkgs-2211_2", - "nixpkgs-2305": "nixpkgs-2305", - "nixpkgs-2311": "nixpkgs-2311", - "nixpkgs-unstable": "nixpkgs-unstable_8", - "old-ghc-nix": "old-ghc-nix_6", - "stackage": "stackage_6" + "nixpkgs-lib": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "nixpkgs" + ] }, "locked": { - "lastModified": 1702428573, - "narHash": "sha256-KpY2FsKQs6vUABgQFjUCqaTPVN5dStNjt0Dxjw7CA9g=", - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "78c22a52a0d80d7e29c12f74df871ebb58a0795d", + "lastModified": 1658277770, + "narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=", + "owner": "tristanpemble", + "repo": "nix-nomad", + "rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "haskell.nix", + "owner": "tristanpemble", + "repo": "nix-nomad", "type": "github" } }, - "haskell-nix_4": { + "nix-nomad_2": { "inputs": { - "HTTP": "HTTP_7", - "cabal-32": "cabal-32_7", - "cabal-34": "cabal-34_7", - "cabal-36": "cabal-36_7", - "cardano-shell": "cardano-shell_7", - "flake-utils": "flake-utils_33", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_7", - "hackage": "hackage_5", - "hpc-coveralls": "hpc-coveralls_7", - "hydra": "hydra_9", - "nix-tools": "nix-tools_5", + "flake-compat": "flake-compat_9", + "flake-utils": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "nix2container", + "flake-utils" + ], + "gomod2nix": "gomod2nix_2", "nixpkgs": [ "ctl", - "kupo-nixos", - "haskell-nix", - "nixpkgs-unstable" + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "nixpkgs" ], - "nixpkgs-2003": "nixpkgs-2003_7", - "nixpkgs-2105": "nixpkgs-2105_7", - "nixpkgs-2111": "nixpkgs-2111_7", - "nixpkgs-unstable": "nixpkgs-unstable_9", - "old-ghc-nix": "old-ghc-nix_7", - "stackage": "stackage_7" + "nixpkgs-lib": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "nixpkgs" + ] }, "locked": { - "lastModified": 1654219238, - "narHash": "sha256-PMS7uSQjYCjsjUfVidTdKcuNtKNu5VPmeNvxruT72go=", - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "974a61451bb1d41b32090eb51efd7ada026d16d9", + "lastModified": 1658277770, + "narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=", + "owner": "tristanpemble", + "repo": "nix-nomad", + "rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "974a61451bb1d41b32090eb51efd7ada026d16d9", + "owner": "tristanpemble", + "repo": "nix-nomad", "type": "github" } }, - "haskellNix": { + "nix-nomad_3": { "inputs": { - "HTTP": "HTTP", - "cabal-32": "cabal-32", - "cabal-34": "cabal-34", - "cabal-36": "cabal-36", - "cardano-shell": "cardano-shell", - "flake-compat": "flake-compat_2", - "flake-utils": "flake-utils_2", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", - "hackage": [ + "flake-compat": "flake-compat_14", + "flake-utils": [ "ctl", "cardano-node", - "hackageNix" + "cardano-automation", + "tullia", + "nix2container", + "flake-utils" ], - "hls-1.10": "hls-1.10", - "hpc-coveralls": "hpc-coveralls", - "hydra": "hydra", - "iserv-proxy": "iserv-proxy", + "gomod2nix": "gomod2nix_3", "nixpkgs": [ "ctl", "cardano-node", + "cardano-automation", + "tullia", "nixpkgs" ], - "nixpkgs-2003": "nixpkgs-2003", - "nixpkgs-2105": "nixpkgs-2105", - "nixpkgs-2111": "nixpkgs-2111", - "nixpkgs-2205": "nixpkgs-2205", - "nixpkgs-2211": "nixpkgs-2211", - "nixpkgs-unstable": "nixpkgs-unstable", - "old-ghc-nix": "old-ghc-nix", - "stackage": "stackage" + "nixpkgs-lib": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1658277770, + "narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=", + "owner": "tristanpemble", + "repo": "nix-nomad", + "rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70", + "type": "github" }, + "original": { + "owner": "tristanpemble", + "repo": "nix-nomad", + "type": "github" + } + }, + "nix-tools": { + "flake": false, "locked": { - "lastModified": 1685495397, - "narHash": "sha256-BwbWroS1Qm8BiHatG5+iHMHN5U6kqOccewBROUYuMKw=", + "lastModified": 1644395812, + "narHash": "sha256-BVFk/BEsTLq5MMZvdy3ZYHKfaS3dHrsKh4+tb5t5b58=", "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "d07c42cdb1cf88d0cab27d3090b00cb3899643c9", + "repo": "nix-tools", + "rev": "d847c63b99bbec78bf83be2a61dc9f09b8a9ccc1", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "haskell.nix", + "repo": "nix-tools", "type": "github" } }, - "haskellNix_2": { - "inputs": { - "HTTP": "HTTP_3", - "cabal-32": "cabal-32_3", - "cabal-34": "cabal-34_3", - "cabal-36": "cabal-36_3", - "cardano-shell": "cardano-shell_3", - "flake-utils": "flake-utils_26", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_3", - "hackage": "hackage_2", - "hpc-coveralls": "hpc-coveralls_3", - "hydra": "hydra_5", - "nix-tools": "nix-tools_2", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "cardano-wallet", - "nixpkgs" - ], - "nixpkgs-2003": "nixpkgs-2003_3", - "nixpkgs-2105": "nixpkgs-2105_3", - "nixpkgs-2111": "nixpkgs-2111_3", - "nixpkgs-unstable": "nixpkgs-unstable_5", - "old-ghc-nix": "old-ghc-nix_3", - "stackage": "stackage_3" - }, + "nix-tools_2": { + "flake": false, "locked": { - "lastModified": 1655369909, - "narHash": "sha256-Z3d17WvaXY2kWdfsOE6yPKViQ1RBfGi4d7XZgXA/j2I=", + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "5a310b0b3904d9b90239390eb2dfb59e4dcb0d96", + "repo": "nix-tools", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "haskell.nix", + "repo": "nix-tools", "type": "github" } }, - "haskellNix_3": { - "inputs": { - "HTTP": "HTTP_5", - "cabal-32": "cabal-32_5", - "cabal-34": "cabal-34_5", - "cabal-36": "cabal-36_5", - "cardano-shell": "cardano-shell_5", - "flake-utils": "flake-utils_32", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_5", - "hackage": "hackage_4", - "hpc-coveralls": "hpc-coveralls_5", - "hydra": "hydra_7", - "nix-tools": "nix-tools_4", - "nixpkgs": [ - "ctl", - "db-sync", - "haskellNix", - "nixpkgs-unstable" - ], - "nixpkgs-2003": "nixpkgs-2003_5", - "nixpkgs-2105": "nixpkgs-2105_5", - "nixpkgs-2111": "nixpkgs-2111_5", - "nixpkgs-unstable": "nixpkgs-unstable_7", - "old-ghc-nix": "old-ghc-nix_5", - "stackage": "stackage_5" + "nix-tools_3": { + "flake": false, + "locked": { + "lastModified": 1658968505, + "narHash": "sha256-UnbQ/Ig/23e9hUdDOBwYHwHgHmQawZ2uazpJ8DLIJgE=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "8a754bdcf20b20e116409c2341cf69065d083053", + "type": "github" }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, + "nix-tools_4": { + "flake": false, "locked": { - "lastModified": 1650936156, - "narHash": "sha256-B58b4OCSc6ohRjGEdbQ78r+TK/OZYsBXION90kfQDC4=", + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", "owner": "input-output-hk", - "repo": "haskell.nix", - "rev": "9a502b8c8aac4d7b8033bc9affb87fd03d4740fc", + "repo": "nix-tools", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "haskell.nix", + "repo": "nix-tools", "type": "github" } }, - "hercules-ci-effects": { + "nix2container": { "inputs": { - "flake-parts": "flake-parts_2", - "nixpkgs": "nixpkgs_70" + "flake-utils": "flake-utils_6", + "nixpkgs": "nixpkgs_17" }, "locked": { - "lastModified": 1699381651, - "narHash": "sha256-mZlQ54xJs3j5+SJrLhzePPMXzS+Czbx7gNyOnOAQrHA=", - "owner": "hercules-ci", - "repo": "hercules-ci-effects", - "rev": "0bd99f5ab7ec7a74c11238bd02bb29e709c14328", + "lastModified": 1671269339, + "narHash": "sha256-KR2SXh4c2Y+bgbCfXjTGJ74O9/u4CAPFA0KYZHhKf5Q=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "6800fff45afecc7e47c334d14cf2b2f4f25601a0", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "hercules-ci-effects", + "owner": "nlewo", + "repo": "nix2container", "type": "github" } }, - "hls-1.10": { - "flake": false, + "nix2container_2": { + "inputs": { + "flake-utils": "flake-utils_7", + "nixpkgs": "nixpkgs_19" + }, "locked": { - "lastModified": 1680000865, - "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "lastModified": 1658567952, + "narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "60bb43d405991c1378baf15a40b5811a53e32ffa", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.10.0.0", - "repo": "haskell-language-server", + "owner": "nlewo", + "repo": "nix2container", "type": "github" } }, - "hls-1.10_2": { - "flake": false, + "nix2container_3": { + "inputs": { + "flake-utils": "flake-utils_10", + "nixpkgs": "nixpkgs_23" + }, "locked": { - "lastModified": 1680000865, - "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "lastModified": 1658567952, + "narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "60bb43d405991c1378baf15a40b5811a53e32ffa", "type": "github" }, "original": { - "owner": "haskell", - "ref": "1.10.0.0", - "repo": "haskell-language-server", + "owner": "nlewo", + "repo": "nix2container", "type": "github" } }, - "hls-2.0": { - "flake": false, + "nix2container_4": { + "inputs": { + "flake-utils": "flake-utils_12", + "nixpkgs": "nixpkgs_27" + }, "locked": { - "lastModified": 1687698105, - "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "783905f211ac63edf982dd1889c671653327e441", + "lastModified": 1671269339, + "narHash": "sha256-KR2SXh4c2Y+bgbCfXjTGJ74O9/u4CAPFA0KYZHhKf5Q=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "6800fff45afecc7e47c334d14cf2b2f4f25601a0", "type": "github" }, "original": { - "owner": "haskell", - "ref": "2.0.0.1", - "repo": "haskell-language-server", + "owner": "nlewo", + "repo": "nix2container", "type": "github" } }, - "hls-2.2": { - "flake": false, + "nix2container_5": { + "inputs": { + "flake-utils": "flake-utils_17", + "nixpkgs": "nixpkgs_32" + }, "locked": { - "lastModified": 1693064058, - "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "lastModified": 1658567952, + "narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "60bb43d405991c1378baf15a40b5811a53e32ffa", "type": "github" }, "original": { - "owner": "haskell", - "ref": "2.2.0.0", - "repo": "haskell-language-server", + "owner": "nlewo", + "repo": "nix2container", "type": "github" } }, - "hls-2.3": { - "flake": false, + "nix2container_6": { + "inputs": { + "flake-utils": "flake-utils_20", + "nixpkgs": "nixpkgs_36" + }, "locked": { - "lastModified": 1695910642, - "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "lastModified": 1712990762, + "narHash": "sha256-hO9W3w7NcnYeX8u8cleHiSpK2YJo7ecarFTUlbybl7k=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "20aad300c925639d5d6cbe30013c8357ce9f2a2e", "type": "github" }, "original": { - "owner": "haskell", - "ref": "2.3.0.0", - "repo": "haskell-language-server", + "owner": "nlewo", + "repo": "nix2container", "type": "github" } }, - "hls-2.4": { - "flake": false, + "nix2container_7": { + "inputs": { + "flake-utils": "flake-utils_45", + "nixpkgs": "nixpkgs_94" + }, "locked": { - "lastModified": 1696939266, - "narHash": "sha256-VOMf5+kyOeOmfXTHlv4LNFJuDGa7G3pDnOxtzYR40IU=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "362fdd1293efb4b82410b676ab1273479f6d17ee", + "lastModified": 1653427219, + "narHash": "sha256-q6MzrIZq1BBFxYN+UQjW60LpQJXV6RIIUmO8gKRyMqg=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "11a0e14c2468720f42ca8dec3b82862abf96c837", "type": "github" }, "original": { - "owner": "haskell", - "ref": "2.4.0.0", - "repo": "haskell-language-server", + "owner": "nlewo", + "ref": "init-nix-db", + "repo": "nix2container", "type": "github" } }, - "hpc-coveralls": { - "flake": false, - "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "nix_10": { + "inputs": { + "lowdown-src": "lowdown-src_10", + "nixpkgs": "nixpkgs_57", + "nixpkgs-regression": "nixpkgs-regression_9" + }, + "locked": { + "lastModified": 1652510778, + "narHash": "sha256-zldZ4SiwkISFXxrbY/UdwooIZ3Z/I6qKxtpc3zD0T/o=", + "owner": "nixos", + "repo": "nix", + "rev": "65cd26eebbbf80eaf0d74092f09b737606cb4b5a", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "nixos", + "ref": "2.8.1", + "repo": "nix", "type": "github" } }, - "hpc-coveralls_2": { - "flake": false, + "nix_11": { + "inputs": { + "lowdown-src": "lowdown-src_11", + "nixpkgs": "nixpkgs_59", + "nixpkgs-regression": "nixpkgs-regression_10" + }, "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1645189081, + "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", + "owner": "nixos", + "repo": "nix", + "rev": "9bc03adbba5334663901c1136203bc07e4776be9", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "nixos", + "repo": "nix", "type": "github" } }, - "hpc-coveralls_3": { - "flake": false, + "nix_12": { + "inputs": { + "lowdown-src": "lowdown-src_12", + "nixpkgs": "nixpkgs_66", + "nixpkgs-regression": "nixpkgs-regression_11" + }, "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1644413094, + "narHash": "sha256-KLGaeSqvhuUFz6DxrB9r3w+lfp9bXIiCT9K1cqg7Ze8=", + "owner": "nixos", + "repo": "nix", + "rev": "52f52319ad21bdbd7a33bb85eccc83756648f110", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "nixos", + "repo": "nix", + "rev": "52f52319ad21bdbd7a33bb85eccc83756648f110", "type": "github" } }, - "hpc-coveralls_4": { - "flake": false, + "nix_13": { + "inputs": { + "lowdown-src": "lowdown-src_13", + "nixpkgs": "nixpkgs_67", + "nixpkgs-regression": "nixpkgs-regression_12" + }, "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1645437800, + "narHash": "sha256-MAMIKi3sIQ0b3jzYyOb5VY29GRgv7JXl1VXoUM9xUZw=", + "owner": "NixOS", + "repo": "nix", + "rev": "f22b9e72f51f97f8f2d334748d3e97123940a146", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "NixOS", + "repo": "nix", + "rev": "f22b9e72f51f97f8f2d334748d3e97123940a146", "type": "github" } }, - "hpc-coveralls_5": { - "flake": false, + "nix_14": { + "inputs": { + "lowdown-src": "lowdown-src_14", + "nixpkgs": "nixpkgs_72", + "nixpkgs-regression": "nixpkgs-regression_13" + }, "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1646164353, + "narHash": "sha256-Nj3ARvplf0Xa+h4F5Cq1r9cc81C2UIpbAKDgJLsDmUc=", + "owner": "kreisys", + "repo": "nix", + "rev": "45677cae8d474270ecd797eb40eb1f8836981604", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "kreisys", + "ref": "goodnix-maybe-dont-functor", + "repo": "nix", "type": "github" } }, - "hpc-coveralls_6": { - "flake": false, + "nix_15": { + "inputs": { + "lowdown-src": "lowdown-src_15", + "nixpkgs": "nixpkgs_74" + }, "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1604400356, + "narHash": "sha256-PX1cSYv0Y6I2tidcuEwJTo8X5vAvf9vjdfHO51LD/J0=", + "owner": "NixOS", + "repo": "nix", + "rev": "cf82e14712b3be881b7c880468cd5486e8934638", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "NixOS", + "repo": "nix", "type": "github" } }, - "hpc-coveralls_7": { - "flake": false, + "nix_16": { + "inputs": { + "lowdown-src": "lowdown-src_16", + "nixpkgs": "nixpkgs_76", + "nixpkgs-regression": "nixpkgs-regression_14" + }, "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1645189081, + "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", + "owner": "nixos", + "repo": "nix", + "rev": "9bc03adbba5334663901c1136203bc07e4776be9", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", + "owner": "nixos", + "repo": "nix", "type": "github" } }, - "hydra": { + "nix_17": { "inputs": { - "nix": "nix", - "nixpkgs": [ - "ctl", - "cardano-node", - "haskellNix", - "hydra", - "nix", - "nixpkgs" - ] + "lowdown-src": "lowdown-src_17", + "nixpkgs": "nixpkgs_88", + "nixpkgs-regression": "nixpkgs-regression_15" }, "locked": { - "lastModified": 1671755331, - "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", "owner": "NixOS", - "repo": "hydra", - "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", + "type": "github" } }, - "hydra_2": { + "nix_18": { "inputs": { - "nix": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "capsules", - "bitte", - "nix" - ], - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "capsules", - "bitte", - "nixpkgs" - ] + "lowdown-src": "lowdown-src_18", + "nixpkgs": "nixpkgs_90", + "nixpkgs-regression": "nixpkgs-regression_16" }, "locked": { - "lastModified": 1631062883, - "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", - "owner": "kreisys", - "repo": "hydra", - "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "hydra-server-includes", - "repo": "hydra", + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", "type": "github" } }, - "hydra_3": { + "nix_19": { "inputs": { - "nix": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "nix" - ], - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "nixpkgs" - ] + "lowdown-src": "lowdown-src_19", + "nixpkgs": "nixpkgs_97", + "nixpkgs-regression": "nixpkgs-regression_17" }, "locked": { - "lastModified": 1631062883, - "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", - "owner": "kreisys", - "repo": "hydra", - "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "hydra-server-includes", - "repo": "hydra", - "type": "github" - } - }, - "hydra_4": { - "inputs": { - "nix": [ - "ctl", - "db-sync", - "cardano-world", - "capsules", - "bitte", - "nix" - ], - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "capsules", - "bitte", - "nixpkgs" - ] + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", + "type": "github" + } + }, + "nix_2": { + "inputs": { + "flake-compat": "flake-compat_3", + "lowdown-src": "lowdown-src_2", + "nixpkgs": "nixpkgs_10", + "nixpkgs-regression": "nixpkgs-regression_2" }, "locked": { - "lastModified": 1631062883, - "narHash": "sha256-JZ6/gjHyX50fHCYpXy/FrX9C0e9k8X9In5Jb/SQYlT8=", - "owner": "kreisys", - "repo": "hydra", - "rev": "785326948be4b1cc2ce77435c806521565e9af45", + "lastModified": 1693573010, + "narHash": "sha256-HBm8mR2skhPtbJ7p+ByrOZjs7SfsfZPwy75MwI1EUmk=", + "owner": "nixos", + "repo": "nix", + "rev": "5568ca5ff130a8a0bc3db5878432eb527c74dd60", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "hydra-server-includes", - "repo": "hydra", + "owner": "nixos", + "ref": "2.17-maintenance", + "repo": "nix", "type": "github" } }, - "hydra_5": { + "nix_20": { "inputs": { - "nix": "nix_12", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "cardano-wallet", - "haskellNix", - "hydra", - "nix", - "nixpkgs" - ] + "lowdown-src": "lowdown-src_20", + "nixpkgs": "nixpkgs_98", + "nixpkgs-regression": "nixpkgs-regression_18" }, "locked": { - "lastModified": 1646878427, - "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", "owner": "NixOS", - "repo": "hydra", - "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" } }, - "hydra_6": { + "nix_3": { "inputs": { - "nix": "nix_13", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "haskell-nix", - "hydra", - "nix", - "nixpkgs" - ] + "lowdown-src": "lowdown-src_3", + "nixpkgs": "nixpkgs_14", + "nixpkgs-regression": "nixpkgs-regression_3" }, "locked": { - "lastModified": 1646878427, - "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", "owner": "NixOS", - "repo": "hydra", - "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" } }, - "hydra_7": { + "nix_4": { "inputs": { - "nix": "nix_14", - "nixpkgs": [ - "ctl", - "db-sync", - "haskellNix", - "hydra", - "nix", - "nixpkgs" - ] + "lowdown-src": "lowdown-src_4", + "nixpkgs": "nixpkgs_16", + "nixpkgs-regression": "nixpkgs-regression_4" }, "locked": { - "lastModified": 1646878427, - "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", "owner": "NixOS", - "repo": "hydra", - "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" } }, - "hydra_8": { + "nix_5": { "inputs": { - "nix": "nix_15", - "nixpkgs": [ - "ctl", - "haskell-nix", - "hydra", - "nix", - "nixpkgs" - ] + "lowdown-src": "lowdown-src_5", + "nixpkgs": "nixpkgs_26", + "nixpkgs-regression": "nixpkgs-regression_5" }, "locked": { - "lastModified": 1671755331, - "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", "owner": "NixOS", - "repo": "hydra", - "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" } }, - "hydra_9": { + "nix_6": { "inputs": { - "nix": "nix_16", - "nixpkgs": [ - "ctl", - "kupo-nixos", - "haskell-nix", - "hydra", - "nix", - "nixpkgs" - ] + "lowdown-src": "lowdown-src_6", + "nixpkgs": "nixpkgs_35", + "nixpkgs-regression": "nixpkgs-regression_6" }, "locked": { - "lastModified": 1646878427, - "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", "owner": "NixOS", - "repo": "hydra", - "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", "type": "github" }, "original": { - "id": "hydra", - "type": "indirect" + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" } }, - "incl": { + "nix_7": { "inputs": { - "nixlib": [ - "ctl", - "cardano-node", - "tullia", - "std", - "nixpkgs" - ] + "lowdown-src": "lowdown-src_7", + "nixpkgs": "nixpkgs_43", + "nixpkgs-regression": "nixpkgs-regression_7" }, "locked": { - "lastModified": 1669263024, - "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", - "owner": "divnix", - "repo": "incl", - "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", + "lastModified": 1646164353, + "narHash": "sha256-Nj3ARvplf0Xa+h4F5Cq1r9cc81C2UIpbAKDgJLsDmUc=", + "owner": "kreisys", + "repo": "nix", + "rev": "45677cae8d474270ecd797eb40eb1f8836981604", "type": "github" }, "original": { - "owner": "divnix", - "repo": "incl", + "owner": "kreisys", + "ref": "goodnix-maybe-dont-functor", + "repo": "nix", "type": "github" } }, - "inclusive": { + "nix_8": { "inputs": { - "stdlib": "stdlib" + "lowdown-src": "lowdown-src_8", + "nixpkgs": "nixpkgs_45" }, "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1604400356, + "narHash": "sha256-PX1cSYv0Y6I2tidcuEwJTo8X5vAvf9vjdfHO51LD/J0=", + "owner": "NixOS", + "repo": "nix", + "rev": "cf82e14712b3be881b7c880468cd5486e8934638", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "NixOS", + "repo": "nix", "type": "github" } }, - "inclusive_10": { + "nix_9": { "inputs": { - "stdlib": "stdlib_10" + "lowdown-src": "lowdown-src_9", + "nixpkgs": "nixpkgs_47", + "nixpkgs-regression": "nixpkgs-regression_8" }, "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1645189081, + "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", + "owner": "nixos", + "repo": "nix", + "rev": "9bc03adbba5334663901c1136203bc07e4776be9", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nixos", + "repo": "nix", "type": "github" } }, - "inclusive_11": { + "nixago": { "inputs": { - "stdlib": "stdlib_11" + "flake-utils": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "flake-utils" + ], + "nixago-exts": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "blank" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1661824785, + "narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=", + "owner": "nix-community", + "repo": "nixago", + "rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nix-community", + "repo": "nixago", "type": "github" } }, - "inclusive_2": { - "inputs": { - "stdlib": "stdlib_2" - }, + "nixago-exts": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nix-community", + "repo": "nixago-extensions", "type": "github" } }, - "inclusive_3": { - "inputs": { - "stdlib": "stdlib_3" - }, + "nixago-exts_2": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1625557891, + "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", + "owner": "divnix", + "repo": "blank", + "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nix-community", + "repo": "nixago-extensions", "type": "github" } }, - "inclusive_4": { + "nixago_2": { "inputs": { - "stdlib": "stdlib_4" + "flake-utils": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "flake-utils" + ], + "nixago-exts": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1676075813, + "narHash": "sha256-X/aIT8Qc8UCqnxJvaZykx3CJ0ZnDFvO+dqp/7fglZWo=", + "owner": "nix-community", + "repo": "nixago", + "rev": "9cab4dde31ec2f2c05d702ea8648ce580664e906", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nix-community", + "repo": "nixago", "type": "github" } }, - "inclusive_5": { + "nixago_3": { "inputs": { - "stdlib": "stdlib_5" + "flake-utils": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "flake-utils" + ], + "nixago-exts": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1683210100, + "narHash": "sha256-bhGDOlkWtlhVECpoOog4fWiFJmLCpVEg09a40aTjCbw=", + "owner": "nix-community", + "repo": "nixago", + "rev": "1da60ad9412135f9ed7a004669fdcf3d378ec630", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nix-community", + "repo": "nixago", "type": "github" } }, - "inclusive_6": { + "nixago_4": { "inputs": { - "stdlib": "stdlib_6" + "flake-utils": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "flake-utils" + ], + "nixago-exts": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "nixpkgs": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1661824785, + "narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=", + "owner": "nix-community", + "repo": "nixago", + "rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nix-community", + "repo": "nixago", "type": "github" } }, - "inclusive_7": { + "nixago_5": { "inputs": { - "stdlib": "stdlib_7" + "flake-utils": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "std", + "flake-utils" + ], + "nixago-exts": "nixago-exts", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "bitte", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1659153038, + "narHash": "sha256-g4npRU8YBR7CAqMF0SyXtkHnoY9q+NcxvZwcc6UvLBc=", + "owner": "nix-community", + "repo": "nixago", + "rev": "608abdd0fe6729d1f7244e03f1a7f8a5d6408898", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nix-community", + "repo": "nixago", "type": "github" } }, - "inclusive_8": { + "nixago_6": { "inputs": { - "stdlib": "stdlib_8" + "flake-utils": [ + "ctl", + "db-sync", + "cardano-world", + "std", + "flake-utils" + ], + "nixago-exts": "nixago-exts_2", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "std", + "nixpkgs" + ] }, "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1659153038, + "narHash": "sha256-g4npRU8YBR7CAqMF0SyXtkHnoY9q+NcxvZwcc6UvLBc=", + "owner": "nix-community", + "repo": "nixago", + "rev": "608abdd0fe6729d1f7244e03f1a7f8a5d6408898", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nix-community", + "repo": "nixago", "type": "github" } }, - "inclusive_9": { - "inputs": { - "stdlib": "stdlib_9" - }, + "nixlib": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1652576347, + "narHash": "sha256-52Wu7hkcIRcS4UenSSrt01J2sAbbQ6YqxZIDpuEPL/c=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "bdf553800c9c34ed00641785b02038f67f44d671", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "nix-community", + "repo": "nixpkgs.lib", "type": "github" } }, - "iogo": { - "inputs": { - "devshell": "devshell_4", - "inclusive": "inclusive_3", - "nixpkgs": "nixpkgs_22", - "utils": "utils_8" - }, + "nixlib_2": { "locked": { - "lastModified": 1652212694, - "narHash": "sha256-baAY5wKzccNsm7OCEYuySrkXRmlshokCHQjs4EdYShM=", - "owner": "input-output-hk", - "repo": "bitte-iogo", - "rev": "e465975aa368b2d919e865f71eeed02828e55471", + "lastModified": 1644107864, + "narHash": "sha256-Wrbt6Gs+hjXD3HUICPBJHKnHEUqiyx8rzHCgvqC1Bok=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "58eabcf65e7dba189eb0013f86831c159e3b2be6", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "bitte-iogo", + "owner": "nix-community", + "repo": "nixpkgs.lib", "type": "github" } }, - "iogo_2": { - "inputs": { - "devshell": "devshell_14", - "inclusive": "inclusive_11", - "nixpkgs": "nixpkgs_51", - "utils": "utils_22" - }, + "nixlib_3": { "locked": { - "lastModified": 1658302707, - "narHash": "sha256-E0FA1CEMQlfAsmtLBRoQE7IY4ItKlBdxZ44YX0tK5Hg=", - "owner": "input-output-hk", - "repo": "bitte-iogo", - "rev": "8751660009202bc95ea3a29e304c393c140a4231", + "lastModified": 1656809537, + "narHash": "sha256-pwXBYG3ThN4ccJjvcdNdonQ8Wyv0y/iYdnuesiFUY1U=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "40e271f69106323734b55e2ba74f13bebde324c0", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "bitte-iogo", + "owner": "nix-community", + "repo": "nixpkgs.lib", "type": "github" } }, - "iohk-nix": { - "inputs": { - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "nixpkgs" - ] - }, + "nixpkgs": { "locked": { - "lastModified": 1658222743, - "narHash": "sha256-yFH01psqx30y5Ws4dBElLkxYpIxxqZx4G+jCVhsXpnA=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "9a604d01bd4420ab7f396f14d1947fbe2ce7db8b", + "lastModified": 1687420147, + "narHash": "sha256-NILbmZVsoP2Aw0OAIXdbYXrWc/qggIDDyIwZ01yUx+Q=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d449a456ba7d81038fc9ec9141eae7ee3aaf2982", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "NixOS", + "ref": "release-23.05", + "repo": "nixpkgs", "type": "github" } }, - "iohk-nix_2": { - "inputs": { - "blst": "blst_2", - "nixpkgs": [ - "ctl", - "nixpkgs" - ], - "secp256k1": "secp256k1_2", - "sodium": "sodium_2" - }, + "nixpkgs-2003": { "locked": { - "lastModified": 1702362799, - "narHash": "sha256-cU8cZXNuo5GRwrSvWqdaqoW5tJ2HWwDEOvWwIVPDPmo=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "b426fb9e0b109a9d1dd2e1476f9e0bd8bb715142", + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", "type": "github" } }, - "iohk-nix_3": { - "inputs": { - "nixpkgs": [ - "ctl", - "kupo-nixos", - "haskell-nix", - "nixpkgs" - ] - }, + "nixpkgs-2003_10": { "locked": { - "lastModified": 1653579289, - "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", "type": "github" } }, - "iohkNix": { - "inputs": { - "blst": "blst", - "nixpkgs": [ - "ctl", - "cardano-node", - "nixpkgs" - ], - "secp256k1": "secp256k1", - "sodium": "sodium" - }, + "nixpkgs-2003_2": { "locked": { - "lastModified": 1684223806, - "narHash": "sha256-IyLoP+zhuyygLtr83XXsrvKyqqLQ8FHXTiySFf4FJOI=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "86421fdd89b3af43fa716ccd07638f96c6ecd1e4", + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", "type": "github" } }, - "iohkNix_2": { - "inputs": { - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "cardano-wallet", - "nixpkgs" - ] - }, + "nixpkgs-2003_3": { "locked": { - "lastModified": 1653579289, - "narHash": "sha256-wveDdPsgB/3nAGAdFaxrcgLEpdi0aJ5kEVNtI+YqVfo=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "edb2d2df2ebe42bbdf03a0711115cf6213c9d366", + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", "type": "github" } }, - "iohkNix_3": { - "inputs": { - "nixpkgs": [ - "ctl", - "db-sync", - "nixpkgs" - ] - }, + "nixpkgs-2003_4": { "locked": { - "lastModified": 1667394105, - "narHash": "sha256-YhS7zGd6jK/QM/+wWyj0zUBZmE3HOXAL/kpJptGYIWg=", - "owner": "input-output-hk", - "repo": "iohk-nix", - "rev": "7fc7625a9ab2ba137bc70ddbc89a13d3fdb78c8b", + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "iohk-nix", + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", "type": "github" } }, - "iserv-proxy": { - "flake": false, + "nixpkgs-2003_5": { "locked": { - "lastModified": 1670983692, - "narHash": "sha256-avLo34JnI9HNyOuauK5R69usJm+GfW3MlyGlYxZhTgY=", - "ref": "hkm/remote-iserv", - "rev": "50d0abb3317ac439a4e7495b185a64af9b7b9300", - "revCount": 10, - "type": "git", - "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" }, "original": { - "ref": "hkm/remote-iserv", - "type": "git", - "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" } }, - "iserv-proxy_2": { - "flake": false, + "nixpkgs-2003_6": { "locked": { - "lastModified": 1691634696, - "narHash": "sha256-MZH2NznKC/gbgBu8NgIibtSUZeJ00HTLJ0PlWKCBHb0=", - "ref": "hkm/remote-iserv", - "rev": "43a979272d9addc29fbffc2e8542c5d96e993d73", - "revCount": 14, - "type": "git", - "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" }, "original": { - "ref": "hkm/remote-iserv", - "type": "git", - "url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git" + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" } }, - "kupo": { - "flake": false, + "nixpkgs-2003_7": { "locked": { - "lastModified": 1668678914, - "narHash": "sha256-XsbAFyUPmevGuoShEFlOVHt/7fFIpyCQuhulIrNzv80=", - "owner": "CardanoSolutions", - "repo": "kupo", - "rev": "c9bc18d99f9e8af1840a265907db82b180d5a4d8", + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", "type": "github" }, "original": { - "owner": "CardanoSolutions", - "ref": "v2.2.0", - "repo": "kupo", + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", "type": "github" } }, - "kupo-nixos": { - "inputs": { - "haskell-nix": "haskell-nix_4", - "iohk-nix": "iohk-nix_3", - "kupo": [ - "ctl", - "kupo" - ], - "nixpkgs": [ - "ctl", - "kupo-nixos", - "haskell-nix", - "nixpkgs" - ] + "nixpkgs-2003_8": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003_9": { "locked": { - "lastModified": 1672905539, - "narHash": "sha256-B4vryG94L7WWn/tuIQdtg9eZHAH+FaFzv35Mancd2l8=", - "owner": "mlabs-haskell", - "repo": "kupo-nixos", - "rev": "6f89cbcc359893a2aea14dd380f9a45e04c6aa67", + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "kupo-nixos", - "rev": "6f89cbcc359893a2aea14dd380f9a45e04c6aa67", + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src": { - "flake": false, + "nixpkgs-2105": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_10": { - "flake": false, + "nixpkgs-2105_10": { "locked": { - "lastModified": 1598695561, - "narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f", + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_11": { - "flake": false, + "nixpkgs-2105_2": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_12": { - "flake": false, + "nixpkgs-2105_3": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_13": { - "flake": false, + "nixpkgs-2105_4": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_14": { - "flake": false, + "nixpkgs-2105_5": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_15": { - "flake": false, + "nixpkgs-2105_6": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1642244250, + "narHash": "sha256-vWpUEqQdVP4srj+/YLJRTN9vjpTs4je0cdWKXPbDItc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0fd9ee1aa36ce865ad273f4f07fdc093adeb5c00", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_16": { - "flake": false, + "nixpkgs-2105_7": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_2": { - "flake": false, + "nixpkgs-2105_8": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1655034179, + "narHash": "sha256-rf1/7AbzuYDw6+8Xvvf3PtEOygymLBrFsFxvext5ZjI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "046ee4af7a9f016a364f8f78eeaa356ba524ac31", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_3": { - "flake": false, + "nixpkgs-2105_9": { "locked": { - "lastModified": 1598695561, - "narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f", + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_4": { - "flake": false, + "nixpkgs-2111": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_5": { - "flake": false, + "nixpkgs-2111_10": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_6": { - "flake": false, + "nixpkgs-2111_2": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_7": { - "flake": false, + "nixpkgs-2111_3": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_8": { - "flake": false, + "nixpkgs-2111_4": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "lowdown-src_9": { - "flake": false, + "nixpkgs-2111_5": { "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "mdbook-kroki-preprocessor": { - "flake": false, + "nixpkgs-2111_6": { "locked": { - "lastModified": 1655670640, - "narHash": "sha256-JjqdxftHBjABTkOpFl3cWUJtc/KGwkQ3NRWGLjH2oUs=", - "owner": "JoelCourtney", - "repo": "mdbook-kroki-preprocessor", - "rev": "bb6e607437ecc3f22fd9036acee6b797a5b45dbc", + "lastModified": 1644510859, + "narHash": "sha256-xjpVvL5ecbyi0vxtVl/Fh9bwGlMbw3S06zE5nUzFB8A=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0d1d5d7e3679fec9d07f2eb804d9f9fdb98378d3", "type": "github" }, "original": { - "owner": "JoelCourtney", - "repo": "mdbook-kroki-preprocessor", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "mdbook-kroki-preprocessor_2": { - "flake": false, + "nixpkgs-2111_7": { "locked": { - "lastModified": 1655670640, - "narHash": "sha256-JjqdxftHBjABTkOpFl3cWUJtc/KGwkQ3NRWGLjH2oUs=", - "owner": "JoelCourtney", - "repo": "mdbook-kroki-preprocessor", - "rev": "bb6e607437ecc3f22fd9036acee6b797a5b45dbc", + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", "type": "github" }, "original": { - "owner": "JoelCourtney", - "repo": "mdbook-kroki-preprocessor", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "n2c": { - "inputs": { - "flake-utils": [ - "ctl", - "cardano-node", - "tullia", - "std", - "flake-utils" - ], - "nixpkgs": [ - "ctl", - "cardano-node", - "tullia", - "std", - "nixpkgs" - ] - }, + "nixpkgs-2111_8": { "locked": { - "lastModified": 1665039323, - "narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a", + "lastModified": 1656782578, + "narHash": "sha256-1eMCBEqJplPotTo/SZ/t5HU6Sf2I8qKlZi9MX7jv9fw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "573603b7fdb9feb0eb8efc16ee18a015c667ab1b", "type": "github" }, "original": { - "owner": "nlewo", - "repo": "nix2container", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "n2c_2": { - "inputs": { - "flake-utils": "flake-utils_11", - "nixpkgs": "nixpkgs_27" - }, + "nixpkgs-2111_9": { "locked": { - "lastModified": 1650568002, - "narHash": "sha256-CciO5C3k/a7sbA+lW4jeiU6WGletujMjWcRzc1513tI=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "2cd391fc65847ea54e3657a491c379854b556262", + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", "type": "github" }, "original": { - "owner": "nlewo", - "repo": "nix2container", + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "n2c_3": { - "inputs": { - "flake-utils": "flake-utils_28", - "nixpkgs": "nixpkgs_62" - }, + "nixpkgs-2205": { "locked": { - "lastModified": 1655533513, - "narHash": "sha256-MAqvv2AZbyNYGJMpV5l9ydN7k66jDErFpaKOvZ1Y7f8=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "2d47dbe633a059d75c7878f554420158712481cb", + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", "type": "github" }, "original": { - "owner": "nlewo", - "repo": "nix2container", + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix": { - "inputs": { - "lowdown-src": "lowdown-src", - "nixpkgs": "nixpkgs_3", - "nixpkgs-regression": "nixpkgs-regression" - }, + "nixpkgs-2205_2": { "locked": { - "lastModified": 1661606874, - "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", "owner": "NixOS", - "repo": "nix", - "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.11.0", - "repo": "nix", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix-cache-proxy": { - "inputs": { - "devshell": "devshell_11", - "inclusive": [ - "ctl", - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "inclusive" - ], - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte-cells", - "cicero", - "nixpkgs" - ], - "utils": "utils_15" - }, + "nixpkgs-2205_3": { "locked": { - "lastModified": 1644317729, - "narHash": "sha256-R9R1XHv69VvZ/c7lXYs18PHcnEBXS+hDfhjdkZ96lgw=", - "owner": "input-output-hk", - "repo": "nix-cache-proxy", - "rev": "378617d6b9865be96f7dfa16e0ce3f329da844ec", + "lastModified": 1682600000, + "narHash": "sha256-ha4BehR1dh8EnXSoE1m/wyyYVvHI9txjW4w5/oxsW5Y=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "50fc86b75d2744e1ab3837ef74b53f103a9b55a0", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-cache-proxy", + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix-inclusive": { - "inputs": { - "stdlib": "stdlib_12" - }, + "nixpkgs-2205_4": { "locked": { - "lastModified": 1628098927, - "narHash": "sha256-Ft4sdf7VPL8MQtu18AAPiN2s5pUsbv+3RxqzJSa/yzg=", - "owner": "input-output-hk", - "repo": "nix-inclusive", - "rev": "13123eb7a8c3359738a4756b8d645729e8655b27", + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-inclusive", + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix-nomad": { - "inputs": { - "flake-compat": "flake-compat_3", - "flake-utils": [ - "ctl", - "cardano-node", - "tullia", - "nix2container", - "flake-utils" - ], - "gomod2nix": "gomod2nix", - "nixpkgs": [ - "ctl", - "cardano-node", - "tullia", - "nixpkgs" - ], - "nixpkgs-lib": [ - "ctl", - "cardano-node", - "tullia", - "nixpkgs" - ] - }, + "nixpkgs-2205_5": { "locked": { - "lastModified": 1658277770, - "narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=", - "owner": "tristanpemble", - "repo": "nix-nomad", - "rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70", + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", "type": "github" }, "original": { - "owner": "tristanpemble", - "repo": "nix-nomad", + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix-tools": { - "flake": false, + "nixpkgs-2205_6": { "locked": { - "lastModified": 1644395812, - "narHash": "sha256-BVFk/BEsTLq5MMZvdy3ZYHKfaS3dHrsKh4+tb5t5b58=", - "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "d847c63b99bbec78bf83be2a61dc9f09b8a9ccc1", + "lastModified": 1657876628, + "narHash": "sha256-URmf0O2cQ/3heg2DJOeLyU/JmfVMqG4X5t9crQXMaeY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "549d82bdd40f760a438c3c3497c1c61160f3de55", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-tools", + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix-tools_2": { - "flake": false, + "nixpkgs-2205_7": { "locked": { - "lastModified": 1649424170, - "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", - "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-tools", + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix-tools_3": { - "flake": false, + "nixpkgs-2211": { "locked": { - "lastModified": 1658968505, - "narHash": "sha256-UnbQ/Ig/23e9hUdDOBwYHwHgHmQawZ2uazpJ8DLIJgE=", - "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "8a754bdcf20b20e116409c2341cf69065d083053", + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-tools", + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix-tools_4": { - "flake": false, + "nixpkgs-2211_2": { "locked": { - "lastModified": 1649424170, - "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", - "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-tools", + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix-tools_5": { - "flake": false, + "nixpkgs-2211_3": { "locked": { - "lastModified": 1649424170, - "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", - "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", + "lastModified": 1682682915, + "narHash": "sha256-haR0u/j/nUvlMloYlaOYq1FMXTvkNHw+wGxc+0qXisM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "09f1b33fcc0f59263137e23e935c1bb03ec920e4", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-tools", + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix2container": { - "inputs": { - "flake-utils": "flake-utils_3", - "nixpkgs": "nixpkgs_4" - }, + "nixpkgs-2211_4": { "locked": { - "lastModified": 1671269339, - "narHash": "sha256-KR2SXh4c2Y+bgbCfXjTGJ74O9/u4CAPFA0KYZHhKf5Q=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "6800fff45afecc7e47c334d14cf2b2f4f25601a0", + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", "type": "github" }, "original": { - "owner": "nlewo", - "repo": "nix2container", + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix2container_2": { - "inputs": { - "flake-utils": "flake-utils_4", - "nixpkgs": "nixpkgs_6" - }, + "nixpkgs-2211_5": { "locked": { - "lastModified": 1658567952, - "narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "60bb43d405991c1378baf15a40b5811a53e32ffa", + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", "type": "github" }, "original": { - "owner": "nlewo", - "repo": "nix2container", + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix2container_3": { - "inputs": { - "flake-utils": "flake-utils_30", - "nixpkgs": "nixpkgs_65" - }, + "nixpkgs-2211_6": { "locked": { - "lastModified": 1653427219, - "narHash": "sha256-q6MzrIZq1BBFxYN+UQjW60LpQJXV6RIIUmO8gKRyMqg=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "11a0e14c2468720f42ca8dec3b82862abf96c837", + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", "type": "github" }, "original": { - "owner": "nlewo", - "ref": "init-nix-db", - "repo": "nix2container", + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_10": { - "inputs": { - "lowdown-src": "lowdown-src_10", - "nixpkgs": "nixpkgs_45" - }, + "nixpkgs-2305": { "locked": { - "lastModified": 1604400356, - "narHash": "sha256-PX1cSYv0Y6I2tidcuEwJTo8X5vAvf9vjdfHO51LD/J0=", + "lastModified": 1690680713, + "narHash": "sha256-NXCWA8N+GfSQyoN7ZNiOgq/nDJKOp5/BHEpiZP8sUZw=", "owner": "NixOS", - "repo": "nix", - "rev": "cf82e14712b3be881b7c880468cd5486e8934638", + "repo": "nixpkgs", + "rev": "b81af66deb21f73a70c67e5ea189568af53b1e8c", "type": "github" }, "original": { "owner": "NixOS", - "repo": "nix", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_11": { - "inputs": { - "lowdown-src": "lowdown-src_11", - "nixpkgs": "nixpkgs_47", - "nixpkgs-regression": "nixpkgs-regression_9" - }, + "nixpkgs-2305_2": { "locked": { - "lastModified": 1645189081, - "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", - "owner": "nixos", - "repo": "nix", - "rev": "9bc03adbba5334663901c1136203bc07e4776be9", + "lastModified": 1695416179, + "narHash": "sha256-610o1+pwbSu+QuF3GE0NU5xQdTHM3t9wyYhB9l94Cd8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "715d72e967ec1dd5ecc71290ee072bcaf5181ed6", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nix", + "owner": "NixOS", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_12": { - "inputs": { - "lowdown-src": "lowdown-src_12", - "nixpkgs": "nixpkgs_59", - "nixpkgs-regression": "nixpkgs-regression_10" - }, + "nixpkgs-2305_3": { "locked": { - "lastModified": 1643066034, - "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "lastModified": 1695416179, + "narHash": "sha256-610o1+pwbSu+QuF3GE0NU5xQdTHM3t9wyYhB9l94Cd8=", "owner": "NixOS", - "repo": "nix", - "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "repo": "nixpkgs", + "rev": "715d72e967ec1dd5ecc71290ee072bcaf5181ed6", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.6.0", - "repo": "nix", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_13": { - "inputs": { - "lowdown-src": "lowdown-src_13", - "nixpkgs": "nixpkgs_61", - "nixpkgs-regression": "nixpkgs-regression_11" - }, + "nixpkgs-2305_4": { "locked": { - "lastModified": 1643066034, - "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "lastModified": 1701362232, + "narHash": "sha256-GVdzxL0lhEadqs3hfRLuj+L1OJFGiL/L7gCcelgBlsw=", "owner": "NixOS", - "repo": "nix", - "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "repo": "nixpkgs", + "rev": "d2332963662edffacfddfad59ff4f709dde80ffe", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.6.0", - "repo": "nix", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_14": { - "inputs": { - "lowdown-src": "lowdown-src_14", - "nixpkgs": "nixpkgs_68", - "nixpkgs-regression": "nixpkgs-regression_12" - }, + "nixpkgs-2305_5": { "locked": { - "lastModified": 1643066034, - "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "lastModified": 1705033721, + "narHash": "sha256-K5eJHmL1/kev6WuqyqqbS1cdNnSidIZ3jeqJ7GbrYnQ=", "owner": "NixOS", - "repo": "nix", - "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "repo": "nixpkgs", + "rev": "a1982c92d8980a0114372973cbdfe0a307f1bdea", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.6.0", - "repo": "nix", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_15": { - "inputs": { - "lowdown-src": "lowdown-src_15", - "nixpkgs": "nixpkgs_69", - "nixpkgs-regression": "nixpkgs-regression_13" - }, + "nixpkgs-2311": { "locked": { - "lastModified": 1661606874, - "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "lastModified": 1701386440, + "narHash": "sha256-xI0uQ9E7JbmEy/v8kR9ZQan6389rHug+zOtZeZFiDJk=", "owner": "NixOS", - "repo": "nix", - "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "repo": "nixpkgs", + "rev": "293822e55ec1872f715a66d0eda9e592dc14419f", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.11.0", - "repo": "nix", + "ref": "nixpkgs-23.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_16": { - "inputs": { - "lowdown-src": "lowdown-src_16", - "nixpkgs": "nixpkgs_71", - "nixpkgs-regression": "nixpkgs-regression_14" - }, + "nixpkgs-2311_2": { "locked": { - "lastModified": 1643066034, - "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "lastModified": 1719957072, + "narHash": "sha256-gvFhEf5nszouwLAkT9nWsDzocUTqLWHuL++dvNjMp9I=", "owner": "NixOS", - "repo": "nix", - "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", + "repo": "nixpkgs", + "rev": "7144d6241f02d171d25fba3edeaf15e0f2592105", "type": "github" }, "original": { "owner": "NixOS", - "ref": "2.6.0", - "repo": "nix", + "ref": "nixpkgs-23.11-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_2": { - "inputs": { - "lowdown-src": "lowdown-src_2", - "nixpkgs": "nixpkgs_14", - "nixpkgs-regression": "nixpkgs-regression_2" - }, + "nixpkgs-2405": { "locked": { - "lastModified": 1646164353, - "narHash": "sha256-Nj3ARvplf0Xa+h4F5Cq1r9cc81C2UIpbAKDgJLsDmUc=", - "owner": "kreisys", - "repo": "nix", - "rev": "45677cae8d474270ecd797eb40eb1f8836981604", + "lastModified": 1720122915, + "narHash": "sha256-Nby8WWxj0elBu1xuRaUcRjPi/rU3xVbkAt2kj4QwX2U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "835cf2d3f37989c5db6585a28de967a667a75fb1", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "goodnix-maybe-dont-functor", - "repo": "nix", + "owner": "NixOS", + "ref": "nixpkgs-24.05-darwin", + "repo": "nixpkgs", "type": "github" } }, - "nix_3": { - "inputs": { - "lowdown-src": "lowdown-src_3", - "nixpkgs": "nixpkgs_16" - }, + "nixpkgs-arion": { "locked": { - "lastModified": 1604400356, - "narHash": "sha256-PX1cSYv0Y6I2tidcuEwJTo8X5vAvf9vjdfHO51LD/J0=", + "lastModified": 1721996520, + "narHash": "sha256-R/d5Af+YT2i6/QlGKQ4mZt/kziI1D6KTXumRWkbX/+s=", "owner": "NixOS", - "repo": "nix", - "rev": "cf82e14712b3be881b7c880468cd5486e8934638", + "repo": "nixpkgs", + "rev": "cd3ac4d9337a8be63e48a38583c5978627f4daeb", "type": "github" }, "original": { "owner": "NixOS", - "repo": "nix", + "repo": "nixpkgs", "type": "github" } }, - "nix_4": { - "inputs": { - "lowdown-src": "lowdown-src_4", - "nixpkgs": "nixpkgs_18", - "nixpkgs-regression": "nixpkgs-regression_3" - }, + "nixpkgs-docker": { "locked": { - "lastModified": 1645189081, - "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", + "lastModified": 1652739558, + "narHash": "sha256-znGkjGugajqF/sFS+H4+ENmGTaVPFE0uu1JjQZJLEaQ=", "owner": "nixos", - "repo": "nix", - "rev": "9bc03adbba5334663901c1136203bc07e4776be9", + "repo": "nixpkgs", + "rev": "ff691ed9ba21528c1b4e034f36a04027e4522c58", "type": "github" }, "original": { "owner": "nixos", - "repo": "nix", + "repo": "nixpkgs", + "rev": "ff691ed9ba21528c1b4e034f36a04027e4522c58", "type": "github" } }, - "nix_5": { - "inputs": { - "lowdown-src": "lowdown-src_5", - "nixpkgs": "nixpkgs_28", - "nixpkgs-regression": "nixpkgs-regression_4" - }, + "nixpkgs-lib": { "locked": { - "lastModified": 1652510778, - "narHash": "sha256-zldZ4SiwkISFXxrbY/UdwooIZ3Z/I6qKxtpc3zD0T/o=", - "owner": "nixos", - "repo": "nix", - "rev": "65cd26eebbbf80eaf0d74092f09b737606cb4b5a", + "dir": "lib", + "lastModified": 1671359686, + "narHash": "sha256-3MpC6yZo+Xn9cPordGz2/ii6IJpP2n8LE8e/ebUXLrs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "04f574a1c0fde90b51bf68198e2297ca4e7cccf4", "type": "github" }, "original": { - "owner": "nixos", - "ref": "2.8.1", - "repo": "nix", + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "nix_6": { - "inputs": { - "lowdown-src": "lowdown-src_6", - "nixpkgs": "nixpkgs_30", - "nixpkgs-regression": "nixpkgs-regression_5" - }, + "nixpkgs-lib_2": { "locked": { - "lastModified": 1645189081, - "narHash": "sha256-yZA+07JTG9Z610DceiYyzm+C08yHhcIgfl/Cp7lY3ho=", - "owner": "nixos", - "repo": "nix", - "rev": "9bc03adbba5334663901c1136203bc07e4776be9", + "dir": "lib", + "lastModified": 1682879489, + "narHash": "sha256-sASwo8gBt7JDnOOstnps90K1wxmVfyhsTPPNTGBPjjg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nix", + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "nix_7": { - "inputs": { - "lowdown-src": "lowdown-src_7", - "nixpkgs": "nixpkgs_37", - "nixpkgs-regression": "nixpkgs-regression_6" - }, + "nixpkgs-lib_3": { "locked": { - "lastModified": 1644413094, - "narHash": "sha256-KLGaeSqvhuUFz6DxrB9r3w+lfp9bXIiCT9K1cqg7Ze8=", - "owner": "nixos", - "repo": "nix", - "rev": "52f52319ad21bdbd7a33bb85eccc83756648f110", + "dir": "lib", + "lastModified": 1690881714, + "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9e1960bc196baf6881340d53dccb203a951745a2", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nix", - "rev": "52f52319ad21bdbd7a33bb85eccc83756648f110", + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "nix_8": { - "inputs": { - "lowdown-src": "lowdown-src_8", - "nixpkgs": "nixpkgs_38", - "nixpkgs-regression": "nixpkgs-regression_7" - }, + "nixpkgs-lib_4": { "locked": { - "lastModified": 1645437800, - "narHash": "sha256-MAMIKi3sIQ0b3jzYyOb5VY29GRgv7JXl1VXoUM9xUZw=", + "dir": "lib", + "lastModified": 1690881714, + "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", "owner": "NixOS", - "repo": "nix", - "rev": "f22b9e72f51f97f8f2d334748d3e97123940a146", + "repo": "nixpkgs", + "rev": "9e1960bc196baf6881340d53dccb203a951745a2", "type": "github" }, "original": { + "dir": "lib", "owner": "NixOS", - "repo": "nix", - "rev": "f22b9e72f51f97f8f2d334748d3e97123940a146", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "nix_9": { - "inputs": { - "lowdown-src": "lowdown-src_9", - "nixpkgs": "nixpkgs_43", - "nixpkgs-regression": "nixpkgs-regression_8" - }, + "nixpkgs-lib_5": { "locked": { - "lastModified": 1646164353, - "narHash": "sha256-Nj3ARvplf0Xa+h4F5Cq1r9cc81C2UIpbAKDgJLsDmUc=", - "owner": "kreisys", - "repo": "nix", - "rev": "45677cae8d474270ecd797eb40eb1f8836981604", + "dir": "lib", + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", "type": "github" }, "original": { - "owner": "kreisys", - "ref": "goodnix-maybe-dont-functor", - "repo": "nix", + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "nixago": { - "inputs": { - "flake-utils": [ - "ctl", - "cardano-node", - "tullia", - "std", - "flake-utils" - ], - "nixago-exts": [ - "ctl", - "cardano-node", - "tullia", - "std", - "blank" - ], - "nixpkgs": [ - "ctl", - "cardano-node", - "tullia", - "std", - "nixpkgs" - ] - }, + "nixpkgs-regression": { "locked": { - "lastModified": 1661824785, - "narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=", - "owner": "nix-community", - "repo": "nixago", - "rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixago-exts": { + "nixpkgs-regression_10": { "locked": { - "lastModified": 1625557891, - "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", - "owner": "divnix", - "repo": "blank", - "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago-extensions", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixago-exts_2": { + "nixpkgs-regression_11": { "locked": { - "lastModified": 1625557891, - "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", - "owner": "divnix", - "repo": "blank", - "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago-extensions", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixago_2": { - "inputs": { - "flake-utils": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "std", - "flake-utils" - ], - "nixago-exts": "nixago-exts", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "std", - "nixpkgs" - ] - }, + "nixpkgs-regression_12": { "locked": { - "lastModified": 1659153038, - "narHash": "sha256-g4npRU8YBR7CAqMF0SyXtkHnoY9q+NcxvZwcc6UvLBc=", - "owner": "nix-community", - "repo": "nixago", - "rev": "608abdd0fe6729d1f7244e03f1a7f8a5d6408898", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixago_3": { - "inputs": { - "flake-utils": [ - "ctl", - "db-sync", - "cardano-world", - "std", - "flake-utils" - ], - "nixago-exts": "nixago-exts_2", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "std", - "nixpkgs" - ] + "nixpkgs-regression_13": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" }, + "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" + } + }, + "nixpkgs-regression_14": { "locked": { - "lastModified": 1659153038, - "narHash": "sha256-g4npRU8YBR7CAqMF0SyXtkHnoY9q+NcxvZwcc6UvLBc=", - "owner": "nix-community", - "repo": "nixago", - "rev": "608abdd0fe6729d1f7244e03f1a7f8a5d6408898", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixago", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixlib": { + "nixpkgs-regression_15": { "locked": { - "lastModified": 1652576347, - "narHash": "sha256-52Wu7hkcIRcS4UenSSrt01J2sAbbQ6YqxZIDpuEPL/c=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "bdf553800c9c34ed00641785b02038f67f44d671", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixlib_2": { + "nixpkgs-regression_16": { "locked": { - "lastModified": 1644107864, - "narHash": "sha256-Wrbt6Gs+hjXD3HUICPBJHKnHEUqiyx8rzHCgvqC1Bok=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "58eabcf65e7dba189eb0013f86831c159e3b2be6", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixlib_3": { + "nixpkgs-regression_17": { "locked": { - "lastModified": 1656809537, - "narHash": "sha256-pwXBYG3ThN4ccJjvcdNdonQ8Wyv0y/iYdnuesiFUY1U=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "40e271f69106323734b55e2ba74f13bebde324c0", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs": { + "nixpkgs-regression_18": { "locked": { - "lastModified": 1687420147, - "narHash": "sha256-NILbmZVsoP2Aw0OAIXdbYXrWc/qggIDDyIwZ01yUx+Q=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d449a456ba7d81038fc9ec9141eae7ee3aaf2982", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "release-23.05", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-2003": { + "nixpkgs-regression_2": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-2003_2": { + "nixpkgs-regression_3": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-2003_3": { + "nixpkgs-regression_4": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-2003_4": { + "nixpkgs-regression_5": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-2003_5": { + "nixpkgs-regression_6": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-2003_6": { + "nixpkgs-regression_7": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs-2003_7": { + "nixpkgs-regression_8": { "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" + } + }, + "nixpkgs-regression_9": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" + }, + "original": { + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs-2105": { + "nixpkgs-stable": { "locked": { - "lastModified": 1659914493, - "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "lastModified": 1690066826, + "narHash": "sha256-6L2qb+Zc0BFkh72OS9uuX637gniOjzU6qCDBpjB2LGY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "rev": "ce45b591975d070044ca24e3003c830d26fea1c8", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "release-23.05", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_2": { + "nixpkgs-unstable": { "locked": { - "lastModified": 1642244250, - "narHash": "sha256-vWpUEqQdVP4srj+/YLJRTN9vjpTs4je0cdWKXPbDItc=", + "lastModified": 1690720142, + "narHash": "sha256-GywuiZjBKfFkntQwpNQfL+Ksa2iGjPprBGL0/psgRZM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0fd9ee1aa36ce865ad273f4f07fdc093adeb5c00", + "rev": "3acb5c4264c490e7714d503c7166a3fde0c51324", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_3": { + "nixpkgs-unstable_10": { "locked": { - "lastModified": 1645296114, - "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_4": { + "nixpkgs-unstable_11": { "locked": { - "lastModified": 1655034179, - "narHash": "sha256-rf1/7AbzuYDw6+8Xvvf3PtEOygymLBrFsFxvext5ZjI=", + "lastModified": 1657888067, + "narHash": "sha256-GnwJoFBTPfW3+mz7QEeJEEQ9OMHZOiIJ/qDhZxrlKh8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "046ee4af7a9f016a364f8f78eeaa356ba524ac31", + "rev": "65fae659e31098ca4ac825a6fef26d890aaf3f4e", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_5": { + "nixpkgs-unstable_12": { "locked": { - "lastModified": 1645296114, - "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_6": { + "nixpkgs-unstable_13": { "locked": { - "lastModified": 1659914493, - "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "lastModified": 1720181791, + "narHash": "sha256-i4vJL12/AdyuQuviMMd1Hk2tsGt02hDNhA0Zj1m16N8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "rev": "4284c2b73c8bce4b46a6adf23e16d9e2ec8da4bb", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2105_7": { + "nixpkgs-unstable_2": { "locked": { - "lastModified": 1645296114, - "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", - "owner": "NixOS", + "lastModified": 1696577711, + "narHash": "sha256-94VRjvClIKDym1QRqPkX5LTQoAwZ1E6QE/3dWtOXSIQ=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "rev": "a2eb207f45e4a14a1e3019d9e3863d1e208e2295", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "owner": "nixos", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111": { + "nixpkgs-unstable_3": { "locked": { - "lastModified": 1659446231, - "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "lastModified": 1695318763, + "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_2": { + "nixpkgs-unstable_4": { "locked": { - "lastModified": 1644510859, - "narHash": "sha256-xjpVvL5ecbyi0vxtVl/Fh9bwGlMbw3S06zE5nUzFB8A=", + "lastModified": 1682656005, + "narHash": "sha256-fYplYo7so1O+rSQ2/aS+SbTPwLTeoUXk4ekKNtSl4P8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0d1d5d7e3679fec9d07f2eb804d9f9fdb98378d3", + "rev": "6806b63e824f84b0f0e60b6d660d4ae753de0477", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_3": { - "locked": { - "lastModified": 1648744337, - "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", + "nixpkgs-unstable_5": { + "locked": { + "lastModified": 1695318763, + "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_4": { + "nixpkgs-unstable_6": { "locked": { - "lastModified": 1656782578, - "narHash": "sha256-1eMCBEqJplPotTo/SZ/t5HU6Sf2I8qKlZi9MX7jv9fw=", + "lastModified": 1694822471, + "narHash": "sha256-6fSDCj++lZVMZlyqOe9SIOL8tYSBz1bI8acwovRwoX8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "573603b7fdb9feb0eb8efc16ee18a015c667ab1b", + "rev": "47585496bcb13fb72e4a90daeea2f434e2501998", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", "repo": "nixpkgs", + "rev": "47585496bcb13fb72e4a90daeea2f434e2501998", "type": "github" } }, - "nixpkgs-2111_5": { + "nixpkgs-unstable_7": { "locked": { - "lastModified": 1648744337, - "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", - "owner": "NixOS", + "lastModified": 1646331602, + "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "rev": "ad267cc9cf3d5a6ae63940df31eb31382d6356e6", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "owner": "nixos", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_6": { + "nixpkgs-unstable_8": { "locked": { - "lastModified": 1659446231, - "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", - "owner": "NixOS", + "lastModified": 1656338871, + "narHash": "sha256-+LOvZFt3MpWtrxXLH4igQtRVzyD43VnuTJjDVbt7phY=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "rev": "819e4d63fc7f337a822a049fd055cd7615a5e0d6", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "owner": "nixos", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111_7": { + "nixpkgs-unstable_9": { "locked": { - "lastModified": 1648744337, - "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", - "owner": "NixOS", + "lastModified": 1646331602, + "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", + "rev": "ad267cc9cf3d5a6ae63940df31eb31382d6356e6", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", + "owner": "nixos", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2205": { + "nixpkgs_10": { "locked": { - "lastModified": 1682600000, - "narHash": "sha256-ha4BehR1dh8EnXSoE1m/wyyYVvHI9txjW4w5/oxsW5Y=", + "lastModified": 1670461440, + "narHash": "sha256-jy1LB8HOMKGJEGXgzFRLDU1CBGL0/LlkolgnqIsF0D8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "50fc86b75d2744e1ab3837ef74b53f103a9b55a0", + "rev": "04a75b2eecc0acf6239acf9dd04485ff8d14f425", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-22.05-darwin", + "ref": "nixos-22.11-small", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2205_2": { + "nixpkgs_11": { "locked": { - "lastModified": 1657876628, - "narHash": "sha256-URmf0O2cQ/3heg2DJOeLyU/JmfVMqG4X5t9crQXMaeY=", + "lastModified": 1690026219, + "narHash": "sha256-oOduRk/kzQxOBknZXTLSEYd7tk+GoKvr8wV6Ab+t4AU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "549d82bdd40f760a438c3c3497c1c61160f3de55", + "rev": "f465da166263bc0d4b39dfd4ca28b777c92d4b73", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-22.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2205_3": { + "nixpkgs_12": { "locked": { - "lastModified": 1685573264, - "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "lastModified": 1675249806, + "narHash": "sha256-u8Rcqekusl3pMZm68hZqr6zozI8Ug5IxqOiqDLAlu1k=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "380be19fbd2d9079f677978361792cb25e8a3635", + "rev": "79feedf38536de2a27d13fe2eaf200a9c05193ba", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-22.05-darwin", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2211": { + "nixpkgs_13": { "locked": { - "lastModified": 1682682915, - "narHash": "sha256-haR0u/j/nUvlMloYlaOYq1FMXTvkNHw+wGxc+0qXisM=", - "owner": "NixOS", + "lastModified": 1636823747, + "narHash": "sha256-oWo1nElRAOZqEf90Yek2ixdHyjD+gqtS/pAgwaQ9UhQ=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "09f1b33fcc0f59263137e23e935c1bb03ec920e4", + "rev": "f6a2ed2082d9a51668c86ba27d0b5496f7a2ea93", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-22.11-darwin", + "owner": "nixos", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2211_2": { + "nixpkgs_14": { "locked": { - "lastModified": 1688392541, - "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-22.11-darwin", + "ref": "nixos-22.05-small", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2305": { + "nixpkgs_15": { "locked": { - "lastModified": 1701362232, - "narHash": "sha256-GVdzxL0lhEadqs3hfRLuj+L1OJFGiL/L7gCcelgBlsw=", + "lastModified": 1642336556, + "narHash": "sha256-QSPPbFEwy0T0DrIuSzAACkaANPQaR1lZR/nHZGz9z04=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d2332963662edffacfddfad59ff4f709dde80ffe", + "rev": "f3d9d4bd898cca7d04af2ae4f6ef01f2219df3d6", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-23.05-darwin", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs-2311": { + "nixpkgs_16": { "locked": { - "lastModified": 1701386440, - "narHash": "sha256-xI0uQ9E7JbmEy/v8kR9ZQan6389rHug+zOtZeZFiDJk=", + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "293822e55ec1872f715a66d0eda9e592dc14419f", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-23.11-darwin", + "ref": "nixos-22.05-small", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-docker": { + "nixpkgs_17": { "locked": { - "lastModified": 1652739558, - "narHash": "sha256-znGkjGugajqF/sFS+H4+ENmGTaVPFE0uu1JjQZJLEaQ=", - "owner": "nixos", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "ff691ed9ba21528c1b4e034f36a04027e4522c58", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { - "owner": "nixos", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "ff691ed9ba21528c1b4e034f36a04027e4522c58", "type": "github" } }, - "nixpkgs-regression": { + "nixpkgs_18": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1653581809, + "narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "83658b28fe638a170a19b8933aa008b30640fbd1", "type": "github" }, "original": { "owner": "NixOS", + "ref": "nixos-unstable", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression_10": { + "nixpkgs_19": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" - } - }, - "nixpkgs-regression_11": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" - }, - "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" } }, - "nixpkgs-regression_12": { + "nixpkgs_2": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1687420147, + "narHash": "sha256-NILbmZVsoP2Aw0OAIXdbYXrWc/qggIDDyIwZ01yUx+Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "d449a456ba7d81038fc9ec9141eae7ee3aaf2982", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "NixOS", + "ref": "release-23.05", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_13": { + "nixpkgs_20": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", + "lastModified": 1674407282, + "narHash": "sha256-2qwc8mrPINSFdWffPK+ji6nQ9aGnnZyHSItVcYDZDlk=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "ab1254087f4cdf4af74b552d7fc95175d9bdbb49", "type": "github" }, "original": { - "owner": "NixOS", + "owner": "nixos", + "ref": "nixos-22.11", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression_14": { + "nixpkgs_21": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", + "lastModified": 1665087388, + "narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_2": { + "nixpkgs_22": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1653581809, + "narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "83658b28fe638a170a19b8933aa008b30640fbd1", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_3": { + "nixpkgs_23": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_4": { + "nixpkgs_24": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", + "lastModified": 1675940568, + "narHash": "sha256-epG6pOT9V0kS+FUqd7R6/CWkgnZx2DMT5Veqo+y6G3c=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "6ccc4a59c3f1b56d039d93da52696633e641bc71", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_5": { + "nixpkgs_25": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1642336556, + "narHash": "sha256-QSPPbFEwy0T0DrIuSzAACkaANPQaR1lZR/nHZGz9z04=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "f3d9d4bd898cca7d04af2ae4f6ef01f2219df3d6", "type": "github" }, "original": { "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "indirect" } }, - "nixpkgs-regression_6": { + "nixpkgs_26": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "NixOS", + "ref": "nixos-22.05-small", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_7": { + "nixpkgs_27": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-regression_8": { + "nixpkgs_28": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "lastModified": 1681001314, + "narHash": "sha256-5sDnCLdrKZqxLPK4KA8+f4A3YKO/u6ElpMILvX0g72c=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "367c0e1086a4eb4502b24d872cea2c7acdd557f4", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" } }, - "nixpkgs-regression_9": { + "nixpkgs_29": { "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", + "lastModified": 1675940568, + "narHash": "sha256-epG6pOT9V0kS+FUqd7R6/CWkgnZx2DMT5Veqo+y6G3c=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "rev": "6ccc4a59c3f1b56d039d93da52696633e641bc71", "type": "github" }, "original": { - "id": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "indirect" + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs-unstable": { + "nixpkgs_3": { "locked": { - "lastModified": 1682656005, - "narHash": "sha256-fYplYo7so1O+rSQ2/aS+SbTPwLTeoUXk4ekKNtSl4P8=", + "lastModified": 1677543769, + "narHash": "sha256-LwbqS8vGisXl2WHpK9r5+kodr0zoIT8F2YB0R4y1TsA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6806b63e824f84b0f0e60b6d660d4ae753de0477", + "rev": "b26d52c9feb6476580016e78935cbf96eb3e2115", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-22.11", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_2": { + "nixpkgs_30": { "locked": { - "lastModified": 1646331602, - "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", + "lastModified": 1677063315, + "narHash": "sha256-qiB4ajTeAOVnVSAwCNEEkoybrAlA+cpeiBxLobHndE8=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ad267cc9cf3d5a6ae63940df31eb31382d6356e6", + "rev": "988cc958c57ce4350ec248d2d53087777f9e1949", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_3": { + "nixpkgs_31": { "locked": { - "lastModified": 1656338871, - "narHash": "sha256-+LOvZFt3MpWtrxXLH4igQtRVzyD43VnuTJjDVbt7phY=", - "owner": "nixos", + "lastModified": 1653581809, + "narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "819e4d63fc7f337a822a049fd055cd7615a5e0d6", + "rev": "83658b28fe638a170a19b8933aa008b30640fbd1", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", + "owner": "NixOS", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_4": { + "nixpkgs_32": { "locked": { - "lastModified": 1646331602, - "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", - "owner": "nixos", + "lastModified": 1654807842, + "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad267cc9cf3d5a6ae63940df31eb31382d6356e6", + "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", + "owner": "NixOS", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_5": { + "nixpkgs_33": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", - "owner": "NixOS", + "lastModified": 1665087388, + "narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7", "type": "github" }, "original": { - "owner": "NixOS", + "owner": "nixos", "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_6": { + "nixpkgs_34": { "locked": { - "lastModified": 1657888067, - "narHash": "sha256-GnwJoFBTPfW3+mz7QEeJEEQ9OMHZOiIJ/qDhZxrlKh8=", + "lastModified": 1642336556, + "narHash": "sha256-QSPPbFEwy0T0DrIuSzAACkaANPQaR1lZR/nHZGz9z04=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "65fae659e31098ca4ac825a6fef26d890aaf3f4e", + "rev": "f3d9d4bd898cca7d04af2ae4f6ef01f2219df3d6", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs-unstable_7": { + "nixpkgs_35": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-22.05-small", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_8": { + "nixpkgs_36": { "locked": { - "lastModified": 1701336116, - "narHash": "sha256-kEmpezCR/FpITc6yMbAh4WrOCiT2zg5pSjnKrq51h5Y=", + "lastModified": 1712920918, + "narHash": "sha256-1yxFvUcJfUphK9V91KufIQom7gCsztza0H4Rz2VCWUU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f5c27c6136db4d76c30e533c20517df6864c46ee", + "rev": "92323443a56f4e9fc4e4b712e3119f66d0969297", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-unstable_9": { + "nixpkgs_37": { "locked": { - "lastModified": 1648219316, - "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", - "owner": "NixOS", + "lastModified": 1708343346, + "narHash": "sha256-qlzHvterVRzS8fS0ophQpkh0rqw0abijHEOAKm0HmV0=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "rev": "9312b935a538684049cb668885e60f15547d4c5f", "type": "github" }, "original": { + "owner": "nixos", + "ref": "release-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_38": { + "locked": { + "lastModified": 1627969475, + "narHash": "sha256-MhVtkVt1MFfaDY3ObJu54NBcsaPk19vOBZ8ouhjO4qs=", "owner": "NixOS", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", + "rev": "bd27e2e8316ac6eab11aa35c586e743286f23ecf", "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs_10": { + "nixpkgs_39": { "locked": { "lastModified": 1644972330, "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", @@ -6952,7 +11924,23 @@ "type": "github" } }, - "nixpkgs_11": { + "nixpkgs_4": { + "locked": { + "lastModified": 1645013224, + "narHash": "sha256-b7OEC8vwzJv3rsz9pwnTX2LQDkeOWz2DbKypkVvNHXc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "b66b39216b1fef2d8c33cc7a5c72d8da80b79970", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_40": { "locked": { "lastModified": 1627969475, "narHash": "sha256-MhVtkVt1MFfaDY3ObJu54NBcsaPk19vOBZ8ouhjO4qs=", @@ -6966,7 +11954,7 @@ "type": "indirect" } }, - "nixpkgs_12": { + "nixpkgs_41": { "locked": { "lastModified": 1644972330, "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", @@ -6982,7 +11970,7 @@ "type": "github" } }, - "nixpkgs_13": { + "nixpkgs_42": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -6998,7 +11986,7 @@ "type": "github" } }, - "nixpkgs_14": { + "nixpkgs_43": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7013,7 +12001,7 @@ "type": "indirect" } }, - "nixpkgs_15": { + "nixpkgs_44": { "locked": { "lastModified": 1638452135, "narHash": "sha256-5Il6hgrTgcWIsB7zug0yDFccYXx7pJCw8cwJdXMuLfM=", @@ -7029,7 +12017,7 @@ "type": "github" } }, - "nixpkgs_16": { + "nixpkgs_45": { "locked": { "lastModified": 1602702596, "narHash": "sha256-fqJ4UgOb4ZUnCDIapDb4gCrtAah5Rnr2/At3IzMitig=", @@ -7044,7 +12032,7 @@ "type": "indirect" } }, - "nixpkgs_17": { + "nixpkgs_46": { "locked": { "lastModified": 1638887115, "narHash": "sha256-emjtIeqyJ84Eb3X7APJruTrwcfnHQKs55XGljj62prs=", @@ -7060,7 +12048,7 @@ "type": "github" } }, - "nixpkgs_18": { + "nixpkgs_47": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7075,7 +12063,7 @@ "type": "indirect" } }, - "nixpkgs_19": { + "nixpkgs_48": { "locked": { "lastModified": 1641909823, "narHash": "sha256-Uxo+Wm6c/ijNhaJlYtFLJG9mh75FYZaBreMC2ZE0nEY=", @@ -7091,37 +12079,39 @@ "type": "github" } }, - "nixpkgs_2": { + "nixpkgs_49": { "locked": { - "lastModified": 1642336556, - "narHash": "sha256-QSPPbFEwy0T0DrIuSzAACkaANPQaR1lZR/nHZGz9z04=", - "owner": "NixOS", + "lastModified": 1647350163, + "narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "f3d9d4bd898cca7d04af2ae4f6ef01f2219df3d6", + "rev": "3eb07eeafb52bcbf02ce800f032f18d666a9498d", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs_20": { + "nixpkgs_5": { "locked": { - "lastModified": 1647350163, - "narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=", + "lastModified": 1680945546, + "narHash": "sha256-8FuaH5t/aVi/pR1XxnF0qi4WwMYC+YxlfdsA0V+TEuQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "3eb07eeafb52bcbf02ce800f032f18d666a9498d", + "rev": "d9f759f2ea8d265d974a6e1259bd510ac5844c5d", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_21": { + "nixpkgs_50": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7137,7 +12127,7 @@ "type": "github" } }, - "nixpkgs_22": { + "nixpkgs_51": { "locked": { "lastModified": 1646506091, "narHash": "sha256-sWNAJE2m+HOh1jtXlHcnhxsj6/sXrHgbqVNcVRlveK4=", @@ -7153,7 +12143,7 @@ "type": "github" } }, - "nixpkgs_23": { + "nixpkgs_52": { "locked": { "lastModified": 1658119717, "narHash": "sha256-4upOZIQQ7Bc4CprqnHsKnqYfw+arJeAuU+QcpjYBXW0=", @@ -7169,7 +12159,7 @@ "type": "github" } }, - "nixpkgs_24": { + "nixpkgs_53": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7185,7 +12175,7 @@ "type": "github" } }, - "nixpkgs_25": { + "nixpkgs_54": { "locked": { "lastModified": 1652576347, "narHash": "sha256-52Wu7hkcIRcS4UenSSrt01J2sAbbQ6YqxZIDpuEPL/c=", @@ -7200,7 +12190,7 @@ "type": "github" } }, - "nixpkgs_26": { + "nixpkgs_55": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7216,7 +12206,7 @@ "type": "github" } }, - "nixpkgs_27": { + "nixpkgs_56": { "locked": { "lastModified": 1642451377, "narHash": "sha256-hvAuYDUN8XIrcQKE6wDw4LjTCcwrTp2B1i1i/5vfDMQ=", @@ -7231,7 +12221,7 @@ "type": "github" } }, - "nixpkgs_28": { + "nixpkgs_57": { "locked": { "lastModified": 1645296114, "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", @@ -7246,39 +12236,23 @@ "type": "indirect" } }, - "nixpkgs_29": { - "locked": { - "lastModified": 1652559422, - "narHash": "sha256-jPVTNImBTUIFdtur+d4IVot6eXmsvtOcBm0TzxmhWPk=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "8b3398bc7587ebb79f93dfeea1b8c574d3c6dba1", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-21.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { + "nixpkgs_58": { "locked": { - "lastModified": 1657693803, - "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", + "lastModified": 1652559422, + "narHash": "sha256-jPVTNImBTUIFdtur+d4IVot6eXmsvtOcBm0TzxmhWPk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", + "rev": "8b3398bc7587ebb79f93dfeea1b8c574d3c6dba1", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-22.05-small", + "owner": "nixos", + "ref": "nixos-21.11", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_30": { + "nixpkgs_59": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7293,7 +12267,23 @@ "type": "indirect" } }, - "nixpkgs_31": { + "nixpkgs_6": { + "locked": { + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.05-small", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_60": { "locked": { "lastModified": 1641909823, "narHash": "sha256-Uxo+Wm6c/ijNhaJlYtFLJG9mh75FYZaBreMC2ZE0nEY=", @@ -7309,7 +12299,7 @@ "type": "github" } }, - "nixpkgs_32": { + "nixpkgs_61": { "locked": { "lastModified": 1647350163, "narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=", @@ -7325,7 +12315,7 @@ "type": "github" } }, - "nixpkgs_33": { + "nixpkgs_62": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7341,7 +12331,7 @@ "type": "github" } }, - "nixpkgs_34": { + "nixpkgs_63": { "locked": { "lastModified": 1658311025, "narHash": "sha256-GqagY5YmaZB3YaO41kKcQhe5RcpS83wnsW8iCu5Znqo=", @@ -7357,7 +12347,7 @@ "type": "github" } }, - "nixpkgs_35": { + "nixpkgs_64": { "locked": { "lastModified": 1646331602, "narHash": "sha256-cRuytTfel52z947yKfJcZU7zbQBgM16qqTf+oJkVwtg=", @@ -7373,7 +12363,7 @@ "type": "github" } }, - "nixpkgs_36": { + "nixpkgs_65": { "locked": { "lastModified": 1643381941, "narHash": "sha256-pHTwvnN4tTsEKkWlXQ8JMY423epos8wUOhthpwJjtpc=", @@ -7389,7 +12379,7 @@ "type": "github" } }, - "nixpkgs_37": { + "nixpkgs_66": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7404,7 +12394,7 @@ "type": "indirect" } }, - "nixpkgs_38": { + "nixpkgs_67": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7419,7 +12409,7 @@ "type": "indirect" } }, - "nixpkgs_39": { + "nixpkgs_68": { "locked": { "lastModified": 1644486793, "narHash": "sha256-EeijR4guVHgVv+JpOX3cQO+1XdrkJfGmiJ9XVsVU530=", @@ -7435,36 +12425,37 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_69": { "locked": { - "lastModified": 1654807842, - "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", + "lastModified": 1627969475, + "narHash": "sha256-MhVtkVt1MFfaDY3ObJu54NBcsaPk19vOBZ8ouhjO4qs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", + "rev": "bd27e2e8316ac6eab11aa35c586e743286f23ecf", "type": "github" }, "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "nixpkgs_40": { + "nixpkgs_7": { "locked": { - "lastModified": 1627969475, - "narHash": "sha256-MhVtkVt1MFfaDY3ObJu54NBcsaPk19vOBZ8ouhjO4qs=", - "owner": "NixOS", + "lastModified": 1692339729, + "narHash": "sha256-TUK76/Pqm9qIDjEGd27Lz9EiBIvn5F70JWDmEQ4Y5DQ=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "bd27e2e8316ac6eab11aa35c586e743286f23ecf", + "rev": "ae521bd4e460b076a455dca8b13f4151489a725c", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "nixos", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" } }, - "nixpkgs_41": { + "nixpkgs_70": { "locked": { "lastModified": 1644972330, "narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=", @@ -7480,7 +12471,7 @@ "type": "github" } }, - "nixpkgs_42": { + "nixpkgs_71": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7496,7 +12487,7 @@ "type": "github" } }, - "nixpkgs_43": { + "nixpkgs_72": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7511,7 +12502,7 @@ "type": "indirect" } }, - "nixpkgs_44": { + "nixpkgs_73": { "locked": { "lastModified": 1638452135, "narHash": "sha256-5Il6hgrTgcWIsB7zug0yDFccYXx7pJCw8cwJdXMuLfM=", @@ -7527,7 +12518,7 @@ "type": "github" } }, - "nixpkgs_45": { + "nixpkgs_74": { "locked": { "lastModified": 1602702596, "narHash": "sha256-fqJ4UgOb4ZUnCDIapDb4gCrtAah5Rnr2/At3IzMitig=", @@ -7542,7 +12533,7 @@ "type": "indirect" } }, - "nixpkgs_46": { + "nixpkgs_75": { "locked": { "lastModified": 1638887115, "narHash": "sha256-emjtIeqyJ84Eb3X7APJruTrwcfnHQKs55XGljj62prs=", @@ -7558,7 +12549,7 @@ "type": "github" } }, - "nixpkgs_47": { + "nixpkgs_76": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7573,7 +12564,7 @@ "type": "indirect" } }, - "nixpkgs_48": { + "nixpkgs_77": { "locked": { "lastModified": 1641909823, "narHash": "sha256-Uxo+Wm6c/ijNhaJlYtFLJG9mh75FYZaBreMC2ZE0nEY=", @@ -7589,7 +12580,7 @@ "type": "github" } }, - "nixpkgs_49": { + "nixpkgs_78": { "locked": { "lastModified": 1647350163, "narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=", @@ -7605,39 +12596,39 @@ "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_79": { "locked": { - "lastModified": 1653581809, - "narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=", - "owner": "NixOS", + "lastModified": 1644525281, + "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "83658b28fe638a170a19b8933aa008b30640fbd1", + "rev": "48d63e924a2666baf37f4f14a18f19347fbd54a2", "type": "github" }, "original": { - "owner": "NixOS", + "owner": "nixos", "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_50": { + "nixpkgs_8": { "locked": { - "lastModified": 1644525281, - "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", + "lastModified": 1684171562, + "narHash": "sha256-BMUWjVWAUdyMWKk0ATMC9H0Bv4qAV/TXwwPUvTiC5IQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "48d63e924a2666baf37f4f14a18f19347fbd54a2", + "rev": "55af203d468a6f5032a519cba4f41acf5a74b638", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-unstable", + "ref": "release-22.11", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_51": { + "nixpkgs_80": { "locked": { "lastModified": 1646506091, "narHash": "sha256-sWNAJE2m+HOh1jtXlHcnhxsj6/sXrHgbqVNcVRlveK4=", @@ -7653,7 +12644,7 @@ "type": "github" } }, - "nixpkgs_52": { + "nixpkgs_81": { "locked": { "lastModified": 1658119717, "narHash": "sha256-4upOZIQQ7Bc4CprqnHsKnqYfw+arJeAuU+QcpjYBXW0=", @@ -7669,7 +12660,7 @@ "type": "github" } }, - "nixpkgs_53": { + "nixpkgs_82": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -7685,7 +12676,7 @@ "type": "github" } }, - "nixpkgs_54": { + "nixpkgs_83": { "locked": { "lastModified": 1646470760, "narHash": "sha256-dQISyucVCCPaFioUhy5ZgfBz8rOMKGI8k13aPDFTqEs=", @@ -7701,7 +12692,7 @@ "type": "github" } }, - "nixpkgs_55": { + "nixpkgs_84": { "locked": { "lastModified": 1619531122, "narHash": "sha256-ovm5bo6PkZzNKh2YGXbRKYIjega0EjiEP0YDwyeXEYU=", @@ -7715,7 +12706,7 @@ "type": "indirect" } }, - "nixpkgs_56": { + "nixpkgs_85": { "locked": { "lastModified": 1656461576, "narHash": "sha256-rlmmw6lIlkMQIiB+NsnO8wQYWTfle8TA41UREPLP5VY=", @@ -7731,7 +12722,7 @@ "type": "github" } }, - "nixpkgs_57": { + "nixpkgs_86": { "locked": { "lastModified": 1655567057, "narHash": "sha256-Cc5hQSMsTzOHmZnYm8OSJ5RNUp22bd5NADWLHorULWQ=", @@ -7745,7 +12736,7 @@ "type": "indirect" } }, - "nixpkgs_58": { + "nixpkgs_87": { "locked": { "lastModified": 1656401090, "narHash": "sha256-bUS2nfQsvTQW2z8SK7oEFSElbmoBahOPtbXPm0AL3I4=", @@ -7759,7 +12750,7 @@ "type": "indirect" } }, - "nixpkgs_59": { + "nixpkgs_88": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7774,22 +12765,7 @@ "type": "indirect" } }, - "nixpkgs_6": { - "locked": { - "lastModified": 1654807842, - "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "fc909087cc3386955f21b4665731dbdaceefb1d8", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_60": { + "nixpkgs_89": { "locked": { "lastModified": 1656809537, "narHash": "sha256-pwXBYG3ThN4ccJjvcdNdonQ8Wyv0y/iYdnuesiFUY1U=", @@ -7804,7 +12780,23 @@ "type": "github" } }, - "nixpkgs_61": { + "nixpkgs_9": { + "locked": { + "lastModified": 1684171562, + "narHash": "sha256-BMUWjVWAUdyMWKk0ATMC9H0Bv4qAV/TXwwPUvTiC5IQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "55af203d468a6f5032a519cba4f41acf5a74b638", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "release-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_90": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7819,7 +12811,7 @@ "type": "indirect" } }, - "nixpkgs_62": { + "nixpkgs_91": { "locked": { "lastModified": 1654807842, "narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=", @@ -7834,7 +12826,7 @@ "type": "github" } }, - "nixpkgs_63": { + "nixpkgs_92": { "locked": { "lastModified": 1656947410, "narHash": "sha256-htDR/PZvjUJGyrRJsVqDmXR8QeoswBaRLzHt13fd0iY=", @@ -7850,7 +12842,7 @@ "type": "github" } }, - "nixpkgs_64": { + "nixpkgs_93": { "locked": { "lastModified": 1658311025, "narHash": "sha256-GqagY5YmaZB3YaO41kKcQhe5RcpS83wnsW8iCu5Znqo=", @@ -7866,7 +12858,7 @@ "type": "github" } }, - "nixpkgs_65": { + "nixpkgs_94": { "locked": { "lastModified": 1642451377, "narHash": "sha256-hvAuYDUN8XIrcQKE6wDw4LjTCcwrTp2B1i1i/5vfDMQ=", @@ -7881,7 +12873,7 @@ "type": "github" } }, - "nixpkgs_66": { + "nixpkgs_95": { "locked": { "lastModified": 1653920503, "narHash": "sha256-BBeCZwZImtjP3oYy4WogkQYy5OxNyfNciVSc1AfZgLQ=", @@ -7897,7 +12889,7 @@ "type": "github" } }, - "nixpkgs_67": { + "nixpkgs_96": { "locked": { "lastModified": 1650469885, "narHash": "sha256-BuILRZ6pzMnGey8/irbjGq1oo3vIvZa1pitSdZCmIXA=", @@ -7913,7 +12905,7 @@ "type": "github" } }, - "nixpkgs_68": { + "nixpkgs_97": { "locked": { "lastModified": 1632864508, "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", @@ -7928,7 +12920,7 @@ "type": "indirect" } }, - "nixpkgs_69": { + "nixpkgs_98": { "locked": { "lastModified": 1657693803, "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", @@ -7944,29 +12936,13 @@ "type": "github" } }, - "nixpkgs_7": { - "locked": { - "lastModified": 1674407282, - "narHash": "sha256-2qwc8mrPINSFdWffPK+ji6nQ9aGnnZyHSItVcYDZDlk=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "ab1254087f4cdf4af74b552d7fc95175d9bdbb49", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-22.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_70": { + "nixpkgs_99": { "locked": { - "lastModified": 1697723726, - "narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe+/uVNy6zCGMXgoeMb7T9rg=", + "lastModified": 1713714899, + "narHash": "sha256-+z/XjO3QJs5rLE5UOf015gdVauVRQd2vZtsFkaXBq2Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7c9cc5a6e5d38010801741ac830a3f8fd667a7a0", + "rev": "6143fc5eeb9c4f00163267708e26191d1e918932", "type": "github" }, "original": { @@ -7976,56 +12952,11 @@ "type": "github" } }, - "nixpkgs_71": { - "locked": { - "lastModified": 1632864508, - "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "ref": "nixos-21.05-small", - "type": "indirect" - } - }, - "nixpkgs_8": { - "locked": { - "lastModified": 1665087388, - "narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_9": { - "locked": { - "lastModified": 1627969475, - "narHash": "sha256-MhVtkVt1MFfaDY3ObJu54NBcsaPk19vOBZ8ouhjO4qs=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "bd27e2e8316ac6eab11aa35c586e743286f23ecf", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, "nomad": { "inputs": { - "nix": "nix_3", - "nixpkgs": "nixpkgs_17", - "utils": "utils_4" + "nix": "nix_8", + "nixpkgs": "nixpkgs_46", + "utils": "utils_9" }, "locked": { "lastModified": 1648128770, @@ -8044,11 +12975,11 @@ }, "nomad-driver-nix": { "inputs": { - "devshell": "devshell_2", - "inclusive": "inclusive", - "nix": "nix_4", - "nixpkgs": "nixpkgs_19", - "utils": "utils_5" + "devshell": "devshell_6", + "inclusive": "inclusive_2", + "nix": "nix_9", + "nixpkgs": "nixpkgs_48", + "utils": "utils_10" }, "locked": { "lastModified": 1648029666, @@ -8066,11 +12997,11 @@ }, "nomad-driver-nix_2": { "inputs": { - "devshell": "devshell_5", - "inclusive": "inclusive_4", - "nix": "nix_6", - "nixpkgs": "nixpkgs_31", - "utils": "utils_10" + "devshell": "devshell_9", + "inclusive": "inclusive_5", + "nix": "nix_11", + "nixpkgs": "nixpkgs_60", + "utils": "utils_15" }, "locked": { "lastModified": 1648029666, @@ -8088,11 +13019,11 @@ }, "nomad-driver-nix_3": { "inputs": { - "devshell": "devshell_12", - "inclusive": "inclusive_9", - "nix": "nix_11", - "nixpkgs": "nixpkgs_48", - "utils": "utils_19" + "devshell": "devshell_16", + "inclusive": "inclusive_10", + "nix": "nix_16", + "nixpkgs": "nixpkgs_77", + "utils": "utils_24" }, "locked": { "lastModified": 1648029666, @@ -8110,10 +13041,10 @@ }, "nomad-follower": { "inputs": { - "devshell": "devshell_3", - "inclusive": "inclusive_2", - "nixpkgs": "nixpkgs_20", - "utils": "utils_6" + "devshell": "devshell_7", + "inclusive": "inclusive_3", + "nixpkgs": "nixpkgs_49", + "utils": "utils_11" }, "locked": { "lastModified": 1649836589, @@ -8131,10 +13062,10 @@ }, "nomad-follower_2": { "inputs": { - "devshell": "devshell_6", - "inclusive": "inclusive_5", - "nixpkgs": "nixpkgs_32", - "utils": "utils_11" + "devshell": "devshell_10", + "inclusive": "inclusive_6", + "nixpkgs": "nixpkgs_61", + "utils": "utils_16" }, "locked": { "lastModified": 1658244176, @@ -8151,11 +13082,11 @@ } }, "nomad-follower_3": { - "inputs": { - "devshell": "devshell_13", - "inclusive": "inclusive_10", - "nixpkgs": "nixpkgs_49", - "utils": "utils_20" + "inputs": { + "devshell": "devshell_17", + "inclusive": "inclusive_11", + "nixpkgs": "nixpkgs_78", + "utils": "utils_25" }, "locked": { "lastModified": 1649836589, @@ -8173,9 +13104,9 @@ }, "nomad_2": { "inputs": { - "nix": "nix_10", - "nixpkgs": "nixpkgs_46", - "utils": "utils_18" + "nix": "nix_15", + "nixpkgs": "nixpkgs_75", + "utils": "utils_23" }, "locked": { "lastModified": 1648128770, @@ -8207,6 +13138,68 @@ "type": "github" } }, + "nosys_2": { + "locked": { + "lastModified": 1668010795, + "narHash": "sha256-JBDVBnos8g0toU7EhIIqQ1If5m/nyBqtHhL3sicdPwI=", + "owner": "divnix", + "repo": "nosys", + "rev": "feade0141487801c71ff55623b421ed535dbdefa", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "nosys", + "type": "github" + } + }, + "nosys_3": { + "locked": { + "lastModified": 1668010795, + "narHash": "sha256-JBDVBnos8g0toU7EhIIqQ1If5m/nyBqtHhL3sicdPwI=", + "owner": "divnix", + "repo": "nosys", + "rev": "feade0141487801c71ff55623b421ed535dbdefa", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "nosys", + "type": "github" + } + }, + "nosys_4": { + "locked": { + "lastModified": 1668010795, + "narHash": "sha256-JBDVBnos8g0toU7EhIIqQ1If5m/nyBqtHhL3sicdPwI=", + "owner": "divnix", + "repo": "nosys", + "rev": "feade0141487801c71ff55623b421ed535dbdefa", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "nosys", + "type": "github" + } + }, + "offchain-metadata-tools-service": { + "flake": false, + "locked": { + "lastModified": 1684160858, + "narHash": "sha256-2pu/T4uoXBxhI47PrOS6zHRZRwaSM6qA87HJySwwIBo=", + "owner": "input-output-hk", + "repo": "offchain-metadata-tools", + "rev": "a68c12b10fe5ed9802defb4a6ca80919b695d945", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "feat-add-password-to-db-conn-string", + "repo": "offchain-metadata-tools", + "type": "github" + } + }, "ogmios": { "flake": false, "locked": { @@ -8224,66 +13217,41 @@ "type": "github" } }, - "ogmios-nixos": { - "inputs": { - "CHaP": "CHaP_3", - "blank": "blank_5", - "cardano-configurations": "cardano-configurations_2", - "cardano-node": [ - "ctl", - "cardano-node" - ], - "flake-compat": "flake-compat_13", - "haskell-nix": [ - "ctl", - "haskell-nix" - ], - "iohk-nix": [ - "ctl", - "iohk-nix" - ], - "nixpkgs": [ - "ctl", - "nixpkgs" - ], - "ogmios-src": [ - "ctl", - "ogmios" - ] - }, + "ogmios_2": { + "flake": false, "locked": { - "lastModified": 1695289922, - "narHash": "sha256-WeZkYCyvOqnVx9zYgyO2rh0rd3O2DmxH0HZ4OJnf/aw=", - "owner": "mlabs-haskell", - "repo": "ogmios-nixos", - "rev": "78e829e9ebd50c5891024dcd1004c2ac51facd80", + "lastModified": 1720778275, + "narHash": "sha256-OpUeVbztfLy+9d2M5w2Jgx1b/IhDNAQdlr/eP1iKUQI=", + "owner": "CardanoSolutions", + "repo": "ogmios", + "rev": "63a9e9d33eadbca22d1ecc90b9623b962148d174", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "repo": "ogmios-nixos", - "rev": "78e829e9ebd50c5891024dcd1004c2ac51facd80", + "owner": "CardanoSolutions", + "ref": "v6.5.0", + "repo": "ogmios", "type": "github" } }, - "ogmios_2": { + "old-ghc-nix": { "flake": false, "locked": { - "lastModified": 1691769233, - "narHash": "sha256-7CLprKq3RwJfvy31LAPux+DYFLjEmbRBFgvtYDpJA8Q=", - "owner": "CardanoSolutions", - "repo": "ogmios", - "rev": "3d3f359b0987c009ef66fb4d4b4bddce92b9aeb3", + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", "type": "github" }, "original": { - "owner": "CardanoSolutions", - "ref": "v6.0.0", - "repo": "ogmios", + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", "type": "github" } }, - "old-ghc-nix": { + "old-ghc-nix_10": { "flake": false, "locked": { "lastModified": 1631092763, @@ -8402,6 +13370,40 @@ "type": "github" } }, + "old-ghc-nix_8": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "old-ghc-nix_9": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, "ops-lib": { "flake": false, "locked": { @@ -8419,6 +13421,70 @@ } }, "ops-lib_2": { + "flake": false, + "locked": { + "lastModified": 1675186784, + "narHash": "sha256-HqDtrvk1l7YeREzCSEpUtChtlEgT6Tww9WrJiozjukc=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "5be29ed53b2a4cbbf4cf326fa2e9c1f2b754d26d", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "ops-lib_3": { + "flake": false, + "locked": { + "lastModified": 1713366514, + "narHash": "sha256-0hNlv+grFTE+TeXIbxSY97QoEEaUupOKMusZ4PesdrQ=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "19d83fa8eab1c0b7765f736eb4e8569d84d3e39d", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "ops-lib_4": { + "flake": false, + "locked": { + "lastModified": 1649848729, + "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "ops-lib_5": { + "flake": false, + "locked": { + "lastModified": 1649848729, + "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", + "owner": "input-output-hk", + "repo": "ops-lib", + "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "ops-lib_6": { "flake": false, "locked": { "lastModified": 1649848729, @@ -8429,86 +13495,255 @@ "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "ops-lib", + "owner": "input-output-hk", + "repo": "ops-lib", + "type": "github" + } + }, + "paisano": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ], + "nosys": "nosys_2", + "yants": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "yants" + ] + }, + "locked": { + "lastModified": 1677437285, + "narHash": "sha256-YGfMothgUq1T9wMJYEhOSvdIiD/8gLXO1YcZA6hyIWU=", + "owner": "paisano-nix", + "repo": "core", + "rev": "5f2fc05e98e001cb1cf9535ded09e05d90cec131", + "type": "github" + }, + "original": { + "owner": "paisano-nix", + "repo": "core", + "type": "github" + } + }, + "paisano-actions": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "paisano-mdbook-preprocessor", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1677306424, + "narHash": "sha256-H9/dI2rGEbKo4KEisqbRPHFG2ajF8Tm111NPdKGIf28=", + "owner": "paisano-nix", + "repo": "actions", + "rev": "65ec4e080b3480167fc1a748c89a05901eea9a9b", + "type": "github" + }, + "original": { + "owner": "paisano-nix", + "repo": "actions", + "type": "github" + } + }, + "paisano-mdbook-preprocessor": { + "inputs": { + "crane": "crane", + "fenix": "fenix_2", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" + ], + "paisano-actions": "paisano-actions", + "std": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std" + ] + }, + "locked": { + "lastModified": 1680654400, + "narHash": "sha256-Qdpio+ldhUK3zfl22Mhf8HUULdUOJXDWDdO7MIK69OU=", + "owner": "paisano-nix", + "repo": "mdbook-paisano-preprocessor", + "rev": "11a8fc47f574f194a7ae7b8b98001f6143ba4cf1", + "type": "github" + }, + "original": { + "owner": "paisano-nix", + "repo": "mdbook-paisano-preprocessor", + "type": "github" + } + }, + "paisano-tui": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "std": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std" + ] + }, + "locked": { + "lastModified": 1677533603, + "narHash": "sha256-Nq1dH/qn7Wg/Tj1+id+ZM3o0fzqonW73jAgY3mCp35M=", + "owner": "paisano-nix", + "repo": "tui", + "rev": "802958d123b0a5437441be0cab1dee487b0ed3eb", + "type": "github" + }, + "original": { + "owner": "paisano-nix", + "repo": "tui", "type": "github" } }, - "ops-lib_3": { - "flake": false, + "paisano-tui_2": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "std": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std" + ] + }, "locked": { - "lastModified": 1649848729, - "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", - "owner": "input-output-hk", - "repo": "ops-lib", - "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "lastModified": 1681847764, + "narHash": "sha256-mdd7PJW1BZvxy0cIKsPfAO+ohVl/V7heE5ZTAHzTdv8=", + "owner": "paisano-nix", + "repo": "tui", + "rev": "3096bad91cae73ab8ab3367d31f8a143d248a244", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "ops-lib", + "owner": "paisano-nix", + "ref": "0.1.1", + "repo": "tui", "type": "github" } }, - "ops-lib_4": { + "paisano-tui_3": { "flake": false, "locked": { - "lastModified": 1649848729, - "narHash": "sha256-5zN9gpn+DwdB67bcHfDD8zgMnR0EaJd2JVNMyL6J1N0=", - "owner": "input-output-hk", - "repo": "ops-lib", - "rev": "517c747f4d5d56e626f62618803bfccb09f14019", + "lastModified": 1708637035, + "narHash": "sha256-R19YURSK+MY/Rw6FZnojQS9zuDh+OoTAyngQAjjoubc=", + "owner": "paisano-nix", + "repo": "tui", + "rev": "231761b260587a64817e4ffae3afc15defaa15db", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "ops-lib", + "owner": "paisano-nix", + "ref": "v0.5.0", + "repo": "tui", "type": "github" } }, - "plutip": { + "paisano_2": { "inputs": { - "CHaP": "CHaP_4", - "cardano-node": [ - "ctl", - "cardano-node" - ], - "flake-compat": "flake-compat_14", - "hackage-nix": [ - "ctl", - "hackage-nix" - ], - "haskell-nix": [ + "nixpkgs": [ "ctl", - "haskell-nix" + "cardano-nix", + "cardano-node-8.7.3", + "std", + "nixpkgs" ], - "iohk-nix": [ + "nosys": "nosys_3", + "yants": [ "ctl", - "iohk-nix" - ], + "cardano-nix", + "cardano-node-8.7.3", + "std", + "yants" + ] + }, + "locked": { + "lastModified": 1686862844, + "narHash": "sha256-m8l/HpRBJnZ3c0F1u0IyQ3nYGWE0R9V5kfORuqZPzgk=", + "owner": "paisano-nix", + "repo": "core", + "rev": "6674b3d3577212c1eeecd30d62d52edbd000e726", + "type": "github" + }, + "original": { + "owner": "paisano-nix", + "ref": "0.1.1", + "repo": "core", + "type": "github" + } + }, + "paisano_3": { + "inputs": { + "call-flake": "call-flake", "nixpkgs": [ "ctl", + "cardano-node", + "std", "nixpkgs" + ], + "nosys": "nosys_4", + "yants": [ + "ctl", + "cardano-node", + "std", + "yants" ] }, "locked": { - "lastModified": 1695131439, - "narHash": "sha256-7ZhZUDhlFvV2us4G27iAk6lHezKS/4WA07NQn88VtQU=", - "owner": "mlabs-haskell", - "repo": "plutip", - "rev": "1bf0b547cd3689c727586abb8385c008fb2a3d1c", + "lastModified": 1708640854, + "narHash": "sha256-EpcAmvIS4ErqhXtVEfd2GPpU/E/s8CCRSfYzk6FZ/fY=", + "owner": "paisano-nix", + "repo": "core", + "rev": "adcf742bc9463c08764ca9e6955bd5e7dcf3a3fe", "type": "github" }, "original": { - "owner": "mlabs-haskell", - "ref": "gergely/version-bump", - "repo": "plutip", + "owner": "paisano-nix", + "ref": "0.2.0", + "repo": "core", "type": "github" } }, "poetry2nix": { "inputs": { - "flake-utils": "flake-utils_17", + "flake-utils": "flake-utils_32", "nixpkgs": [ "ctl", "db-sync", @@ -8535,8 +13770,8 @@ }, "pre-commit-hooks": { "inputs": { - "flake-utils": "flake-utils_23", - "nixpkgs": "nixpkgs_55" + "flake-utils": "flake-utils_38", + "nixpkgs": "nixpkgs_84" }, "locked": { "lastModified": 1639823344, @@ -8552,12 +13787,42 @@ "type": "github" } }, + "pre-commit-hooks-nix": { + "inputs": { + "flake-compat": "flake-compat_13", + "flake-utils": "flake-utils_15", + "gitignore": "gitignore", + "nixpkgs": [ + "ctl", + "cardano-nix", + "nixpkgs" + ], + "nixpkgs-stable": [ + "ctl", + "cardano-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1708018599, + "narHash": "sha256-M+Ng6+SePmA8g06CmUZWi1AjG2tFBX9WCXElBHEKnyM=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "5df5a70ad7575f6601d91f0efec95dd9bc619431", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "ragenix": { "inputs": { "agenix": "agenix_3", - "flake-utils": "flake-utils_8", - "nixpkgs": "nixpkgs_21", - "rust-overlay": "rust-overlay" + "flake-utils": "flake-utils_23", + "nixpkgs": "nixpkgs_50", + "rust-overlay": "rust-overlay_2" }, "locked": { "lastModified": 1641119695, @@ -8576,9 +13841,9 @@ "ragenix_2": { "inputs": { "agenix": "agenix_4", - "flake-utils": "flake-utils_10", - "nixpkgs": "nixpkgs_24", - "rust-overlay": "rust-overlay_2" + "flake-utils": "flake-utils_25", + "nixpkgs": "nixpkgs_53", + "rust-overlay": "rust-overlay_3" }, "locked": { "lastModified": 1645147603, @@ -8597,9 +13862,9 @@ "ragenix_3": { "inputs": { "agenix": "agenix_5", - "flake-utils": "flake-utils_12", - "nixpkgs": "nixpkgs_33", - "rust-overlay": "rust-overlay_3" + "flake-utils": "flake-utils_27", + "nixpkgs": "nixpkgs_62", + "rust-overlay": "rust-overlay_4" }, "locked": { "lastModified": 1641119695, @@ -8618,9 +13883,9 @@ "ragenix_4": { "inputs": { "agenix": "agenix_7", - "flake-utils": "flake-utils_19", - "nixpkgs": "nixpkgs_50", - "rust-overlay": "rust-overlay_4" + "flake-utils": "flake-utils_34", + "nixpkgs": "nixpkgs_79", + "rust-overlay": "rust-overlay_5" }, "locked": { "lastModified": 1641119695, @@ -8639,9 +13904,9 @@ "ragenix_5": { "inputs": { "agenix": "agenix_8", - "flake-utils": "flake-utils_21", - "nixpkgs": "nixpkgs_53", - "rust-overlay": "rust-overlay_5" + "flake-utils": "flake-utils_36", + "nixpkgs": "nixpkgs_82", + "rust-overlay": "rust-overlay_6" }, "locked": { "lastModified": 1645147603, @@ -8660,7 +13925,7 @@ "root": { "inputs": { "ctl": "ctl", - "flake-compat": "flake-compat_15", + "flake-compat": "flake-compat_26", "nixpkgs": [ "ctl", "nixpkgs" @@ -8668,6 +13933,40 @@ } }, "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1645205556, + "narHash": "sha256-e4lZW3qRyOEJ+vLKFQP7m2Dxh5P44NrnekZYLxlucww=", + "owner": "rust-analyzer", + "repo": "rust-analyzer", + "rev": "acf5874b39f3dc5262317a6074d9fc7285081161", + "type": "github" + }, + "original": { + "owner": "rust-analyzer", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-analyzer-src_2": { + "flake": false, + "locked": { + "lastModified": 1677221702, + "narHash": "sha256-1M+58rC4eTCWNmmX0hQVZP20t3tfYNunl9D/PrGUyGE=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "f5401f620699b26ed9d47a1d2e838143a18dbe3b", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-analyzer-src_3": { "flake": false, "locked": { "lastModified": 1645024434, @@ -8684,7 +13983,7 @@ "type": "github" } }, - "rust-analyzer-src_2": { + "rust-analyzer-src_4": { "flake": false, "locked": { "lastModified": 1649178056, @@ -8701,7 +14000,7 @@ "type": "github" } }, - "rust-analyzer-src_3": { + "rust-analyzer-src_5": { "flake": false, "locked": { "lastModified": 1645024434, @@ -8718,7 +14017,7 @@ "type": "github" } }, - "rust-analyzer-src_4": { + "rust-analyzer-src_6": { "flake": false, "locked": { "lastModified": 1660579619, @@ -8735,7 +14034,7 @@ "type": "github" } }, - "rust-analyzer-src_5": { + "rust-analyzer-src_7": { "flake": false, "locked": { "lastModified": 1645024434, @@ -8752,7 +14051,7 @@ "type": "github" } }, - "rust-analyzer-src_6": { + "rust-analyzer-src_8": { "flake": false, "locked": { "lastModified": 1649178056, @@ -8770,6 +14069,41 @@ } }, "rust-overlay": { + "inputs": { + "flake-utils": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "paisano-mdbook-preprocessor", + "crane", + "flake-utils" + ], + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "paisano-mdbook-preprocessor", + "crane", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1675391458, + "narHash": "sha256-ukDKZw922BnK5ohL9LhwtaDAdCsJL7L6ScNEyF1lO9w=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "383a4acfd11d778d5c2efcf28376cbd845eeaedf", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_2": { "inputs": { "flake-utils": [ "ctl", @@ -8806,7 +14140,7 @@ "type": "github" } }, - "rust-overlay_2": { + "rust-overlay_3": { "inputs": { "flake-utils": [ "ctl", @@ -8841,7 +14175,7 @@ "type": "github" } }, - "rust-overlay_3": { + "rust-overlay_4": { "inputs": { "flake-utils": [ "ctl", @@ -8874,7 +14208,7 @@ "type": "github" } }, - "rust-overlay_4": { + "rust-overlay_5": { "inputs": { "flake-utils": [ "ctl", @@ -8909,7 +14243,7 @@ "type": "github" } }, - "rust-overlay_5": { + "rust-overlay_6": { "inputs": { "flake-utils": [ "ctl", @@ -8929,20 +14263,105 @@ ] }, "locked": { - "lastModified": 1644633594, - "narHash": "sha256-Te6mBYYirUwsoqENvVx1K1EEoRq2CKrTnNkWF42jNgE=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "14c48021a9a5fe6ea8ae6b21c15caa106afa9d19", + "lastModified": 1644633594, + "narHash": "sha256-Te6mBYYirUwsoqENvVx1K1EEoRq2CKrTnNkWF42jNgE=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "14c48021a9a5fe6ea8ae6b21c15caa106afa9d19", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "secp256k1": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", + "type": "github" + }, + "original": { + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", + "type": "github" + } + }, + "secp256k1_2": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", + "type": "github" + }, + "original": { + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", + "type": "github" + } + }, + "secp256k1_3": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", + "type": "github" + }, + "original": { + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", + "type": "github" + } + }, + "secp256k1_4": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", + "type": "github" + }, + "original": { + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", + "type": "github" + } + }, + "secp256k1_5": { + "flake": false, + "locked": { + "lastModified": 1683999695, + "narHash": "sha256-9nJJVENMXjXEJZzw8DHzin1DkFkF8h9m/c6PuM7Uk4s=", + "owner": "bitcoin-core", + "repo": "secp256k1", + "rev": "acf5c55ae6a94e5ca847e07def40427547876101", "type": "github" }, "original": { - "owner": "oxalica", - "repo": "rust-overlay", + "owner": "bitcoin-core", + "ref": "v0.3.2", + "repo": "secp256k1", "type": "github" } }, - "secp256k1": { + "secp256k1_6": { "flake": false, "locked": { "lastModified": 1683999695, @@ -8959,7 +14378,7 @@ "type": "github" } }, - "secp256k1_2": { + "secp256k1_7": { "flake": false, "locked": { "lastModified": 1683999695, @@ -9010,7 +14429,143 @@ "type": "github" } }, + "sodium_3": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sodium_4": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sodium_5": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sodium_6": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sodium_7": { + "flake": false, + "locked": { + "lastModified": 1675156279, + "narHash": "sha256-0uRcN5gvMwO7MCXVYnoqG/OmeBFi8qRVnDWJLnBb9+Y=", + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "libsodium", + "rev": "dbb48cce5429cb6585c9034f002568964f1ce567", + "type": "github" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": "nixpkgs_11", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1690199016, + "narHash": "sha256-yTLL72q6aqGmzHq+C3rDp3rIjno7EJZkFLof6Ika7cE=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "c36df4fe4bf4bb87759b1891cab21e7a05219500", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, + "stable": { + "locked": { + "lastModified": 1669735802, + "narHash": "sha256-qtG/o/i5ZWZLmXw108N2aPiVsxOcidpHJYNkT45ry9Q=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "731cc710aeebecbf45a258e977e8b68350549522", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, "stackage": { + "flake": false, + "locked": { + "lastModified": 1701043780, + "narHash": "sha256-d5CYT7WGEaL6IFNmUg4JUb+onxI/tO1qgHs/TCIKB3A=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "cb49435b81adf0549589c51f39b5b38b4369f106", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "stackage_2": { "flake": false, "locked": { "lastModified": 1685491814, @@ -9026,7 +14581,39 @@ "type": "github" } }, - "stackage_2": { + "stackage_3": { + "flake": false, + "locked": { + "lastModified": 1700438989, + "narHash": "sha256-x+7Qtboko7ds8CU8pq2sIZiD45DauYoX9LxBfwQr/hs=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "9c2015334cc77837b8454b3b10ef4f711a256f6f", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "stackage_4": { + "flake": false, + "locked": { + "lastModified": 1718756571, + "narHash": "sha256-8rL8viTbuE9/yV1of6SWp2tHmhVMD2UmkOfmN5KDbKg=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "027672fb6fd45828b0e623c8152572d4058429ad", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "stackage_5": { "flake": false, "locked": { "lastModified": 1646010978, @@ -9042,7 +14629,7 @@ "type": "github" } }, - "stackage_3": { + "stackage_6": { "flake": false, "locked": { "lastModified": 1655255731, @@ -9058,7 +14645,7 @@ "type": "github" } }, - "stackage_4": { + "stackage_7": { "flake": false, "locked": { "lastModified": 1659402917, @@ -9074,94 +14661,316 @@ "type": "github" } }, - "stackage_5": { - "flake": false, + "stackage_8": { + "flake": false, + "locked": { + "lastModified": 1650936094, + "narHash": "sha256-9ibS+iszPXe3HQd8rexVfrQeO4JkXSPokhbPiJ/Lags=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "85f94546f85fb9b92080f958bec655a364b2f0e5", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "stackage_9": { + "flake": false, + "locked": { + "lastModified": 1721952692, + "narHash": "sha256-UXiGzFWWOZMZRYkhS0oVaNK/v8Rr5PxxsM2qV1T6iJI=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "73bfeeb1dccad2858f22f6f57b6571b10579ed2e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "statix": { + "inputs": { + "fenix": "fenix", + "nixpkgs": "nixpkgs_4" + }, + "locked": { + "lastModified": 1676888642, + "narHash": "sha256-C73LOMVVCkeL0jA5xN7klLEDEB4NkuiATEJY4A/tIyM=", + "owner": "nerdypepper", + "repo": "statix", + "rev": "3c7136a23f444db252a556928c1489869ca3ab4e", + "type": "github" + }, + "original": { + "owner": "nerdypepper", + "repo": "statix", + "type": "github" + } + }, + "std": { + "inputs": { + "arion": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "blank" + ], + "blank": "blank", + "devshell": "devshell", + "dmerge": "dmerge", + "flake-utils": "flake-utils_8", + "incl": "incl", + "makes": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "blank" + ], + "microvm": [ + "ctl", + "cardano-nix", + "cardano-node-8.1.1", + "tullia", + "std", + "blank" + ], + "n2c": "n2c", + "nixago": "nixago", + "nixpkgs": "nixpkgs_21", + "nosys": "nosys", + "yants": "yants" + }, + "locked": { + "lastModified": 1674526466, + "narHash": "sha256-tMTaS0bqLx6VJ+K+ZT6xqsXNpzvSXJTmogkraBGzymg=", + "owner": "divnix", + "repo": "std", + "rev": "516387e3d8d059b50e742a2ff1909ed3c8f82826", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "std", + "type": "github" + } + }, + "std_2": { + "inputs": { + "arion": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "blank": "blank_2", + "devshell": "devshell_2", + "dmerge": "dmerge_2", + "flake-utils": "flake-utils_11", + "incl": "incl_2", + "makes": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "microvm": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "n2c": "n2c_2", + "nixago": "nixago_2", + "nixpkgs": "nixpkgs_24", + "paisano": "paisano", + "paisano-tui": "paisano-tui", + "yants": "yants_2" + }, "locked": { - "lastModified": 1650936094, - "narHash": "sha256-9ibS+iszPXe3HQd8rexVfrQeO4JkXSPokhbPiJ/Lags=", - "owner": "input-output-hk", - "repo": "stackage.nix", - "rev": "85f94546f85fb9b92080f958bec655a364b2f0e5", + "lastModified": 1677533652, + "narHash": "sha256-H37dcuWAGZs6Yl9mewMNVcmSaUXR90/bABYFLT/nwhk=", + "owner": "divnix", + "repo": "std", + "rev": "490542f624412662e0411d8cb5a9af988ef56633", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "stackage.nix", + "owner": "divnix", + "repo": "std", "type": "github" } }, - "stackage_6": { - "flake": false, + "std_3": { + "inputs": { + "arion": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "blank": "blank_3", + "devshell": "devshell_3", + "dmerge": "dmerge_3", + "flake-utils": "flake-utils_13", + "haumea": "haumea", + "incl": "incl_3", + "makes": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "microvm": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "std", + "blank" + ], + "n2c": "n2c_3", + "nixago": "nixago_3", + "nixpkgs": "nixpkgs_29", + "paisano": "paisano_2", + "paisano-mdbook-preprocessor": "paisano-mdbook-preprocessor", + "paisano-tui": "paisano-tui_2", + "yants": "yants_3" + }, "locked": { - "lastModified": 1702426166, - "narHash": "sha256-j7wjtnR3HjT+OOq4GOWQMG+LufhAmz7CNDTJDW7ouXE=", - "owner": "input-output-hk", - "repo": "stackage.nix", - "rev": "8f4b266959e3087825631fb8c7b2ef2f4c915ed9", + "lastModified": 1687300684, + "narHash": "sha256-oBqbss0j+B568GoO3nF2BCoPEgPxUjxfZQGynW6mhEk=", + "owner": "divnix", + "repo": "std", + "rev": "80e5792eae98353a97ab1e85f3fba2784e4a3690", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "stackage.nix", + "owner": "divnix", + "repo": "std", "type": "github" } }, - "stackage_7": { - "flake": false, + "std_4": { + "inputs": { + "blank": "blank_4", + "devshell": "devshell_5", + "dmerge": "dmerge_4", + "flake-utils": "flake-utils_18", + "makes": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor", + "microvm": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "blank" + ], + "n2c": "n2c_4", + "nixago": "nixago_4", + "nixpkgs": "nixpkgs_33", + "yants": "yants_4" + }, "locked": { - "lastModified": 1654219171, - "narHash": "sha256-5kp4VTlum+AMmoIbhtrcVSEfYhR4oTKSrwe1iysD8uU=", - "owner": "input-output-hk", - "repo": "stackage.nix", - "rev": "6d1fc076976ce6c45da5d077bf882487076efe5c", + "lastModified": 1665513321, + "narHash": "sha256-D6Pacw9yf/HMs84KYuCxHXnNDL7v43gtcka5URagFqE=", + "owner": "divnix", + "repo": "std", + "rev": "94a90eedb9cfc115b12ae8f6622d9904788559e4", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "stackage.nix", + "owner": "divnix", + "repo": "std", "type": "github" } }, - "std": { + "std_5": { "inputs": { "arion": [ "ctl", "cardano-node", - "tullia", "std", "blank" ], - "blank": "blank", - "devshell": "devshell", - "dmerge": "dmerge", - "flake-utils": "flake-utils_5", - "incl": "incl", + "blank": "blank_5", + "devshell": [ + "ctl", + "cardano-node", + "std", + "blank" + ], + "dmerge": "dmerge_5", + "haumea": "haumea_2", + "incl": "incl_4", + "lib": "lib", "makes": [ "ctl", "cardano-node", - "tullia", "std", "blank" ], "microvm": [ "ctl", "cardano-node", - "tullia", "std", "blank" ], - "n2c": "n2c", - "nixago": "nixago", - "nixpkgs": "nixpkgs_8", - "nosys": "nosys", - "yants": "yants" + "n2c": [ + "ctl", + "cardano-node", + "std", + "blank" + ], + "nixago": [ + "ctl", + "cardano-node", + "std", + "blank" + ], + "nixpkgs": "nixpkgs_37", + "paisano": "paisano_3", + "paisano-tui": "paisano-tui_3", + "terranix": [ + "ctl", + "cardano-node", + "std", + "blank" + ], + "yants": "yants_5" }, "locked": { - "lastModified": 1674526466, - "narHash": "sha256-tMTaS0bqLx6VJ+K+ZT6xqsXNpzvSXJTmogkraBGzymg=", + "lastModified": 1715201063, + "narHash": "sha256-LcLYV5CDhIiJs3MfxGZFKsXPR4PtfnY4toZ75GM+2Pw=", "owner": "divnix", "repo": "std", - "rev": "516387e3d8d059b50e742a2ff1909ed3c8f82826", + "rev": "b6924a7d37a46fc1dda8efe405040e27ecf1bbd6", "type": "github" }, "original": { @@ -9170,15 +14979,15 @@ "type": "github" } }, - "std_2": { + "std_6": { "inputs": { - "devshell": "devshell_7", - "dmerge": "dmerge_2", - "flake-utils": "flake-utils_13", - "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor", - "nixago": "nixago_2", - "nixpkgs": "nixpkgs_34", - "yants": "yants_3" + "devshell": "devshell_11", + "dmerge": "dmerge_6", + "flake-utils": "flake-utils_28", + "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor_2", + "nixago": "nixago_5", + "nixpkgs": "nixpkgs_63", + "yants": "yants_7" }, "locked": { "lastModified": 1661370377, @@ -9194,15 +15003,15 @@ "type": "github" } }, - "std_3": { + "std_7": { "inputs": { - "devshell": "devshell_15", - "dmerge": "dmerge_3", - "flake-utils": "flake-utils_29", - "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor_2", - "nixago": "nixago_3", - "nixpkgs": "nixpkgs_64", - "yants": "yants_5" + "devshell": "devshell_19", + "dmerge": "dmerge_7", + "flake-utils": "flake-utils_44", + "mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor_3", + "nixago": "nixago_6", + "nixpkgs": "nixpkgs_93", + "yants": "yants_9" }, "locked": { "lastModified": 1661367957, @@ -9218,11 +15027,11 @@ "type": "github" } }, - "std_4": { + "std_8": { "inputs": { - "devshell": "devshell_16", - "nixpkgs": "nixpkgs_67", - "yants": "yants_6" + "devshell": "devshell_20", + "nixpkgs": "nixpkgs_96", + "yants": "yants_10" }, "locked": { "lastModified": 1652784712, @@ -9298,6 +15107,21 @@ "type": "github" } }, + "stdlib_13": { + "locked": { + "lastModified": 1590026685, + "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", + "owner": "manveru", + "repo": "nix-lib", + "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "type": "github" + }, + "original": { + "owner": "manveru", + "repo": "nix-lib", + "type": "github" + } + }, "stdlib_2": { "locked": { "lastModified": 1590026685, @@ -9375,53 +15199,143 @@ }, "stdlib_7": { "locked": { - "lastModified": 1590026685, - "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", - "owner": "manveru", - "repo": "nix-lib", - "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "lastModified": 1590026685, + "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", + "owner": "manveru", + "repo": "nix-lib", + "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "type": "github" + }, + "original": { + "owner": "manveru", + "repo": "nix-lib", + "type": "github" + } + }, + "stdlib_8": { + "locked": { + "lastModified": 1590026685, + "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", + "owner": "manveru", + "repo": "nix-lib", + "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "type": "github" + }, + "original": { + "owner": "manveru", + "repo": "nix-lib", + "type": "github" + } + }, + "stdlib_9": { + "locked": { + "lastModified": 1590026685, + "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", + "owner": "manveru", + "repo": "nix-lib", + "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "type": "github" + }, + "original": { + "owner": "manveru", + "repo": "nix-lib", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "manveru", - "repo": "nix-lib", + "owner": "nix-systems", + "repo": "default", "type": "github" } }, - "stdlib_8": { + "systems_5": { "locked": { - "lastModified": 1590026685, - "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", - "owner": "manveru", - "repo": "nix-lib", - "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "manveru", - "repo": "nix-lib", + "owner": "nix-systems", + "repo": "default", "type": "github" } }, - "stdlib_9": { + "systems_6": { "locked": { - "lastModified": 1590026685, - "narHash": "sha256-E5INrVvYX/P/UpcoUFDAsuHem+lsqT+/teBs9O7oc9Q=", - "owner": "manveru", - "repo": "nix-lib", - "rev": "99088cf7febcdb21afd375a335dcafa959bef3ed", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "manveru", - "repo": "nix-lib", + "owner": "nix-systems", + "repo": "default", "type": "github" } }, "tailwind-haskell": { "inputs": { - "flake-utils": "flake-utils_24", - "nixpkgs": "nixpkgs_58" + "flake-utils": "flake-utils_39", + "nixpkgs": "nixpkgs_87" }, "locked": { "lastModified": 1654211622, @@ -9438,28 +15352,38 @@ "type": "github" } }, + "terraform-providers": { + "inputs": { + "nixpkgs": "nixpkgs_12" + }, + "locked": { + "lastModified": 1695893013, + "narHash": "sha256-+5EuXNXwxpTiOEGCbZWtZCU75WcVwnS89heLa5xJ2K0=", + "owner": "nix-community", + "repo": "nixpkgs-terraform-providers-bin", + "rev": "6c6865ae6f9bff7aaa4e86c875f520f2aca65c0d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs-terraform-providers-bin", + "type": "github" + } + }, "terranix": { "inputs": { "bats-assert": "bats-assert", "bats-support": "bats-support", - "flake-utils": "flake-utils_9", - "nixpkgs": [ - "ctl", - "db-sync", - "cardano-world", - "bitte", - "capsules", - "bitte", - "blank" - ], + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_13", "terranix-examples": "terranix-examples" }, "locked": { - "lastModified": 1637158331, - "narHash": "sha256-x5LEKtSkVq+D3BXHDBOb2wdCLxAhVmXIWONRi9lxDPg=", + "lastModified": 1684906298, + "narHash": "sha256-pNuJxmVMGbBHw7pa+Bx0HY0orXIXoyyAXOKuQ1zpfus=", "owner": "terranix", "repo": "terranix", - "rev": "34198bb154af86d2a559446f10d7339e53126abe", + "rev": "c0dd15076856c6cb425795b8c7d5d37d3a1e922a", "type": "github" }, "original": { @@ -9513,16 +15437,33 @@ "type": "github" } }, + "terranix-examples_4": { + "locked": { + "lastModified": 1636300201, + "narHash": "sha256-0n1je1WpiR6XfCsvi8ZK7GrpEnMl+DpwhWaO1949Vbc=", + "owner": "terranix", + "repo": "terranix-examples", + "rev": "a934aa1cf88f6bd6c6ddb4c77b77ec6e1660bd5e", + "type": "github" + }, + "original": { + "owner": "terranix", + "repo": "terranix-examples", + "type": "github" + } + }, "terranix_2": { "inputs": { "bats-assert": "bats-assert_2", "bats-support": "bats-support_2", - "flake-utils": "flake-utils_14", + "flake-utils": "flake-utils_24", "nixpkgs": [ "ctl", "db-sync", "cardano-world", "bitte", + "capsules", + "bitte", "blank" ], "terranix-examples": "terranix-examples_2" @@ -9545,12 +15486,11 @@ "inputs": { "bats-assert": "bats-assert_3", "bats-support": "bats-support_3", - "flake-utils": "flake-utils_20", + "flake-utils": "flake-utils_29", "nixpkgs": [ "ctl", "db-sync", "cardano-world", - "capsules", "bitte", "blank" ], @@ -9570,54 +15510,278 @@ "type": "github" } }, - "tullia": { - "inputs": { - "nix-nomad": "nix-nomad", - "nix2container": "nix2container_2", - "nixpkgs": "nixpkgs_7", - "std": "std" - }, + "terranix_4": { + "inputs": { + "bats-assert": "bats-assert_4", + "bats-support": "bats-support_4", + "flake-utils": "flake-utils_35", + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "capsules", + "bitte", + "blank" + ], + "terranix-examples": "terranix-examples_4" + }, + "locked": { + "lastModified": 1637158331, + "narHash": "sha256-x5LEKtSkVq+D3BXHDBOb2wdCLxAhVmXIWONRi9lxDPg=", + "owner": "terranix", + "repo": "terranix", + "rev": "34198bb154af86d2a559446f10d7339e53126abe", + "type": "github" + }, + "original": { + "owner": "terranix", + "repo": "terranix", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": "nixpkgs_5" + }, + "locked": { + "lastModified": 1683117219, + "narHash": "sha256-IyNRNRxw0slA3VQySVA7QPXHMOxlbx0ePWvj9oln+Wk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "c8c3731dc404f837f38f89c2c5ffc2afc02e249d", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_2": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-db-sync", + "cardano-parts", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1691440708, + "narHash": "sha256-c7Cc08vJ0IPFgIERpTdO2xvDHQNL7Uf5iXT0GlYO6vo=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "2a535809ac5c9a32288f4d3b938296e056d948cc", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_3": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697388351, + "narHash": "sha256-63N2eBpKaziIy4R44vjpUu8Nz5fCJY7okKrkixvDQmY=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "aae39f64f5ecbe89792d05eacea5cb241891292a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "tullia": { + "inputs": { + "nix-nomad": "nix-nomad", + "nix2container": "nix2container_2", + "nixpkgs": "nixpkgs_20", + "std": "std" + }, + "locked": { + "lastModified": 1675695930, + "narHash": "sha256-B7rEZ/DBUMlK1AcJ9ajnAPPxqXY6zW2SBX+51bZV0Ac=", + "owner": "input-output-hk", + "repo": "tullia", + "rev": "621365f2c725608f381b3ad5b57afef389fd4c31", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "tullia", + "type": "github" + } + }, + "tullia_2": { + "inputs": { + "nix-nomad": "nix-nomad_2", + "nix2container": "nix2container_3", + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "nixpkgs" + ], + "std": "std_2" + }, + "locked": { + "lastModified": 1684859161, + "narHash": "sha256-wOKutImA7CRL0rN+Ng80E72fD5FkVub7LLP2k9NICpg=", + "owner": "input-output-hk", + "repo": "tullia", + "rev": "2964cff1a16eefe301bdddb508c49d94d04603d6", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "tullia", + "type": "github" + } + }, + "tullia_3": { + "inputs": { + "nix-nomad": "nix-nomad_3", + "nix2container": "nix2container_5", + "nixpkgs": [ + "ctl", + "cardano-node", + "cardano-automation", + "nixpkgs" + ], + "std": "std_4" + }, + "locked": { + "lastModified": 1668711738, + "narHash": "sha256-CBjky16o9pqsGE1bWu6nRlRajgSXMEk+yaFQLibqXcE=", + "owner": "input-output-hk", + "repo": "tullia", + "rev": "ead1f515c251f0e060060ef0e2356a51d3dfe4b0", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "tullia", + "type": "github" + } + }, + "tullia_4": { + "inputs": { + "nix2container": "nix2container_7", + "nixpkgs": "nixpkgs_95", + "std": "std_8" + }, + "locked": { + "lastModified": 1657811465, + "narHash": "sha256-KHNWwKuUIG08CUg/ol81zf26RRlnsQsyqMr63vXcCes=", + "owner": "input-output-hk", + "repo": "tullia", + "rev": "f025fcf3676d1d1281de184e89c5f7c8e7f74ebe", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "tullia", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_10": { + "locked": { + "lastModified": 1633020561, + "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", + "owner": "kreisys", + "repo": "flake-utils", + "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "type": "github" + }, + "original": { + "owner": "kreisys", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_11": { + "locked": { + "lastModified": 1633020561, + "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", + "owner": "kreisys", + "repo": "flake-utils", + "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "type": "github" + }, + "original": { + "owner": "kreisys", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_12": { "locked": { - "lastModified": 1675695930, - "narHash": "sha256-B7rEZ/DBUMlK1AcJ9ajnAPPxqXY6zW2SBX+51bZV0Ac=", - "owner": "input-output-hk", - "repo": "tullia", - "rev": "621365f2c725608f381b3ad5b57afef389fd4c31", + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "tullia", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "tullia_2": { - "inputs": { - "nix2container": "nix2container_3", - "nixpkgs": "nixpkgs_66", - "std": "std_4" - }, + "utils_13": { "locked": { - "lastModified": 1657811465, - "narHash": "sha256-KHNWwKuUIG08CUg/ol81zf26RRlnsQsyqMr63vXcCes=", - "owner": "input-output-hk", - "repo": "tullia", - "rev": "f025fcf3676d1d1281de184e89c5f7c8e7f74ebe", + "lastModified": 1633020561, + "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", + "owner": "kreisys", + "repo": "flake-utils", + "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "tullia", + "owner": "kreisys", + "repo": "flake-utils", "type": "github" } }, - "utils": { + "utils_14": { "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "lastModified": 1637014545, + "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", "type": "github" }, "original": { @@ -9626,7 +15790,7 @@ "type": "github" } }, - "utils_10": { + "utils_15": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9641,7 +15805,7 @@ "type": "github" } }, - "utils_11": { + "utils_16": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9656,7 +15820,7 @@ "type": "github" } }, - "utils_12": { + "utils_17": { "locked": { "lastModified": 1638122382, "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", @@ -9671,7 +15835,7 @@ "type": "github" } }, - "utils_13": { + "utils_18": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9686,7 +15850,7 @@ "type": "github" } }, - "utils_14": { + "utils_19": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9701,7 +15865,22 @@ "type": "github" } }, - "utils_15": { + "utils_2": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_20": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9716,7 +15895,7 @@ "type": "github" } }, - "utils_16": { + "utils_21": { "locked": { "lastModified": 1644229661, "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", @@ -9731,7 +15910,7 @@ "type": "github" } }, - "utils_17": { + "utils_22": { "locked": { "lastModified": 1637014545, "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", @@ -9746,7 +15925,7 @@ "type": "github" } }, - "utils_18": { + "utils_23": { "locked": { "lastModified": 1601282935, "narHash": "sha256-WQAFV6sGGQxrRs3a+/Yj9xUYvhTpukQJIcMbIi7LCJ4=", @@ -9761,7 +15940,7 @@ "type": "github" } }, - "utils_19": { + "utils_24": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9776,22 +15955,7 @@ "type": "github" } }, - "utils_2": { - "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "utils_20": { + "utils_25": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9806,7 +15970,7 @@ "type": "github" } }, - "utils_21": { + "utils_26": { "locked": { "lastModified": 1638122382, "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", @@ -9821,7 +15985,7 @@ "type": "github" } }, - "utils_22": { + "utils_27": { "locked": { "lastModified": 1633020561, "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", @@ -9836,7 +16000,7 @@ "type": "github" } }, - "utils_23": { + "utils_28": { "locked": { "lastModified": 1638122382, "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", @@ -9853,11 +16017,11 @@ }, "utils_3": { "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "owner": "numtide", "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { @@ -9868,11 +16032,11 @@ }, "utils_4": { "locked": { - "lastModified": 1601282935, - "narHash": "sha256-WQAFV6sGGQxrRs3a+/Yj9xUYvhTpukQJIcMbIi7LCJ4=", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "588973065fce51f4763287f0fda87a174d78bf48", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { @@ -9883,41 +16047,44 @@ }, "utils_5": { "locked": { - "lastModified": 1633020561, - "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", - "owner": "kreisys", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", "repo": "flake-utils", - "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { - "owner": "kreisys", + "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "utils_6": { "locked": { - "lastModified": 1633020561, - "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", - "owner": "kreisys", + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", "repo": "flake-utils", - "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", "type": "github" }, "original": { - "owner": "kreisys", + "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "utils_7": { + "inputs": { + "systems": "systems_6" + }, "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -9928,26 +16095,26 @@ }, "utils_8": { "locked": { - "lastModified": 1633020561, - "narHash": "sha256-4uAiRqL9nP3d/NQ8VBqjQ5iZypHaM+X/FyWpXVXkwTA=", - "owner": "kreisys", + "lastModified": 1637014545, + "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "owner": "numtide", "repo": "flake-utils", - "rev": "2923532a276a5595ee64376ec1b3db6ed8503c52", + "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", "type": "github" }, "original": { - "owner": "kreisys", + "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "utils_9": { "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "lastModified": 1601282935, + "narHash": "sha256-WQAFV6sGGQxrRs3a+/Yj9xUYvhTpukQJIcMbIi7LCJ4=", "owner": "numtide", "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "rev": "588973065fce51f4763287f0fda87a174d78bf48", "type": "github" }, "original": { @@ -9994,7 +16161,8 @@ "inputs": { "nixpkgs": [ "ctl", - "cardano-node", + "cardano-nix", + "cardano-node-8.1.1", "tullia", "std", "nixpkgs" @@ -10014,9 +16182,16 @@ "type": "github" } }, - "yants_2": { + "yants_10": { "inputs": { - "nixpkgs": "nixpkgs_25" + "nixpkgs": [ + "ctl", + "db-sync", + "cardano-world", + "tullia", + "std", + "nixpkgs" + ] }, "locked": { "lastModified": 1645126146, @@ -10032,23 +16207,49 @@ "type": "github" } }, + "yants_2": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-nix", + "cardano-node-8.7.3", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1667096281, + "narHash": "sha256-wRRec6ze0gJHmGn6m57/zhz/Kdvp9HS4Nl5fkQ+uIuA=", + "owner": "divnix", + "repo": "yants", + "rev": "d18f356ec25cb94dc9c275870c3a7927a10f8c3c", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "yants", + "type": "github" + } + }, "yants_3": { "inputs": { "nixpkgs": [ "ctl", - "db-sync", - "cardano-world", - "bitte", + "cardano-nix", + "cardano-node-8.7.3", "std", + "haumea", "nixpkgs" ] }, "locked": { - "lastModified": 1645126146, - "narHash": "sha256-XQ1eg4gzXoc7Tl8iXak1uCt3KnsTyxqPtLE+vOoDnrQ=", + "lastModified": 1686863218, + "narHash": "sha256-kooxYm3/3ornWtVBNHM3Zh020gACUyFX2G0VQXnB+mk=", "owner": "divnix", "repo": "yants", - "rev": "77df2be1b3cce9f571c6cf451f786b266a6869cc", + "rev": "8f0da0dba57149676aa4817ec0c880fbde7a648d", "type": "github" }, "original": { @@ -10059,7 +16260,55 @@ }, "yants_4": { "inputs": { - "nixpkgs": "nixpkgs_60" + "nixpkgs": [ + "ctl", + "cardano-node", + "cardano-automation", + "tullia", + "std", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660507851, + "narHash": "sha256-BKjq7JnVuUR/xDtcv6Vm9GYGKAblisXrAgybor9hT/s=", + "owner": "divnix", + "repo": "yants", + "rev": "0b895ca02a8fa72bad50b454cb3e7d8a66407c96", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "yants", + "type": "github" + } + }, + "yants_5": { + "inputs": { + "nixpkgs": [ + "ctl", + "cardano-node", + "std", + "lib" + ] + }, + "locked": { + "lastModified": 1686863218, + "narHash": "sha256-kooxYm3/3ornWtVBNHM3Zh020gACUyFX2G0VQXnB+mk=", + "owner": "divnix", + "repo": "yants", + "rev": "8f0da0dba57149676aa4817ec0c880fbde7a648d", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "yants", + "type": "github" + } + }, + "yants_6": { + "inputs": { + "nixpkgs": "nixpkgs_54" }, "locked": { "lastModified": 1645126146, @@ -10075,12 +16324,13 @@ "type": "github" } }, - "yants_5": { + "yants_7": { "inputs": { "nixpkgs": [ "ctl", "db-sync", "cardano-world", + "bitte", "std", "nixpkgs" ] @@ -10099,13 +16349,30 @@ "type": "github" } }, - "yants_6": { + "yants_8": { + "inputs": { + "nixpkgs": "nixpkgs_89" + }, + "locked": { + "lastModified": 1645126146, + "narHash": "sha256-XQ1eg4gzXoc7Tl8iXak1uCt3KnsTyxqPtLE+vOoDnrQ=", + "owner": "divnix", + "repo": "yants", + "rev": "77df2be1b3cce9f571c6cf451f786b266a6869cc", + "type": "github" + }, + "original": { + "owner": "divnix", + "repo": "yants", + "type": "github" + } + }, + "yants_9": { "inputs": { "nixpkgs": [ "ctl", "db-sync", "cardano-world", - "tullia", "std", "nixpkgs" ] diff --git a/templates/ctl-scaffold/flake.nix b/templates/ctl-scaffold/flake.nix index c1104f2e79..1a2ea7735e 100644 --- a/templates/ctl-scaffold/flake.nix +++ b/templates/ctl-scaffold/flake.nix @@ -16,7 +16,7 @@ type = "github"; owner = "Plutonomicon"; repo = "cardano-transaction-lib"; - rev = "7d533241367081fa69ec5f0ec8f50e00c39430c2"; + rev = "01708d64e858a2ed3cbbc7a9a235d3acf79a7b91"; }; # To use the same version of `nixpkgs` as we do nixpkgs.follows = "ctl/nixpkgs"; @@ -158,7 +158,7 @@ pkgs = nixpkgsFor system; in { - ctl-scaffold-plutip-test = (psProjectFor pkgs).runPlutipTest { + ctl-scaffold-local-testnet-test = (psProjectFor pkgs).runLocalTestnetTest { testMain = "Test.Scaffold.Main"; }; diff --git a/templates/ctl-scaffold/package-lock.json b/templates/ctl-scaffold/package-lock.json index 7b3db0184c..95b6916926 100644 --- a/templates/ctl-scaffold/package-lock.json +++ b/templates/ctl-scaffold/package-lock.json @@ -9,26 +9,22 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "@emurgo/cardano-message-signing-browser": "1.0.1", - "@emurgo/cardano-message-signing-nodejs": "1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc-browser": "^1.0.6", - "@mlabs-haskell/cardano-serialization-lib-gc-nodejs": "^1.0.6", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1", + "@mlabs-haskell/cardano-message-signing": "^1.0.1", + "@mlabs-haskell/cardano-serialization-lib-gc": "12.0.0-alpha.31", "@mlabs-haskell/json-bigint": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "1.0.29-alpha", "@noble/secp256k1": "^1.7.0", - "apply-args-browser": "0.0.1", - "apply-args-nodejs": "0.0.1", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", "bip39": "^3.1.0", - "blakejs": "1.2.1", "bufferutil": "4.0.5", - "jssha": "3.2.0", + "isomorphic-ws": "^5.0.0", "puppeteer-core": "^15.3.2", "reconnecting-websocket": "4.4.0", "uniqid": "5.4.0", "utf-8-validate": "^5.0.10", - "ws": "8.4.0", + "web-encoding": "^1.1.5", + "ws": "^8.16.0", "xhr2": "0.2.1" }, "devDependencies": { @@ -62,14 +58,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "node_modules/@emurgo/cardano-serialization-lib-browser": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.4.0.tgz", - "integrity": "sha512-VWMvLRBFo7MAYh42zledURFs5BpMTWvkP4DzsLNbyJxZlwjDS+bPyehJVyGc116d2gq8NHFmANbfdeuK8ffJ7A==" + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-beta.1.tgz", + "integrity": "sha512-Fj56XnZe+ilFVgf66SB6ajQXf0rtH9o0GmICLM9qahLDZ2kAPsVu31PbbQ0YWpQB8SlDGLZE5f9Pf3Lx7cc7oA==" }, "node_modules/@emurgo/cardano-serialization-lib-nodejs": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.4.0.tgz", - "integrity": "sha512-dMiofDcqv+IrAITCgWBZmsMLqwv2xImDsJDSrKiYYG1zRKaL8XfMOxx6S0WEnKVj5/343Q5FFURYcSu3iBRNMQ==" + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-beta.1.tgz", + "integrity": "sha512-4BE7mSvSDWAmTXbzvNZg7NnaBoECv/QxsrNVKXdbaom5J9OhnnwvX3xhbEv98FAU2Awma8tLn9sHELZ46p2zbg==" }, "node_modules/@esbuild/android-arm": { "version": "0.18.11", @@ -493,34 +489,54 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, - "node_modules/@mlabs-haskell/cardano-serialization-lib-gc-browser": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc-browser/-/cardano-serialization-lib-gc-browser-1.0.6.tgz", - "integrity": "sha512-b7dLrrhjUJSdsmjzariCZO734NB+M/ONLGBiQ/TQzMRtsMydqSFQg6WbMdwYPustoNmQOg6a8bm9+RgllqdmFw==", + "node_modules/@mlabs-haskell/cardano-message-signing": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-message-signing/-/cardano-message-signing-1.0.1.tgz", + "integrity": "sha512-LNX+Msq1rJ86d5mmaR2Om5tUqB0ZthfE69fpsZcxOYDHNw5s+qtcCyNEmzAWfHC+uIJ4NDEJA8Gk2RfWto7ChA==", "dependencies": { - "@emurgo/cardano-serialization-lib-browser": "^11.2.1", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1" + "@emurgo/cardano-message-signing-browser": "^1.0.1", + "@emurgo/cardano-message-signing-nodejs": "^1.0.1" } }, - "node_modules/@mlabs-haskell/cardano-serialization-lib-gc-nodejs": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc-nodejs/-/cardano-serialization-lib-gc-nodejs-1.0.6.tgz", - "integrity": "sha512-I1FqhjEHgib+y0+6K1tSqvrtldRvqjrM5mL+TW9224ezEDScQeCroPWbgGBwwi6rjkN9YpS8Uz6gC0vo8lua1A==", + "node_modules/@mlabs-haskell/cardano-serialization-lib-gc": { + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", + "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", "dependencies": { - "@emurgo/cardano-serialization-lib-nodejs": "^11.4.0", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1" + "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", + "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, "node_modules/@mlabs-haskell/csl-gc-wrapper": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/csl-gc-wrapper/-/csl-gc-wrapper-1.0.1.tgz", - "integrity": "sha512-8pEb4BoQlD5zN+KtOCgtTg62OmLPjMa+DiJvoAzlLcWmp01P3TyJPgbEOtS+xiZpGA+1rRkdyeeLZV3wyw8Xfw==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/csl-gc-wrapper/-/csl-gc-wrapper-1.0.2.tgz", + "integrity": "sha512-jyASltvC/ZVzpMUgbIkIaCLc56uGqymCPnieLkgIMWPhzcRoAxEfshjYONyxPY5XIl0NdIQXjbppXFoPQMk0VQ==" }, "node_modules/@mlabs-haskell/json-bigint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@mlabs-haskell/json-bigint/-/json-bigint-2.0.0.tgz", "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, + "node_modules/@mlabs-haskell/uplc-apply-args": { + "version": "1.0.29-alpha", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-1.0.29-alpha.tgz", + "integrity": "sha512-eTazItNZlOvuK/ZNHBKUOM3fL1mhRaY0GFYPtalo6PrkGcwZeSzlD6+B8Mbgmb18HusDZPSRi3zhp/urxOygFA==", + "dependencies": { + "@mlabs-haskell/uplc-apply-args-browser": "^1.0.29-alpha", + "@mlabs-haskell/uplc-apply-args-nodejs": "^1.0.29-alpha2" + } + }, + "node_modules/@mlabs-haskell/uplc-apply-args-browser": { + "version": "1.0.29-alpha", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-1.0.29-alpha.tgz", + "integrity": "sha512-U/FEEI1UbHGRLblNHX4WxF5KpPR3S/C1rgXvN8X6gL2CDc4iAqvbP88d5vqwLL+seG2aO4pqqJXQnnKtlLHk7A==" + }, + "node_modules/@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "1.0.29-alpha2", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-1.0.29-alpha2.tgz", + "integrity": "sha512-91Lfk0SGH3cEHGE/F/If9lot42OJ6+bpM4HsHZr5PDvHFNOICFdTwLq/6BFmIClCkdZZNuDZIc1EpRCBgtdROw==" + }, "node_modules/@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -941,6 +957,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -1087,16 +1109,6 @@ "node": ">= 8" } }, - "node_modules/apply-args-browser": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-browser/-/apply-args-browser-0.0.1.tgz", - "integrity": "sha512-gq4ldo4Fk5SEVpeW/0yBe0v5g3VDEWAm9LB80zGarYtDvojTD7ar0Y/WvIy9gYAkKmlE3USu5wYwKKCqOXfNkg==" - }, - "node_modules/apply-args-nodejs": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-nodejs/-/apply-args-nodejs-0.0.1.tgz", - "integrity": "sha512-JwZPEvEDrL+4y16Un6FcNjDSITpsBykchgwPh8UtxnziYrbxKAc2BUfyC5uvA6ZVIhQjiO4r+Kg1MQ3nqWk+1Q==" - }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -1137,7 +1149,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -1246,11 +1257,6 @@ "node": ">= 6" } }, - "node_modules/blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" - }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -1553,7 +1559,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -2513,7 +2518,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, "dependencies": { "is-callable": "^1.1.3" } @@ -2569,14 +2573,12 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -2642,7 +2644,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -2666,7 +2667,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -2699,7 +2699,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -2711,7 +2710,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -2723,7 +2721,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -3042,7 +3039,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -3070,7 +3066,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -3118,7 +3113,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -3194,7 +3188,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, "dependencies": { "which-typed-array": "^1.1.11" }, @@ -3238,6 +3231,14 @@ "node": ">=0.10.0" } }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "peerDependencies": { + "ws": "*" + } + }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -3264,14 +3265,6 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "node_modules/jssha": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.2.0.tgz", - "integrity": "sha512-QuruyBENDWdN4tZwJbQq7/eAK85FqrI4oDbXjy5IBhYD+2pTJyBUWZe8ctWaCkrV0gy6AaelgOZZBMeswEa/6Q==", - "engines": { - "node": "*" - } - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -4989,7 +4982,6 @@ "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", @@ -5058,6 +5050,17 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -5352,27 +5355,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/webpack-merge": { "version": "5.9.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", @@ -5446,7 +5428,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -5473,15 +5454,15 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", - "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -5537,14 +5518,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "@emurgo/cardano-serialization-lib-browser": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.4.0.tgz", - "integrity": "sha512-VWMvLRBFo7MAYh42zledURFs5BpMTWvkP4DzsLNbyJxZlwjDS+bPyehJVyGc116d2gq8NHFmANbfdeuK8ffJ7A==" + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-beta.1.tgz", + "integrity": "sha512-Fj56XnZe+ilFVgf66SB6ajQXf0rtH9o0GmICLM9qahLDZ2kAPsVu31PbbQ0YWpQB8SlDGLZE5f9Pf3Lx7cc7oA==" }, "@emurgo/cardano-serialization-lib-nodejs": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.4.0.tgz", - "integrity": "sha512-dMiofDcqv+IrAITCgWBZmsMLqwv2xImDsJDSrKiYYG1zRKaL8XfMOxx6S0WEnKVj5/343Q5FFURYcSu3iBRNMQ==" + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-beta.1.tgz", + "integrity": "sha512-4BE7mSvSDWAmTXbzvNZg7NnaBoECv/QxsrNVKXdbaom5J9OhnnwvX3xhbEv98FAU2Awma8tLn9sHELZ46p2zbg==" }, "@esbuild/android-arm": { "version": "0.18.11", @@ -5761,34 +5742,54 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, - "@mlabs-haskell/cardano-serialization-lib-gc-browser": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc-browser/-/cardano-serialization-lib-gc-browser-1.0.6.tgz", - "integrity": "sha512-b7dLrrhjUJSdsmjzariCZO734NB+M/ONLGBiQ/TQzMRtsMydqSFQg6WbMdwYPustoNmQOg6a8bm9+RgllqdmFw==", + "@mlabs-haskell/cardano-message-signing": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-message-signing/-/cardano-message-signing-1.0.1.tgz", + "integrity": "sha512-LNX+Msq1rJ86d5mmaR2Om5tUqB0ZthfE69fpsZcxOYDHNw5s+qtcCyNEmzAWfHC+uIJ4NDEJA8Gk2RfWto7ChA==", "requires": { - "@emurgo/cardano-serialization-lib-browser": "^11.2.1", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1" + "@emurgo/cardano-message-signing-browser": "^1.0.1", + "@emurgo/cardano-message-signing-nodejs": "^1.0.1" } }, - "@mlabs-haskell/cardano-serialization-lib-gc-nodejs": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc-nodejs/-/cardano-serialization-lib-gc-nodejs-1.0.6.tgz", - "integrity": "sha512-I1FqhjEHgib+y0+6K1tSqvrtldRvqjrM5mL+TW9224ezEDScQeCroPWbgGBwwi6rjkN9YpS8Uz6gC0vo8lua1A==", + "@mlabs-haskell/cardano-serialization-lib-gc": { + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", + "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", "requires": { - "@emurgo/cardano-serialization-lib-nodejs": "^11.4.0", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1" + "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", + "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, "@mlabs-haskell/csl-gc-wrapper": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/csl-gc-wrapper/-/csl-gc-wrapper-1.0.1.tgz", - "integrity": "sha512-8pEb4BoQlD5zN+KtOCgtTg62OmLPjMa+DiJvoAzlLcWmp01P3TyJPgbEOtS+xiZpGA+1rRkdyeeLZV3wyw8Xfw==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/csl-gc-wrapper/-/csl-gc-wrapper-1.0.2.tgz", + "integrity": "sha512-jyASltvC/ZVzpMUgbIkIaCLc56uGqymCPnieLkgIMWPhzcRoAxEfshjYONyxPY5XIl0NdIQXjbppXFoPQMk0VQ==" }, "@mlabs-haskell/json-bigint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@mlabs-haskell/json-bigint/-/json-bigint-2.0.0.tgz", "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, + "@mlabs-haskell/uplc-apply-args": { + "version": "1.0.29-alpha", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-1.0.29-alpha.tgz", + "integrity": "sha512-eTazItNZlOvuK/ZNHBKUOM3fL1mhRaY0GFYPtalo6PrkGcwZeSzlD6+B8Mbgmb18HusDZPSRi3zhp/urxOygFA==", + "requires": { + "@mlabs-haskell/uplc-apply-args-browser": "^1.0.29-alpha", + "@mlabs-haskell/uplc-apply-args-nodejs": "^1.0.29-alpha2" + } + }, + "@mlabs-haskell/uplc-apply-args-browser": { + "version": "1.0.29-alpha", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-1.0.29-alpha.tgz", + "integrity": "sha512-U/FEEI1UbHGRLblNHX4WxF5KpPR3S/C1rgXvN8X6gL2CDc4iAqvbP88d5vqwLL+seG2aO4pqqJXQnnKtlLHk7A==" + }, + "@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "1.0.29-alpha2", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-1.0.29-alpha2.tgz", + "integrity": "sha512-91Lfk0SGH3cEHGE/F/If9lot42OJ6+bpM4HsHZr5PDvHFNOICFdTwLq/6BFmIClCkdZZNuDZIc1EpRCBgtdROw==" + }, "@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -6174,6 +6175,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -6278,16 +6285,6 @@ "picomatch": "^2.0.4" } }, - "apply-args-browser": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-browser/-/apply-args-browser-0.0.1.tgz", - "integrity": "sha512-gq4ldo4Fk5SEVpeW/0yBe0v5g3VDEWAm9LB80zGarYtDvojTD7ar0Y/WvIy9gYAkKmlE3USu5wYwKKCqOXfNkg==" - }, - "apply-args-nodejs": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-nodejs/-/apply-args-nodejs-0.0.1.tgz", - "integrity": "sha512-JwZPEvEDrL+4y16Un6FcNjDSITpsBykchgwPh8UtxnziYrbxKAc2BUfyC5uvA6ZVIhQjiO4r+Kg1MQ3nqWk+1Q==" - }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -6329,8 +6326,7 @@ "available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "balanced-match": { "version": "1.0.2", @@ -6398,11 +6394,6 @@ } } }, - "blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" - }, "bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -6646,7 +6637,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -7414,7 +7404,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, "requires": { "is-callable": "^1.1.3" } @@ -7457,14 +7446,12 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -7512,7 +7499,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "requires": { "get-intrinsic": "^1.1.3" } @@ -7533,7 +7519,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -7556,20 +7541,17 @@ "has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "requires": { "has-symbols": "^1.0.2" } @@ -7807,7 +7789,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, "requires": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -7825,8 +7806,7 @@ "is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" }, "is-core-module": { "version": "2.13.0", @@ -7853,7 +7833,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, "requires": { "has-tostringtag": "^1.0.0" } @@ -7902,7 +7881,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, "requires": { "which-typed-array": "^1.1.11" } @@ -7934,6 +7912,12 @@ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true }, + "isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "requires": {} + }, "jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -7957,11 +7941,6 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "jssha": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.2.0.tgz", - "integrity": "sha512-QuruyBENDWdN4tZwJbQq7/eAK85FqrI4oDbXjy5IBhYD+2pTJyBUWZe8ctWaCkrV0gy6AaelgOZZBMeswEa/6Q==" - }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -9290,7 +9269,6 @@ "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, "requires": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", @@ -9347,6 +9325,15 @@ "minimalistic-assert": "^1.0.0" } }, + "web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "requires": { + "@zxing/text-encoding": "0.9.0", + "util": "^0.12.3" + } + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -9543,13 +9530,6 @@ "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } - }, - "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "requires": {} } } }, @@ -9608,7 +9588,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dev": true, "requires": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -9629,9 +9608,9 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "ws": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", - "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "requires": {} }, "xhr2": { diff --git a/templates/ctl-scaffold/package.json b/templates/ctl-scaffold/package.json index 1997e20657..4ec30b3110 100644 --- a/templates/ctl-scaffold/package.json +++ b/templates/ctl-scaffold/package.json @@ -3,7 +3,7 @@ "name": "ctl-scaffold", "version": "0.1.0", "description": "", - "main": "index.js", + "main": "./output/Scaffold.Main/index.js", "directories": { "test": "test" }, @@ -25,26 +25,22 @@ "author": "", "license": "MIT", "dependencies": { - "@emurgo/cardano-message-signing-browser": "1.0.1", - "@emurgo/cardano-message-signing-nodejs": "1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc-browser": "^1.0.6", - "@mlabs-haskell/cardano-serialization-lib-gc-nodejs": "^1.0.6", - "@mlabs-haskell/csl-gc-wrapper": "^1.0.1", + "@mlabs-haskell/cardano-message-signing": "^1.0.1", + "@mlabs-haskell/cardano-serialization-lib-gc": "12.0.0-alpha.31", "@mlabs-haskell/json-bigint": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "1.0.29-alpha", "@noble/secp256k1": "^1.7.0", - "apply-args-browser": "0.0.1", - "apply-args-nodejs": "0.0.1", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", "bip39": "^3.1.0", - "blakejs": "1.2.1", "bufferutil": "4.0.5", - "jssha": "3.2.0", + "isomorphic-ws": "^5.0.0", "puppeteer-core": "^15.3.2", "reconnecting-websocket": "4.4.0", "uniqid": "5.4.0", "utf-8-validate": "^5.0.10", - "ws": "8.4.0", + "web-encoding": "^1.1.5", + "ws": "^8.16.0", "xhr2": "0.2.1" }, "devDependencies": { diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index d6d88c4d74..f0b785071e 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -1,109 +1,3 @@ -{- -Welcome to your new Dhall package-set! - -Below are instructions for how to edit this file for most use -cases, so that you don't need to know Dhall to use it. - -## Warning: Don't Move This Top-Level Comment! - -Due to how `dhall format` currently works, this comment's -instructions cannot appear near corresponding sections below -because `dhall format` will delete the comment. However, -it will not delete a top-level comment like this one. - -## Use Cases - -Most will want to do one or both of these options: -1. Override/Patch a package's dependency -2. Add a package not already in the default package set - -This file will continue to work whether you use one or both options. -Instructions for each option are explained below. - -### Overriding/Patching a package - -Purpose: -- Change a package's dependency to a newer/older release than the - default package set's release -- Use your own modified version of some dependency that may - include new API, changed API, removed API by - using your custom git repo of the library rather than - the package set's repo - -Syntax: -where `entityName` is one of the following: -- dependencies -- repo -- version -------------------------------- -let upstream = -- -in upstream - with packageName.entityName = "new value" -------------------------------- - -Example: -------------------------------- -let upstream = -- -in upstream - with halogen.version = "master" - with halogen.repo = "https://example.com/path/to/git/repo.git" - - with halogen-vdom.version = "v4.0.0" -------------------------------- - -### Additions - -Purpose: -- Add packages that aren't already included in the default package set - -Syntax: -where `` is: -- a tag (i.e. "v4.0.0") -- a branch (i.e. "master") -- commit hash (i.e. "701f3e44aafb1a6459281714858fadf2c4c2a977") -------------------------------- -let upstream = -- -in upstream - with new-package-name = - { dependencies = - [ "dependency1" - , "dependency2" - ] - , repo = - "https://example.com/path/to/git/repo.git" - , version = - "" - } -------------------------------- - -Example: -------------------------------- -let upstream = -- -in upstream - with benchotron = - { dependencies = - [ "arrays" - , "exists" - , "profunctor" - , "strings" - , "quickcheck" - , "lcg" - , "transformers" - , "foldable-traversable" - , "exceptions" - , "node-fs" - , "node-buffer" - , "node-readline" - , "datetime" - , "now" - ] - , repo = - "https://github.com/hdgarrood/purescript-benchotron.git" - , version = - "v7.0.0" - } -------------------------------- --} let upstream = https://github.com/purescript/package-sets/releases/download/psc-0.15.4-20230105/packages.dhall sha256:3e9fbc9ba03e9a1fcfd895f65e2d50ee2f5e86c4cd273f3d5c841b655a0e1bda @@ -144,7 +38,7 @@ let additions = , "untagged-union" ] , repo = "https://github.com/mlabs-haskell/purescript-aeson.git" - , version = "v2.0.0" + , version = "v2.0.1" } , bignumber = { dependencies = @@ -193,6 +87,7 @@ let additions = { dependencies = [ "aff" , "aff-promise" + , "bytearrays" , "effect" , "prelude" , "spec" @@ -201,7 +96,383 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-noble-secp256k1.git" - , version = "a3c0f67e9fdb0086016d7aebfad35d09a08b4ecd" + , version = "v2.0.0" + } + , js-bigints = + { dependencies = [ "integers", "maybe", "prelude" ] + , repo = "https://github.com/purescript-contrib/purescript-js-bigints" + , version = "36a7d8ac75a7230043ae511f3145f9ed130954a9" + } + , cip30 = + { dependencies = + [ "aff" + , "aff-promise" + , "arrays" + , "console" + , "effect" + , "literals" + , "maybe" + , "newtype" + , "nullable" + , "prelude" + , "untagged-union" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cip30" + , version = "v1.0.0" + } + , cip30-typesafe = + { dependencies = + [ "aff" + , "bifunctors" + , "cip30" + , "control" + , "effect" + , "either" + , "exceptions" + , "maybe" + , "prelude" + , "spec" + , "transformers" + , "variant" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cip30-typesafe" + , version = "v1.0.0" + } + , cip95 = + { dependencies = + [ "aff" + , "aff-promise" + , "cip30" + , "console" + , "effect" + , "newtype" + , "prelude" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cip95" + , version = "v1.0.0" + } + , cip95-typesafe = + { dependencies = + [ "aff" + , "bifunctors" + , "cip30" + , "cip30-typesafe" + , "cip95" + , "console" + , "control" + , "effect" + , "either" + , "exceptions" + , "maybe" + , "prelude" + , "spec" + , "transformers" + , "variant" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cip95-typesafe" + , version = "v1.0.0" + } + , bytearrays = + { dependencies = + [ "aeson" + , "aff" + , "arraybuffer-types" + , "effect" + , "either" + , "foldable-traversable" + , "maybe" + , "newtype" + , "prelude" + , "quickcheck" + , "quickcheck-laws" + , "spec" + , "strings" + ] + , repo = "https://github.com/mlabs-haskell/purescript-bytearrays" + , version = "v1.0.0" + } + , cardano-serialization-lib = + { dependencies = + [ "aeson" + , "aff" + , "argonaut" + , "bifunctors" + , "bytearrays" + , "effect" + , "either" + , "enums" + , "maybe" + , "nullable" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor" + , "spec" + , "transformers" + , "tuples" + , "unsafe-coerce" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib" + , version = "v1.0.0" + } + , cardano-plutus-data-schema = + { dependencies = [ "prelude" ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-plutus-data-schema" + , version = "v1.0.0" + } + , plutus-types = + { dependencies = + [ "aeson" + , "argonaut-codecs" + , "arrays" + , "bifunctors" + , "bytearrays" + , "cardano-plutus-data-schema" + , "cardano-types" + , "console" + , "effect" + , "either" + , "foldable-traversable" + , "gen" + , "js-bigints" + , "lattice" + , "maybe" + , "monad-logger" + , "newtype" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor-lenses" + , "quickcheck" + , "these" + , "tuples" + ] + , repo = "https://github.com/mlabs-haskell/purescript-plutus-types" + , version = "v1.0.1" + } + , cip30-mock = + { dependencies = + [ "aff-promise", "console", "effect", "functions", "prelude" ] + , repo = "https://github.com/mlabs-haskell/purescript-cip30-mock" + , version = "v1.1.0" + } + , cardano-collateral-select = + { dependencies = + [ "arrays" + , "cardano-types" + , "console" + , "effect" + , "exceptions" + , "foldable-traversable" + , "lists" + , "maybe" + , "newtype" + , "ordered-collections" + , "partial" + , "prelude" + , "tuples" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-collateral-select" + , version = "v1.0.0" + } + , cardano-key-wallet = + { dependencies = + [ "aeson" + , "aff" + , "arrays" + , "cardano-collateral-select" + , "cardano-message-signing" + , "cardano-types" + , "console" + , "effect" + , "either" + , "foldable-traversable" + , "maybe" + , "newtype" + , "ordered-collections" + , "prelude" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-key-wallet" + , version = "v2.0.0" + } + , uplc-apply-args = + { dependencies = + [ "aff" + , "bytearrays" + , "cardano-serialization-lib" + , "cardano-types" + , "effect" + , "either" + , "foldable-traversable" + , "foreign-object" + , "js-bigints" + , "lists" + , "maybe" + , "mote" + , "mote-testplan" + , "partial" + , "prelude" + , "profunctor" + , "spec" + , "transformers" + , "tuples" + ] + , repo = "https://github.com/mlabs-haskell/purescript-uplc-apply-args" + , version = "v1.0.0" + } + , cardano-types = + { dependencies = + [ "aeson" + , "aff" + , "arraybuffer-types" + , "arrays" + , "bifunctors" + , "bytearrays" + , "cardano-plutus-data-schema" + , "cardano-serialization-lib" + , "control" + , "datetime" + , "effect" + , "either" + , "encoding" + , "exceptions" + , "foldable-traversable" + , "foreign-object" + , "integers" + , "js-bigints" + , "lattice" + , "lists" + , "literals" + , "maybe" + , "monad-logger" + , "mote" + , "mote-testplan" + , "newtype" + , "nonempty" + , "nullable" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor" + , "profunctor-lenses" + , "quickcheck" + , "rationals" + , "record" + , "safe-coerce" + , "spec" + , "these" + , "tuples" + , "typelevel-prelude" + , "uint" + , "unfoldable" + , "unsafe-coerce" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" + , version = "v2.0.1" + } + , cardano-message-signing = + { dependencies = + [ "bytearrays" + , "cardano-types" + , "console" + , "effect" + , "newtype" + , "prelude" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-message-signing" + , version = "v1.0.0" + } + , cardano-hd-wallet = + { dependencies = + [ "cardano-serialization-lib" + , "cardano-types" + , "console" + , "effect" + , "either" + , "prelude" + , "uint" + ] + , repo = "https://github.com/mlabs-haskell/purescript-cardano-hd-wallet" + , version = "cc1073ddf8bce72407ef6671e3decb59f422e304" + } + , cardano-transaction-builder = + { dependencies = + [ "aeson" + , "aff" + , "arraybuffer-types" + , "arrays" + , "bifunctors" + , "bytearrays" + , "cardano-plutus-data-schema" + , "cardano-serialization-lib" + , "cardano-types" + , "console" + , "control" + , "datetime" + , "effect" + , "either" + , "encoding" + , "exceptions" + , "foldable-traversable" + , "foreign-object" + , "integers" + , "js-bigints" + , "lattice" + , "lists" + , "literals" + , "maybe" + , "monad-logger" + , "mote" + , "mote-testplan" + , "newtype" + , "nonempty" + , "nullable" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor" + , "profunctor-lenses" + , "quickcheck" + , "rationals" + , "record" + , "safe-coerce" + , "spec" + , "strings" + , "these" + , "transformers" + , "tuples" + , "typelevel-prelude" + , "uint" + , "unfoldable" + , "unsafe-coerce" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder" + , version = "a9c033b9a2bb78b134ae5309209f73e47f3d5791" + } + , mote-testplan = + { dependencies = + [ "aff" + , "console" + , "datetime" + , "effect" + , "foldable-traversable" + , "maybe" + , "mote" + , "newtype" + , "numbers" + , "ordered-collections" + , "prelude" + , "spec" + , "transformers" + ] + , repo = "https://github.com/mlabs-haskell/purescript-mote-testplan" + , version = "v1.0.0" } , cardano-transaction-lib = { dependencies = @@ -213,15 +484,24 @@ let additions = , "ansi" , "argonaut" , "argonaut-codecs" - , "arraybuffer-types" , "arrays" , "avar" , "bifunctors" - , "js-bigints" , "bignumber" + , "bytearrays" + , "cardano-hd-wallet" + , "cardano-key-wallet" + , "cardano-message-signing" + , "cardano-plutus-data-schema" + , "cardano-serialization-lib" + , "cardano-transaction-builder" + , "cardano-types" , "checked-exceptions" , "cip30" + , "cip30-mock" , "cip30-typesafe" + , "cip95" + , "cip95-typesafe" , "console" , "control" , "crypto" @@ -229,7 +509,6 @@ let additions = , "debug" , "effect" , "either" - , "encoding" , "enums" , "exceptions" , "foldable-traversable" @@ -237,18 +516,20 @@ let additions = , "foreign-object" , "formatters" , "functions" - , "gen" , "heterogeneous" , "http-methods" , "identity" , "integers" + , "js-bigints" , "js-date" , "lattice" , "lists" + , "literals" , "maybe" , "media-types" , "monad-logger" , "mote" + , "mote-testplan" , "newtype" , "noble-secp256k1" , "node-buffer" @@ -259,86 +540,51 @@ let additions = , "node-process" , "node-readline" , "node-streams" + , "node-streams-aff" , "nonempty" , "now" + , "nullable" , "numbers" , "optparse" , "ordered-collections" , "orders" , "parallel" + , "parsing" , "partial" + , "plutus-types" , "posix-types" , "prelude" , "profunctor" , "profunctor-lenses" - , "toppokki" , "quickcheck" , "quickcheck-combinators" - , "quickcheck-laws" , "random" , "rationals" , "record" , "refs" , "safe-coerce" + , "safely" , "spec" , "spec-quickcheck" , "strings" , "stringutils" , "tailrec" , "these" + , "toppokki" , "transformers" , "tuples" - , "typelevel" , "typelevel-prelude" , "uint" , "unfoldable" + , "unsafe-coerce" , "untagged-union" + , "uplc-apply-args" , "variant" , "web-html" , "web-storage" ] , repo = "https://github.com/Plutonomicon/cardano-transaction-lib.git" - , version = "7d533241367081fa69ec5f0ec8f50e00c39430c2" - } - , js-bigints = - { dependencies = [ "integers", "maybe", "prelude" ] - , repo = "https://github.com/purescript-contrib/purescript-js-bigints" - , version = "36a7d8ac75a7230043ae511f3145f9ed130954a9" - } - , cip30 = - { dependencies = - [ "aff" - , "aff-promise" - , "arrays" - , "console" - , "effect" - , "literals" - , "maybe" - , "newtype" - , "nullable" - , "prelude" - , "untagged-union" - ] - , repo = "https://github.com/mlabs-haskell/purescript-cip30" - , version = "8f1b34b48825fcec5e9c67f33e255770b1e0bc45" - } - , cip30-typesafe = - { dependencies = - [ "aff" - , "bifunctors" - , "cip30" - , "control" - , "effect" - , "either" - , "exceptions" - , "maybe" - , "prelude" - , "spec" - , "transformers" - , "variant" - ] - , repo = "https://github.com/mlabs-haskell/purescript-cip30-typesafe" - , version = "d72e51fbc0255eb3246c9132d295de7f65e16a99" + , version = "01708d64e858a2ed3cbbc7a9a235d3acf79a7b91" } } diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index 5c9a5b894d..8428b9676d 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -7,11 +7,11 @@ let "aeson" = pkgs.stdenv.mkDerivation { name = "aeson"; - version = "v2.0.0"; + version = "v2.0.1"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-aeson.git"; - rev = "4fddd518a143de563299d484272a0ef18daa7dcd"; - sha256 = "1bz1z9l6nwf5yk45sbbjllmqvci0n1l92cvk3lgmni19g9silbrl"; + rev = "ac674dda5cf58c6544cb361a208bced4d06ee93a"; + sha256 = "1zx7d96rz86axqz8n28j5d4lkgx48via0nw9c7xid1z1pz215zsd"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -197,13 +197,121 @@ let installPhase = "ln -s $src $out"; }; + "bytearrays" = pkgs.stdenv.mkDerivation { + name = "bytearrays"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-bytearrays"; + rev = "e3991d562a04d8825472551d91a06407ad9c9112"; + sha256 = "0lyp1x8kgzg8ykv5yp8dd21ziypi9yzhzqpwv5l995kfm4mdglh2"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-collateral-select" = pkgs.stdenv.mkDerivation { + name = "cardano-collateral-select"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-collateral-select"; + rev = "193bf49be979b42aa1f0f9cb3d7582d6bc98e3b9"; + sha256 = "1jbl6k779brbqzf7jf80is63b23k3mqzf2mzr222qswd3wg8s5b0"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-hd-wallet" = pkgs.stdenv.mkDerivation { + name = "cardano-hd-wallet"; + version = "cc1073ddf8bce72407ef6671e3decb59f422e304"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-hd-wallet"; + rev = "cc1073ddf8bce72407ef6671e3decb59f422e304"; + sha256 = "0y51lp3x785yjjrr91rmpw1bhzjdfjb5fs27n1vlwihxjyfylxya"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-key-wallet" = pkgs.stdenv.mkDerivation { + name = "cardano-key-wallet"; + version = "v2.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-key-wallet"; + rev = "99d9bb7c8b291ad0bc9709d493ff7e02d14a89c0"; + sha256 = "11jw05s7vpgg6bdyi3zy4z1fcj53a8kaaja5717b7yjgflmhfn8s"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-message-signing" = pkgs.stdenv.mkDerivation { + name = "cardano-message-signing"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-message-signing"; + rev = "97f6f97a258ae3490df0be6b39fa6769677aa04f"; + sha256 = "1ns7m9awn4w5amvf9ffldxk7acm73fg8clw4hja4nnl61mskqr5w"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-plutus-data-schema" = pkgs.stdenv.mkDerivation { + name = "cardano-plutus-data-schema"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-plutus-data-schema"; + rev = "eb0bb78927c50c4bee364e932c9fa8cf94546191"; + sha256 = "118i6dlfqk7q0va3bd4vplsv9i6sh83cr51gshas6jjwc5qbriks"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-serialization-lib" = pkgs.stdenv.mkDerivation { + name = "cardano-serialization-lib"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib"; + rev = "903bf0adeefedc4d065ad6523ad079433bdd8e32"; + sha256 = "0jlfxrx037hyd4v0j7l2b16yxlm6nw6qlnr992hj9nzip36vbpfg"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-transaction-builder" = pkgs.stdenv.mkDerivation { + name = "cardano-transaction-builder"; + version = "a9c033b9a2bb78b134ae5309209f73e47f3d5791"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder"; + rev = "a9c033b9a2bb78b134ae5309209f73e47f3d5791"; + sha256 = "1xz6k56kwghq9nl0iwrqs6m05wja0xfj34iicmlhwvdp7k4nc65w"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-lib"; - version = "7d533241367081fa69ec5f0ec8f50e00c39430c2"; + version = "01708d64e858a2ed3cbbc7a9a235d3acf79a7b91"; src = pkgs.fetchgit { url = "https://github.com/Plutonomicon/cardano-transaction-lib.git"; - rev = "7d533241367081fa69ec5f0ec8f50e00c39430c2"; - sha256 = "0wpcjrajyfn53ijpdv1w2kg6rmifsz3p8gxx88zin1wv0437cmxh"; + rev = "01708d64e858a2ed3cbbc7a9a235d3acf79a7b91"; + sha256 = "1c75kk2wr6xx4a2jkaql0divfdi0pg5g8mlsa66r4gmiy248s008"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-types" = pkgs.stdenv.mkDerivation { + name = "cardano-types"; + version = "v2.0.1"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-types"; + rev = "5b16e9571167e9889605d3aecdd0ccce24d38696"; + sha256 = "1052lknpkhcq86lj8aavfwzr9ybrirjighsjccpgrcaq2jn4kcmj"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -235,7 +343,7 @@ let "cip30" = pkgs.stdenv.mkDerivation { name = "cip30"; - version = "8f1b34b48825fcec5e9c67f33e255770b1e0bc45"; + version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cip30"; rev = "8f1b34b48825fcec5e9c67f33e255770b1e0bc45"; @@ -245,9 +353,21 @@ let installPhase = "ln -s $src $out"; }; + "cip30-mock" = pkgs.stdenv.mkDerivation { + name = "cip30-mock"; + version = "v1.1.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cip30-mock"; + rev = "7ab1d872b550b60ee32df2a01feef3e8dce3f906"; + sha256 = "1bzkzs9rc9g46s0pivpzixd9l5ab010501hwgrg75psf7bim6d4c"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cip30-typesafe" = pkgs.stdenv.mkDerivation { name = "cip30-typesafe"; - version = "d72e51fbc0255eb3246c9132d295de7f65e16a99"; + version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cip30-typesafe"; rev = "d72e51fbc0255eb3246c9132d295de7f65e16a99"; @@ -257,6 +377,30 @@ let installPhase = "ln -s $src $out"; }; + "cip95" = pkgs.stdenv.mkDerivation { + name = "cip95"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cip95"; + rev = "2a27322aaaad116fd6f08832d171d8e5b43f290f"; + sha256 = "1jg6w27qvwkyvf1k83rpdn0d83bsfpfqsqzshv1ypnr90cy8brw5"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cip95-typesafe" = pkgs.stdenv.mkDerivation { + name = "cip95-typesafe"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cip95-typesafe"; + rev = "bee527d5bca9b8d9f7126f67160773196f492259"; + sha256 = "1cl4h65xc6px1bwldbi6vr3a5h682frasnslx7ryfdrinyx3fs0y"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "console" = pkgs.stdenv.mkDerivation { name = "console"; version = "v6.0.0"; @@ -533,6 +677,18 @@ let installPhase = "ln -s $src $out"; }; + "freet" = pkgs.stdenv.mkDerivation { + name = "freet"; + version = "v7.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/purescript-contrib/purescript-freet.git"; + rev = "21be6fba22599a25812430dda6ba2ca8135920a1"; + sha256 = "006wbr7f19k7vs1jg4wgkwyx1q4wvvs2wqscfcxsp8fzfpn2yqw8"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "functions" = pkgs.stdenv.mkDerivation { name = "functions"; version = "v6.0.0"; @@ -785,6 +941,18 @@ let installPhase = "ln -s $src $out"; }; + "mote-testplan" = pkgs.stdenv.mkDerivation { + name = "mote-testplan"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-mote-testplan"; + rev = "3d56986a32134fbd675e42ef6b6f55dc91ad678a"; + sha256 = "11vivzi1bs9mc8hx4v4zarb9r7x47zm6m6z1xvcn228m7lr69csy"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "newtype" = pkgs.stdenv.mkDerivation { name = "newtype"; version = "v5.0.0"; @@ -799,11 +967,11 @@ let "noble-secp256k1" = pkgs.stdenv.mkDerivation { name = "noble-secp256k1"; - version = "a3c0f67e9fdb0086016d7aebfad35d09a08b4ecd"; + version = "v2.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-noble-secp256k1.git"; - rev = "a3c0f67e9fdb0086016d7aebfad35d09a08b4ecd"; - sha256 = "0n2q83n210ih5l54p6wrrjqmy40xhhdd3mam5mzixgr2hszm8969"; + rev = "32a9b39f1734fe0d809b3a3b4854b9e4ad6056f1"; + sha256 = "0hrf7vgf2mh91803l4drygg6srmkg765x4gk6i6zqyr6398fyxw6"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -929,6 +1097,18 @@ let installPhase = "ln -s $src $out"; }; + "node-streams-aff" = pkgs.stdenv.mkDerivation { + name = "node-streams-aff"; + version = "v4.0.1"; + src = pkgs.fetchgit { + url = "https://github.com/purescript-node/purescript-node-streams-aff.git"; + rev = "5c9b6937d14d6fed2273e3ac8780e3d256763e7d"; + sha256 = "1vm5s6mlawdpqamnqfyh1vbsybjm2s972m02h8mza4m47zlca948"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "node-url" = pkgs.stdenv.mkDerivation { name = "node-url"; version = "v6.0.0"; @@ -1097,6 +1277,18 @@ let installPhase = "ln -s $src $out"; }; + "plutus-types" = pkgs.stdenv.mkDerivation { + name = "plutus-types"; + version = "v1.0.1"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-plutus-types"; + rev = "dfec05e2dee79ee8dafad3d698906966ea6628bb"; + sha256 = "0milz16kdl1pd0i6b8ibxpacdd2r7p6n96gl1g6h41v9bccs69p9"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "posix-types" = pkgs.stdenv.mkDerivation { name = "posix-types"; version = "v6.0.0"; @@ -1265,6 +1457,18 @@ let installPhase = "ln -s $src $out"; }; + "safely" = pkgs.stdenv.mkDerivation { + name = "safely"; + version = "v4.0.1"; + src = pkgs.fetchgit { + url = "https://github.com/paf31/purescript-safely.git"; + rev = "19f854737e17b4d058e5a1504a960821db36e4ab"; + sha256 = "1mrpz19smjsamz4cci287z89q715chzxna0gpbvdgivlca4z6879"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "spec" = pkgs.stdenv.mkDerivation { name = "spec"; version = "v7.2.0"; @@ -1481,6 +1685,18 @@ let installPhase = "ln -s $src $out"; }; + "uplc-apply-args" = pkgs.stdenv.mkDerivation { + name = "uplc-apply-args"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args"; + rev = "aa528d5310cbfbd01b4d94557f404d95cfb6bb3c"; + sha256 = "1r064ca2m16hkbcswrvlng032ax1ygbpr2gxrlaqmjlf2gnin280"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "variant" = pkgs.stdenv.mkDerivation { name = "variant"; version = "v8.0.0"; diff --git a/templates/ctl-scaffold/spago.dhall b/templates/ctl-scaffold/spago.dhall index 9880991208..e726079d22 100644 --- a/templates/ctl-scaffold/spago.dhall +++ b/templates/ctl-scaffold/spago.dhall @@ -5,15 +5,30 @@ You can edit this file as you like. { name = "ctl-package-example" , dependencies = [ "aff" - , "js-bigints" + , "bytearrays" + , "cardano-hd-wallet" + , "cardano-plutus-data-schema" + , "cardano-collateral-select" + , "cardano-key-wallet" + , "cardano-message-signing" + , "cip30-mock" + , "uplc-apply-args" + , "cardano-serialization-lib" + , "cardano-transaction-builder" , "cardano-transaction-lib" + , "cardano-types" , "datetime" , "effect" + , "js-bigints" , "maybe" , "mote" + , "mote-testplan" + , "noble-secp256k1" , "ordered-collections" + , "plutus-types" , "posix-types" , "prelude" + , "safely" , "spec" ] , packages = ./packages.dhall diff --git a/templates/ctl-scaffold/test/E2E.purs b/templates/ctl-scaffold/test/E2E.purs index 6293691a6d..acf0922dca 100644 --- a/templates/ctl-scaffold/test/E2E.purs +++ b/templates/ctl-scaffold/test/E2E.purs @@ -5,20 +5,12 @@ import Contract.Prelude import Contract.Config ( ContractParams - , mainnetFlintConfig - , mainnetGeroConfig - , mainnetLodeConfig - , mainnetNamiConfig - , testnetEternlConfig - , testnetFlintConfig - , testnetGeroConfig - , testnetLodeConfig - , testnetNamiConfig + , KnownWallet(Nami, Gero, Flint, Eternl, Lode) + , WalletSpec(ConnectToGenericCip30) + , testnetConfig + , walletName ) import Contract.Monad (Contract) -import Contract.Test.Cip30Mock - ( WalletMock(MockFlint, MockGero, MockNami, MockLode) - ) import Contract.Test.E2E (E2EConfigName, E2ETestName, addLinks, route) import Data.Map (Map) import Data.Map as Map @@ -29,23 +21,29 @@ main = do addLinks configs tests route configs tests -configs :: Map E2EConfigName (ContractParams /\ Maybe WalletMock) -configs = Map.fromFoldable - [ "nami" /\ testnetNamiConfig /\ Nothing - , "gero" /\ testnetGeroConfig /\ Nothing - , "flint" /\ testnetFlintConfig /\ Nothing - , "eternl" /\ testnetEternlConfig /\ Nothing - , "lode" /\ testnetLodeConfig /\ Nothing - , "nami-mock" /\ testnetNamiConfig /\ Just MockNami - , "gero-mock" /\ testnetGeroConfig /\ Just MockGero - , "flint-mock" /\ testnetFlintConfig /\ Just MockFlint - , "lode-mock" /\ testnetLodeConfig /\ Just MockLode - -- Plutip cluster's network ID is set to mainnet: - , "plutip-nami-mock" /\ mainnetNamiConfig /\ Just MockNami - , "plutip-gero-mock" /\ mainnetGeroConfig /\ Just MockGero - , "plutip-flint-mock" /\ mainnetFlintConfig /\ Just MockFlint - , "plutip-lode-mock" /\ mainnetLodeConfig /\ Just MockLode +configs :: Map E2EConfigName (ContractParams /\ Maybe String) +configs = map (map walletName) <$> Map.fromFoldable + [ "nami" /\ testnetConfig' Nami /\ Nothing + , "gero" /\ testnetConfig' Gero /\ Nothing + , "flint" /\ testnetConfig' Flint /\ Nothing + , "eternl" /\ testnetConfig' Eternl /\ Nothing + , "lode" /\ testnetConfig' Lode /\ Nothing + , "nami-mock" /\ testnetConfig' Nami /\ Just Nami + , "gero-mock" /\ testnetConfig' Gero /\ Just Gero + , "flint-mock" /\ testnetConfig' Flint /\ Just Flint + , "lode-mock" /\ testnetConfig' Lode /\ Just Lode + , "plutip-nami-mock" /\ testnetConfig' Nami /\ Just Nami + , "plutip-gero-mock" /\ testnetConfig' Gero /\ Just Gero + , "plutip-flint-mock" /\ testnetConfig' Flint /\ Just Flint + , "plutip-lode-mock" /\ testnetConfig' Lode /\ Just Lode ] + where + testnetConfig' :: KnownWallet -> ContractParams + testnetConfig' wallet = + testnetConfig + { walletSpec = + Just $ ConnectToGenericCip30 (walletName wallet) { cip95: false } + } tests :: Map E2ETestName (Contract Unit) tests = Map.fromFoldable diff --git a/templates/ctl-scaffold/test/Main.purs b/templates/ctl-scaffold/test/Main.purs index 1ea12ce4e2..ec4bebbff5 100644 --- a/templates/ctl-scaffold/test/Main.purs +++ b/templates/ctl-scaffold/test/Main.purs @@ -1,15 +1,16 @@ --- | This module implements a test suite that uses Plutip to automate running +-- | This module implements a test suite that uses Cardano Testnet to automate running -- | contracts in temporary, private networks. module Test.Scaffold.Main (main, suite) where import Contract.Prelude +import Contract.Numeric.BigNum as BigNum import Contract.Test.Mote (TestPlanM, interpretWithConfig) -import Contract.Test.Plutip - ( InitialUTxOs - , PlutipTest - , defaultPlutipConfig - , testPlutipContracts +import Contract.Test.Testnet + ( ContractTest + , InitialUTxOs + , defaultTestnetConfig + , testTestnetContracts , withKeyWallet , withWallets ) @@ -21,7 +22,6 @@ import Effect.Aff , effectCanceler , launchAff ) -import JS.BigInt (fromInt) as BigInt import Mote (group, test) import Scaffold (contract) import Test.Spec.Runner (defaultConfig) @@ -32,17 +32,17 @@ main = interruptOnSignal SIGINT =<< launchAff do flip cancelWith (effectCanceler (exitCode 1)) do interpretWithConfig defaultConfig { timeout = Just $ Milliseconds 70_000.0, exit = true } $ - testPlutipContracts defaultPlutipConfig suite + testTestnetContracts defaultTestnetConfig suite -suite :: TestPlanM PlutipTest Unit +suite :: TestPlanM ContractTest Unit suite = do group "Project tests" do test "Print PubKey" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 2_000_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 2_000_000_000 ] withWallets distribution \wallet -> do withKeyWallet wallet do diff --git a/templates/ctl-scaffold/test/e2e.env b/templates/ctl-scaffold/test/e2e.env index 4d7280e45d..1ecc9a1c77 100644 --- a/templates/ctl-scaffold/test/e2e.env +++ b/templates/ctl-scaffold/test/e2e.env @@ -29,7 +29,9 @@ fi; export E2E_TEST_TIMEOUT=200 export E2E_BROWSER=chromium -export E2E_NO_HEADLESS=false +export E2E_NO_HEADLESS=true +export E2E_PASS_BROWSER_LOGS=false + export E2E_SETTINGS_ARCHIVE_URL="https://github.com/mlabs-haskell/ctl-e2e-assets/releases/download/preview-1/preview-settings.tar.gz" export E2E_SETTINGS_ARCHIVE=test-data/settings.tar.gz export E2E_CHROME_USER_DATA="test-data/chrome-user-data" diff --git a/templates/ctl-scaffold/webpack.config.cjs b/templates/ctl-scaffold/webpack.config.cjs index d5fcdf1c63..1ccf6e5ba3 100644 --- a/templates/ctl-scaffold/webpack.config.cjs +++ b/templates/ctl-scaffold/webpack.config.cjs @@ -14,6 +14,7 @@ module.exports = env => { layers: false, lazyCompilation: false, outputModule: true, + // `syncWebAssembly` must be set to `true` because CTL internal code expects it. syncWebAssembly: true, topLevelAwait: true, }, @@ -58,9 +59,6 @@ module.exports = env => { }, plugins: [ - new webpack.DefinePlugin({ - BROWSER_RUNTIME: isBrowser, - }), new webpack.LoaderOptionsPlugin({ debug: true, }), diff --git a/test/ApplyArgs.purs b/test/ApplyArgs.purs index da50480104..a1c24d4683 100644 --- a/test/ApplyArgs.purs +++ b/test/ApplyArgs.purs @@ -2,20 +2,15 @@ module Test.Ctl.ApplyArgs (main, suite, contract) where import Contract.Prelude +import Cardano.Plutus.ApplyArgs (applyArgs) import Contract.Monad (Contract, launchAff_) import Contract.Numeric.BigNum as BigNum import Contract.PlutusData (PlutusData(List, Map, Bytes, Constr), toData) import Contract.Prim.ByteArray (hexToByteArrayUnsafe) import Contract.Scripts (PlutusScript) -import Contract.TextEnvelope - ( decodeTextEnvelope - , plutusScriptV1FromEnvelope - , plutusScriptV2FromEnvelope - ) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Control.Monad.Error.Class (class MonadError) -import Ctl.Internal.ApplyArgs (applyArgs) import Ctl.Internal.Cardano.TextEnvelope (TextEnvelope) -import Ctl.Internal.Test.TestPlanM (TestPlanM, interpret) import Data.List.Lazy (replicate) import Data.Profunctor.Choice (left) import Effect.Aff (Error, error, throwError) @@ -23,6 +18,7 @@ import Foreign.Object (Object) import Foreign.Object as Object import JS.BigInt (fromInt) import Mote (group, test) +import Mote.TestPlanM (TestPlanM, interpret) import Test.Spec.Assertions (shouldEqual) scriptSources :: Object String @@ -356,7 +352,7 @@ v1 => Object String -> String -> m PlutusScript -v1 scripts name = lookupAux plutusScriptV1FromEnvelope scripts name +v1 scripts name = lookupAux plutusScriptFromEnvelope scripts name v2 :: forall (m :: Type -> Type) @@ -364,7 +360,7 @@ v2 => Object String -> String -> m PlutusScript -v2 scripts name = lookupAux plutusScriptV2FromEnvelope scripts name +v2 scripts name = lookupAux plutusScriptFromEnvelope scripts name lookupAux :: forall (m :: Type -> Type) diff --git a/test/BalanceTx/ChangeGeneration.purs b/test/BalanceTx/ChangeGeneration.purs index b0ae5eff29..5b9a5afdeb 100644 --- a/test/BalanceTx/ChangeGeneration.purs +++ b/test/BalanceTx/ChangeGeneration.purs @@ -2,11 +2,11 @@ module Test.Ctl.BalanceTx.ChangeGeneration (suite) where import Prelude +import Cardano.Types.BigNum as BigNum import Contract.Test (ContractTest, InitialUTxOs, withKeyWallet, withWallets) import Ctl.Examples.ChangeGeneration (checkChangeOutputsDistribution) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import JS.BigInt (fromInt) as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM) suite :: TestPlanM ContractTest Unit suite = do @@ -36,8 +36,8 @@ mkChangeOutputs outputsToScript outputsToSelf expectedOutputs = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1000_000_000 - , BigInt.fromInt 2000_000_000 + [ BigNum.fromInt 1000_000_000 + , BigNum.fromInt 2000_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do diff --git a/test/BalanceTx/Collateral.purs b/test/BalanceTx/Collateral.purs index 4bad2e75a5..9365f9b9e8 100644 --- a/test/BalanceTx/Collateral.purs +++ b/test/BalanceTx/Collateral.purs @@ -2,6 +2,18 @@ module Test.Ctl.BalanceTx.Collateral (suite) where import Prelude +import Cardano.Types + ( Coin(Coin) + , TransactionHash + , TransactionInput + , TransactionOutput + , TransactionUnspentOutput + , UtxoMap + , Value(Value) + ) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.Value as Value import Contract.Config (testnetConfig) import Contract.Monad (Contract, runContract) import Contract.ProtocolParameters (getProtocolParameters) @@ -11,22 +23,10 @@ import Ctl.Internal.BalanceTx.Collateral.Select , selectCollateral ) import Ctl.Internal.BalanceTx.FakeOutput (fakeOutputWithValue) -import Ctl.Internal.Cardano.Types.Transaction (TransactionOutput, UtxoMap) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput - ) -import Ctl.Internal.Cardano.Types.Value (Coin(Coin), Value(Value)) -import Ctl.Internal.Cardano.Types.Value - ( lovelaceValueOf - , mkSingletonNonAdaAsset - ) as Value -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.ProtocolParameters (CoinsPerUtxoUnit) -import Ctl.Internal.Types.Transaction (TransactionHash, TransactionInput) import Data.Array (length, range, replicate, zipWith) as Array import Data.List (singleton) as List import Data.Map (fromFoldable) as Map -import Data.Maybe (Maybe(Just)) +import Data.Maybe (Maybe(Just), fromJust) import Data.Newtype (unwrap, wrap) import Data.Time.Duration (Seconds(Seconds)) import Data.Tuple (Tuple(Tuple)) @@ -34,9 +34,10 @@ import Data.Tuple.Nested (type (/\), (/\)) import Data.UInt (UInt) import Data.UInt (fromInt, toInt) as UInt import Effect.Aff (Aff) -import Effect.Class (liftEffect) import JS.BigInt (fromInt) as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM) +import Partial.Unsafe (unsafePartial) import Test.Ctl.Fixtures ( currencySymbol1 , tokenName1 @@ -54,7 +55,7 @@ suite = do withParams \coinsPerUtxoUnit maxCollateralInputs -> do collateral <- measure - $ liftEffect + $ pure $ selectCollateral coinsPerUtxoUnit maxCollateralInputs utxosFixture1 collateral `shouldEqual` @@ -64,7 +65,7 @@ suite = do withParams \coinsPerUtxoUnit maxCollateralInputs -> do collateral <- measure - $ liftEffect + $ pure $ selectCollateral coinsPerUtxoUnit maxCollateralInputs utxosFixture2 collateral `shouldEqual` @@ -73,12 +74,12 @@ suite = do test "Selects a collateral in less than 2 seconds" do withParams \coinsPerUtxoUnit maxCollateralInputs -> measureWithTimeout (Seconds 2.0) - ( void $ liftEffect $ selectCollateral coinsPerUtxoUnit + ( void $ pure $ selectCollateral coinsPerUtxoUnit maxCollateralInputs utxosFixture3 ) -withParams :: (CoinsPerUtxoUnit -> Int -> Contract Unit) -> Aff Unit +withParams :: (Coin -> Int -> Contract Unit) -> Aff Unit withParams test = runContract testnetConfig { suppressLogs = true } (join (test <$> getCoinsPerUtxoUnit <*> getMaxCollateralInputs)) @@ -88,37 +89,50 @@ withParams test = getProtocolParameters <#> UInt.toInt <<< _.maxCollateralInputs <<< unwrap - getCoinsPerUtxoUnit :: Contract CoinsPerUtxoUnit + getCoinsPerUtxoUnit :: Contract Coin getCoinsPerUtxoUnit = getProtocolParameters <#> unwrap >>> - _.coinsPerUtxoUnit + _.coinsPerUtxoByte -- | Ada-only tx output sufficient to cover `minRequiredCollateral`. adaOnlyTxOutputSuf :: TransactionOutput adaOnlyTxOutputSuf = fakeOutputWithValue $ - Value.lovelaceValueOf (minRequiredCollateral + one) + Value.lovelaceValueOf + ( unsafePartial $ fromJust $ BigNum.add BigNum.one $ unwrap + minRequiredCollateral + ) -- | Ada-only tx output insufficient to cover `minRequiredCollateral`. adaOnlyTxOutputInsuf :: TransactionOutput adaOnlyTxOutputInsuf = - fakeOutputWithValue $ - Value.lovelaceValueOf (minRequiredCollateral / BigInt.fromInt 2) + fakeOutputWithValue + $ Value.lovelaceValueOf + $ unsafePartial + $ fromJust + $ BigNum.fromBigInt + $ BigNum.toBigInt (unwrap minRequiredCollateral) / BigInt.fromInt 2 -- | Single-asset tx output sufficient to cover `minRequiredCollateral`. singleAssetTxOutputSuf :: TransactionOutput singleAssetTxOutputSuf = fakeOutputWithValue - $ Value (Coin $ minRequiredCollateral + one) - $ Value.mkSingletonNonAdaAsset currencySymbol1 tokenName1 one + $ Value + ( Coin $ unsafePartial $ fromJust $ BigNum.add BigNum.one $ unwrap + minRequiredCollateral + ) + $ MultiAsset.singleton currencySymbol1 tokenName1 BigNum.one -- | Multi-asset tx output sufficient to cover `minRequiredCollateral`. multiAssetTxOutputSuf :: TransactionOutput -multiAssetTxOutputSuf = - fakeOutputWithValue - $ Value (Coin $ minRequiredCollateral + one) - $ Value.mkSingletonNonAdaAsset currencySymbol1 tokenName1 one - <> Value.mkSingletonNonAdaAsset currencySymbol1 tokenName2 one +multiAssetTxOutputSuf = unsafePartial + $ fakeOutputWithValue + $ Value + ( Coin $ unsafePartial $ fromJust $ BigNum.add BigNum.one $ unwrap + minRequiredCollateral + ) + $ MultiAsset.singleton currencySymbol1 tokenName1 BigNum.one + <> MultiAsset.singleton currencySymbol1 tokenName2 BigNum.one utxosFixture1 :: UtxoMap utxosFixture1 = diff --git a/test/BalanceTx/Time.purs b/test/BalanceTx/Time.purs index c1fe6e8dce..4e436ce96c 100644 --- a/test/BalanceTx/Time.purs +++ b/test/BalanceTx/Time.purs @@ -2,12 +2,11 @@ module Test.Ctl.BalanceTx.Time (suite) where import Contract.Prelude +import Cardano.Types (BigNum, Transaction, _body) +import Cardano.Types.BigNum (fromInt, toInt) as BigNum import Contract.Config (testnetConfig) import Contract.Monad (Contract, runContract) -import Contract.ScriptLookups - ( ScriptLookups - , UnbalancedTx - ) +import Contract.ScriptLookups (ScriptLookups) import Contract.Time ( POSIXTime , Slot @@ -25,14 +24,13 @@ import Contract.Time import Contract.TxConstraints (mustValidateIn) import Contract.UnbalancedTx (mkUnbalancedTxE) import Control.Monad.Except (throwError) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.BigNum (BigNum) -import Ctl.Internal.Types.BigNum (fromInt, toInt) as BigNum import Ctl.Internal.Types.Interval (Interval) +import Data.Lens ((^.)) import Effect.Aff (Aff) import Effect.Exception (error) import JS.BigInt (fromString) as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Test.Spec.Assertions (fail, shouldEqual) @@ -85,7 +83,7 @@ mkTestFromSingleInterval interval = do mutx <- mkUnbalancedTxE emptyLookup constraint case mutx of Left e -> fail $ show e - Right utx -> + Right (utx /\ _) -> do returnedInterval <- getTimeFromUnbalanced utx returnedInterval `shouldEqual` interval @@ -120,7 +118,7 @@ mkTestMultipleInterval intervals expected = do mutx <- mkUnbalancedTxE emptyLookup constraint case mutx of Left e -> fail $ show e - Right utx -> + Right (utx /\ _) -> do returnedInterval <- getTimeFromUnbalanced utx returnedInterval `shouldEqual` expected @@ -146,10 +144,8 @@ unsafeSubtractOne value = wrap <<< fromJust -------------------------------------------------------------------------------- getTimeFromUnbalanced - :: UnbalancedTx -> Contract (Interval POSIXTime) -getTimeFromUnbalanced utx = validityToPosixTime $ unwrap body - where - body = (unwrap utx) # _.transaction >>> unwrap >>> _.body + :: Transaction -> Contract (Interval POSIXTime) +getTimeFromUnbalanced tx = validityToPosixTime $ unwrap $ tx ^. _body toPosixTime :: Slot -> Contract POSIXTime toPosixTime time = do diff --git a/test/Blockfrost.purs b/test/Blockfrost.purs index fb3d84732d..1b392952fe 100644 --- a/test/Blockfrost.purs +++ b/test/Blockfrost.purs @@ -2,11 +2,14 @@ module Test.Ctl.Blockfrost (main, testPlan) where import Prelude +import Cardano.AsCbor (decodeCbor) +import Cardano.Serialization.Lib (fromBytes) +import Cardano.Types (ScriptHash) +import Cardano.Types.BigNum as BigNum import Contract.Config (blockfrostPublicPreviewServerConfig) import Contract.Metadata ( GeneralTransactionMetadata(GeneralTransactionMetadata) - , TransactionMetadatum(Text, MetadataMap) - , TransactionMetadatumLabel(TransactionMetadatumLabel) + , TransactionMetadatum(Text, Map) ) import Contract.Prim.ByteArray (hexToByteArrayUnsafe) import Contract.Test.Mote (TestPlanM, interpretWithConfig) @@ -21,7 +24,6 @@ import Contract.Transaction import Control.Monad.Error.Class (liftEither) import Ctl.Internal.Contract.QueryBackend (BlockfrostBackend) import Ctl.Internal.Helpers (liftedM) -import Ctl.Internal.Serialization.Hash (ScriptHash, scriptHashFromBytes) import Ctl.Internal.Service.Blockfrost ( BlockfrostServiceM , runBlockfrostServiceM @@ -39,7 +41,6 @@ import Data.Tuple.Nested ((/\)) import Effect (Effect) import Effect.Aff (Aff, error, launchAff_) import Effect.Class.Console (log) -import JS.BigInt as BigInt import Mote (group, test) import Node.Process (argv) import Partial.Unsafe (unsafePartial) @@ -64,10 +65,11 @@ testPlan :: BlockfrostBackend -> TestPlanM (Aff Unit) Unit testPlan backend = group "Blockfrost" do let mkDatumHash :: String -> DataHash - mkDatumHash = wrap <<< hexToByteArrayUnsafe + mkDatumHash s = unsafePartial $ fromJust $ decodeCbor $ wrap $ + hexToByteArrayUnsafe s mkStringHash :: String -> ScriptHash - mkStringHash s = unsafePartial $ fromJust $ scriptHashFromBytes $ + mkStringHash s = unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe s test "getDatumByHash - not found" do @@ -125,8 +127,7 @@ fixtureHash = case _ of fixture1 :: Fixture fixture1 = TxWithMetadata - { hash: TransactionHash $ hexToByteArrayUnsafe - "7a2aff2b7f92f6f8ec3fb2135301c7bfc36fea1489a3ca37fd6066f3155c46ff" + { hash: txHash2 , metadata: GeneralTransactionMetadata $ Map.fromFoldable $ [ 30 /\ "5" @@ -185,13 +186,12 @@ fixture1 = TxWithMetadata , 77 /\ "4e5205e5df368030e9f814c2258c01f50c62375c55b07fbcc076c181::02" ] <#> \(label /\ text) -> - TransactionMetadatumLabel (BigInt.fromInt label) /\ Text text + BigNum.fromInt label /\ Text text } fixture2 :: Fixture fixture2 = TxWithMetadata - { hash: TransactionHash $ hexToByteArrayUnsafe - "d499729695be63b4c6affb2412899a7f16390d54d97f78f51d796a5cef424126" + { hash: txHash1 , metadata: GeneralTransactionMetadata $ Map.fromFoldable $ [ 674 /\ @@ -202,19 +202,26 @@ fixture2 = TxWithMetadata , "Timestamp" /\ "1672173001" ] ] <#> \(label /\ metamap) -> - TransactionMetadatumLabel - (BigInt.fromInt label) /\ MetadataMap + BigNum.fromInt label /\ Map (Map.fromFoldable $ metamap <#> \(k /\ v) -> Text k /\ Text v) } +txHash1 :: TransactionHash +txHash1 = TransactionHash $ unsafePartial $ fromJust $ fromBytes $ + hexToByteArrayUnsafe + "d499729695be63b4c6affb2412899a7f16390d54d97f78f51d796a5cef424126" + +txHash2 :: TransactionHash +txHash2 = TransactionHash $ unsafePartial $ fromJust $ fromBytes $ + hexToByteArrayUnsafe + "7b458500ef7783e16dab5d9f9f282505182c316ccf3ecf75d0472f95ab31eeaa" + fixture3 :: Fixture fixture3 = TxWithNoMetadata - { hash: TransactionHash $ hexToByteArrayUnsafe - "7b458500ef7783e16dab5d9f9f282505182c316ccf3ecf75d0472f95ab31eeaa" + { hash: txHash2 } fixture4 :: Fixture fixture4 = UnconfirmedTx - { hash: TransactionHash $ hexToByteArrayUnsafe - "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + { hash: txHash2 } diff --git a/test/Blockfrost/Aeson/Suite.purs b/test/Blockfrost/Aeson/Suite.purs index 2f246d48a3..347472cf0f 100644 --- a/test/Blockfrost/Aeson/Suite.purs +++ b/test/Blockfrost/Aeson/Suite.purs @@ -23,7 +23,6 @@ import Ctl.Internal.Service.Blockfrost , BlockfrostScriptInfo , BlockfrostSystemStart ) -import Ctl.Internal.Test.TestPlanM (TestPlanM, interpret) import Data.Array (catMaybes, length) import Data.Array.NonEmpty (tail) import Data.Bifunctor (bimap, lmap) @@ -38,6 +37,7 @@ import Data.Traversable (for_) import Effect (Effect) import Effect.Aff (Aff, error, launchAff_) import Mote (group, test) +import Mote.TestPlanM (TestPlanM, interpret) import Node.Encoding (Encoding(UTF8)) import Node.FS.Aff (readTextFile, readdir) import Node.Path (FilePath, basename, concat) diff --git a/test/Blockfrost/Contract.purs b/test/Blockfrost/Contract.purs index 138afc2cd6..6918624496 100644 --- a/test/Blockfrost/Contract.purs +++ b/test/Blockfrost/Contract.purs @@ -1,4 +1,4 @@ --- | Module to run `Test.Ctl.Plutip.Contract`s suite without Plutip, using +-- | Module to run `Test.Ctl.Testnet.Contract`s suite without Testnet, using -- | an already running instance of Blockfrost (preview). -- | -- | Use `npm run blockfrost-test` to run. @@ -13,7 +13,7 @@ import Data.Maybe (Maybe(Just)) import Data.Time.Duration (Milliseconds(Milliseconds)) import Effect (Effect) import Test.Ctl.Integration as IntegrationTest -import Test.Ctl.Plutip.Contract as Plutip +import Test.Ctl.Testnet.Contract as Testnet import Test.Spec.Runner (defaultConfig) as TestSpec main :: Effect Unit @@ -22,5 +22,5 @@ main = launchAff_ do TestSpec.defaultConfig { timeout = Just $ Milliseconds 1000000.0 } testnetConfig { suppressLogs = true } do - Plutip.suite + Testnet.suite IntegrationTest.stakingSuite diff --git a/test/Blockfrost/GenerateFixtures/Helpers.purs b/test/Blockfrost/GenerateFixtures/Helpers.purs index 5adb2fdbc6..3bc372455e 100644 --- a/test/Blockfrost/GenerateFixtures/Helpers.purs +++ b/test/Blockfrost/GenerateFixtures/Helpers.purs @@ -24,7 +24,7 @@ import Ctl.Internal.Contract.QueryBackend , defaultConfirmTxDelay , mkBlockfrostBackendParams ) -import Ctl.Internal.Hashing (md5HashHex) +import Ctl.Internal.ServerConfig (blockfrostPublicSanchonetServerConfig) import Data.Maybe (Maybe(Just, Nothing), maybe) import Data.String (take) as String import Effect.Exception (throw) @@ -33,6 +33,7 @@ import Node.FS.Aff (writeTextFile) import Node.FS.Sync (exists) import Node.Path (concat) import Node.Process (lookupEnv) +import Test.Ctl.Internal.Hashing (md5HashHex) blockfrostBackend :: Effect BlockfrostBackend blockfrostBackend = do @@ -58,6 +59,7 @@ contractParams = do } , logLevel = Info , walletSpec = Just $ UseKeys (PrivatePaymentKeyFile skeyFilepath) Nothing + Nothing } blockfrostConfigFromApiKey :: String -> Effect ServerConfig @@ -68,6 +70,8 @@ blockfrostConfigFromApiKey = String.take networkPrefixLength >>> case _ of pure blockfrostPublicPreviewServerConfig "preprod" -> pure blockfrostPublicPreprodServerConfig + "sanchon" -> + pure blockfrostPublicSanchonetServerConfig _ -> throw "Failed to derive server config from Blockfrost API key" where diff --git a/test/Blockfrost/GenerateFixtures/NativeScript.purs b/test/Blockfrost/GenerateFixtures/NativeScript.purs index 5d2c45a1ae..9ae633a6f9 100644 --- a/test/Blockfrost/GenerateFixtures/NativeScript.purs +++ b/test/Blockfrost/GenerateFixtures/NativeScript.purs @@ -2,6 +2,7 @@ module Test.Ctl.Blockfrost.GenerateFixtures.NativeScript (main) where import Contract.Prelude +import Cardano.Types.BigNum as BigNum import Contract.Config ( ContractParams , PrivatePaymentKeySource(PrivatePaymentKeyFile) @@ -29,10 +30,11 @@ import Ctl.Internal.Service.Blockfrost , BlockfrostRawResponse , runBlockfrostServiceTestM ) -import Ctl.Internal.Service.Blockfrost (getScriptByHash) as Blockfrost +import Ctl.Internal.Service.Blockfrost + ( getScriptByHash + ) as Blockfrost import Data.Array (mapWithIndex) import Data.UInt (fromInt) as UInt -import JS.BigInt (fromInt) as BigInt import Test.Ctl.Blockfrost.GenerateFixtures.Helpers ( blockfrostBackend , getSkeyFilepathFromEnv @@ -67,7 +69,7 @@ main = } , logLevel = Info , walletSpec = - Just $ UseKeys (PrivatePaymentKeyFile skeyFilepath) Nothing + Just $ UseKeys (PrivatePaymentKeyFile skeyFilepath) Nothing Nothing } generateFixtures :: Int -> Contract Unit @@ -87,7 +89,7 @@ generateFixtures numFixtures = do constraints :: Constraints.TxConstraints constraints = mustPayToPubKeyStakeAddressWithScriptRef pkh skh nativeScriptRef - (Value.lovelaceValueOf $ BigInt.fromInt 2_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 2_000_000) txHash <- submitTxFromConstraints mempty constraints awaitTxConfirmed txHash diff --git a/test/Blockfrost/GenerateFixtures/ProtocolParameters.purs b/test/Blockfrost/GenerateFixtures/ProtocolParameters.purs new file mode 100644 index 0000000000..097fe784fc --- /dev/null +++ b/test/Blockfrost/GenerateFixtures/ProtocolParameters.purs @@ -0,0 +1,43 @@ +module Test.Ctl.Blockfrost.GenerateFixtures.ProtocolParameters (main) where + +import Prelude + +import Ctl.Internal.Service.Blockfrost + ( BlockfrostEndpoint(LatestProtocolParameters) + , BlockfrostRawResponse + , runBlockfrostServiceTestM + ) +import Ctl.Internal.Service.Blockfrost (getProtocolParameters) as Blockfrost +import Data.Either (either) +import Data.Maybe (Maybe(Just, Nothing)) +import Effect (Effect) +import Effect.Aff (Aff, launchAff_) +import Effect.Class (liftEffect) +import Effect.Exception (throw) +import Test.Ctl.Blockfrost.GenerateFixtures.Helpers + ( blockfrostBackend + , storeBlockfrostFixture + ) + +main :: Effect Unit +main = launchAff_ generateFixture + +generateFixture :: Aff Unit +generateFixture = do + backend <- liftEffect blockfrostBackend + pparams <- runBlockfrostServiceTestM (const (pure unit)) backend + (Just onBlockfrostRawResponse) + Nothing + Blockfrost.getProtocolParameters + either (liftEffect <<< throw <<< show) (const (pure unit)) + pparams + where + onBlockfrostRawResponse + :: BlockfrostEndpoint + -> BlockfrostRawResponse + -> Aff Unit + onBlockfrostRawResponse query rawResp = + case query of + LatestProtocolParameters -> + storeBlockfrostFixture zero "getProtocolParameters" rawResp + _ -> pure unit diff --git a/test/Blockfrost/GenerateFixtures/ScriptInfo.purs b/test/Blockfrost/GenerateFixtures/ScriptInfo.purs index 46421748f3..a9125ce812 100644 --- a/test/Blockfrost/GenerateFixtures/ScriptInfo.purs +++ b/test/Blockfrost/GenerateFixtures/ScriptInfo.purs @@ -2,6 +2,7 @@ module Test.Ctl.Blockfrost.GenerateFixtures.ScriptInfo (main) where import Contract.Prelude +import Cardano.Types.BigNum as BigNum import Contract.Config ( ContractParams , PrivatePaymentKeySource(PrivatePaymentKeyFile) @@ -37,7 +38,6 @@ import Ctl.Internal.Service.Blockfrost (getScriptInfo) as Blockfrost import Data.Array (zip) as Array import Data.FoldableWithIndex (forWithIndex_) import Data.UInt (fromInt) as UInt -import JS.BigInt (fromInt) as BigInt import Test.Ctl.Blockfrost.GenerateFixtures.Helpers ( blockfrostBackend , getSkeyFilepathFromEnv @@ -72,7 +72,7 @@ main = } , logLevel = Info , walletSpec = - Just $ UseKeys (PrivatePaymentKeyFile skeyFilepath) Nothing + Just $ UseKeys (PrivatePaymentKeyFile skeyFilepath) Nothing Nothing } generateFixtures :: Contract Unit @@ -81,8 +81,8 @@ generateFixtures = do backend <- liftEffect blockfrostBackend nativeScriptRef <- liftEffect (NativeScriptRef <$> randomSampleOne arbitrary) - v1PlutusScriptRef <- PlutusScriptRef <$> unwrap <$> alwaysSucceedsScript - v2PlutusScriptRef <- PlutusScriptRef <$> unwrap <$> alwaysSucceedsScriptV2 + v1PlutusScriptRef <- PlutusScriptRef <$> alwaysSucceedsScript + v2PlutusScriptRef <- PlutusScriptRef <$> alwaysSucceedsScriptV2 let scriptRefs = [ nativeScriptRef, v1PlutusScriptRef, v2PlutusScriptRef ] @@ -94,7 +94,7 @@ generateFixtures = do skh <- ownStakePubKeyHash let value :: Value - value = Value.lovelaceValueOf $ BigInt.fromInt 2_000_000 + value = Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 constraints :: Constraints.TxConstraints constraints = diff --git a/test/Blockfrost/ProtocolParameters.purs b/test/Blockfrost/ProtocolParameters.purs index ec9e596c8e..47378bfd85 100644 --- a/test/Blockfrost/ProtocolParameters.purs +++ b/test/Blockfrost/ProtocolParameters.purs @@ -25,11 +25,11 @@ import Test.Spec.Runner (defaultConfig) blockfrostFixture :: String blockfrostFixture = - "blockfrost/getProtocolParameters/getProtocolParameters-2d2ce3159a465c84058d7eab67b1b345.json" + "blockfrost/getProtocolParameters/getProtocolParameters-6ac22050d53def4302608de2fa695f02.json" ogmiosFixture :: String ogmiosFixture = - "ogmios/queryLedgerState-protocolParameters-68ba1141d17af9326cad70407ea3d7fb.json" + "ogmios/queryLedgerState-protocolParameters-1d8c6233b8bfb7c028f1dd60eb113d40.json" loadFixture :: forall (a :: Type). DecodeAeson a => String -> Aff a loadFixture fixture = diff --git a/test/ByteArray.purs b/test/ByteArray.purs deleted file mode 100644 index 57b147199a..0000000000 --- a/test/ByteArray.purs +++ /dev/null @@ -1,45 +0,0 @@ -module Test.Ctl.ByteArray where - -import Prelude - -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.ByteArray - ( ByteArray - , byteArrayFromIntArray - , byteArrayFromIntArrayUnsafe - , byteArrayToHex - , byteArrayToIntArray - , hexToByteArray - ) -import Data.Maybe (Maybe(Just)) -import Effect.Aff (Aff) -import Effect.Class (liftEffect) -import Mote (group, test) -import Test.QuickCheck (quickCheck, (===)) -import Test.QuickCheck.Laws.Data.Eq (checkEq) -import Test.QuickCheck.Laws.Data.Monoid (checkMonoid) -import Test.QuickCheck.Laws.Data.Ord (checkOrd) -import Test.QuickCheck.Laws.Data.Semigroup (checkSemigroup) -import Type.Proxy (Proxy(Proxy)) - -suite :: TestPlanM (Aff Unit) Unit -suite = do - group "ByteArray" do - test "Eq instance" $ liftEffect do - checkEq (Proxy :: Proxy ByteArray) - test "Ord instance" $ liftEffect do - checkOrd (Proxy :: Proxy ByteArray) - test "Semigroup instance" $ liftEffect do - checkSemigroup (Proxy :: Proxy ByteArray) - test "Monoid instance" $ liftEffect do - checkMonoid (Proxy :: Proxy ByteArray) - test "hexToByteArray <<< byteArrayToHex = Just" $ liftEffect do - quickCheck \bytes -> - hexToByteArray (byteArrayToHex bytes) === Just bytes - test "byteArrayFromIntArrayUnsafe <<< byteArrayToIntArray = id" $ liftEffect - do - quickCheck \bytes -> - byteArrayFromIntArrayUnsafe (byteArrayToIntArray bytes) === bytes - test "byteArrayFromIntArray <<< byteArrayToIntArray = Just" $ liftEffect do - quickCheck \bytes -> - byteArrayFromIntArray (byteArrayToIntArray bytes) === Just bytes diff --git a/test/CoinSelection/Arbitrary.purs b/test/CoinSelection/Arbitrary.purs index 2ce2beb022..8ea7895b23 100644 --- a/test/CoinSelection/Arbitrary.purs +++ b/test/CoinSelection/Arbitrary.purs @@ -2,30 +2,19 @@ module Test.Ctl.CoinSelection.Arbitrary where import Prelude -import Control.Apply (lift2) -import Ctl.Internal.BalanceTx.CoinSelection (SelectionState, fromIndexFiltered) -import Ctl.Internal.Cardano.Types.Transaction - ( TransactionOutput(TransactionOutput) +import Cardano.Types + ( TransactionHash + , TransactionInput(TransactionInput) + , TransactionOutput(TransactionOutput) , UtxoMap ) -import Ctl.Internal.Cardano.Types.Value (Value) +import Control.Apply (lift2) +import Ctl.Internal.BalanceTx.CoinSelection (SelectionState, fromIndexFiltered) import Ctl.Internal.CoinSelection.UtxoIndex (UtxoIndex) import Ctl.Internal.CoinSelection.UtxoIndex (buildUtxoIndex) as UtxoIndex -import Ctl.Internal.Serialization.Address - ( Address - , NetworkId(MainnetId) - , baseAddressToAddress - , paymentKeyHashStakeKeyHashAddress - ) -import Ctl.Internal.Types.OutputDatum (OutputDatum(NoOutputDatum)) -import Ctl.Internal.Types.Transaction - ( TransactionHash - , TransactionInput(TransactionInput) - ) import Data.Generic.Rep (class Generic) import Data.Map (Map) import Data.Map.Gen (genMap) as Map -import Data.Maybe (Maybe(Nothing)) import Data.Newtype (class Newtype, unwrap, wrap) import Data.Show.Generic (genericShow) import Data.Tuple (Tuple(Tuple)) @@ -108,31 +97,7 @@ newtype ArbitraryTransactionOutput = derive instance Newtype ArbitraryTransactionOutput _ -instance Arbitrary ArbitraryTransactionOutput where - arbitrary = wrap <$> lift2 mkTxOutput arbitrary arbitrary - where - mkTxOutput :: ArbitraryAddress -> Value -> TransactionOutput - mkTxOutput address amount = - TransactionOutput - { address: unwrap address - , amount - , datum: NoOutputDatum - , scriptRef: Nothing - } - --------------------------------------------------------------------------------- --- ArbitraryAddress --------------------------------------------------------------------------------- - -newtype ArbitraryAddress = ArbitraryAddress Address - -derive instance Newtype ArbitraryAddress _ - -instance Arbitrary ArbitraryAddress where - arbitrary = - wrap <<< baseAddressToAddress <$> - lift2 (paymentKeyHashStakeKeyHashAddress MainnetId) arbitrary arbitrary - +derive newtype instance Arbitrary ArbitraryTransactionOutput -------------------------------------------------------------------------------- -- ArbitrarySelectionState -------------------------------------------------------------------------------- diff --git a/test/CoinSelection/CoinSelection.purs b/test/CoinSelection/CoinSelection.purs index 499db9afa7..c74466833a 100644 --- a/test/CoinSelection/CoinSelection.purs +++ b/test/CoinSelection/CoinSelection.purs @@ -2,6 +2,19 @@ module Test.Ctl.CoinSelection (suite) where import Prelude +import Cardano.AsCbor (decodeCbor) +import Cardano.Types + ( Address + , MultiAsset + , ScriptHash + , TransactionOutput(TransactionOutput) + , Value + ) +import Cardano.Types.AssetName (AssetName, mkAssetName) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.Value (mkValue) import Control.Monad.Error.Class (class MonadThrow) import Ctl.Internal.BalanceTx.CoinSelection ( SelectionStrategy(SelectionStrategyMinimal, SelectionStrategyOptimal) @@ -9,31 +22,15 @@ import Ctl.Internal.BalanceTx.CoinSelection , performMultiAssetSelection ) import Ctl.Internal.BalanceTx.Error (BalanceTxError) -import Ctl.Internal.Cardano.Types.Transaction - ( TransactionOutput(TransactionOutput) - ) -import Ctl.Internal.Cardano.Types.Value - ( CurrencySymbol - , NonAdaAsset - , Value - , mkCoin - , mkCurrencySymbol - , mkSingletonNonAdaAsset - , mkValue - ) import Ctl.Internal.CoinSelection.UtxoIndex (UtxoIndex) import Ctl.Internal.CoinSelection.UtxoIndex (buildUtxoIndex) as UtxoIndex -import Ctl.Internal.Hashing (blake2b224Hash) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.ByteArray (byteArrayFromAscii) -import Ctl.Internal.Types.OutputDatum (OutputDatum(NoOutputDatum)) -import Ctl.Internal.Types.TokenName (TokenName, mkTokenName) -import Ctl.Internal.Types.Transaction (TransactionInput) +import Ctl.Internal.Types.Val as Val +import Data.ByteArray (byteArrayFromAscii) import Data.Foldable (fold, foldMap) import Data.Generic.Rep (class Generic) import Data.Map (fromFoldable, values) as Map import Data.Maybe (Maybe(Nothing), fromJust) -import Data.Newtype (class Newtype, unwrap) +import Data.Newtype (class Newtype, unwrap, wrap) import Data.Show.Generic (genericShow) import Data.Traversable (for, for_) import Data.Tuple (Tuple(Tuple)) @@ -43,23 +40,23 @@ import Effect.Aff (Aff) import Effect.Class (class MonadEffect, liftEffect) import Effect.Exception (throw) import Effect.Unsafe (unsafePerformEffect) -import JS.BigInt (fromInt) as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Test.Ctl.CoinSelection.Arbitrary - ( ArbitraryAddress - , ArbitraryTransactionInput + ( ArbitraryTransactionInput , ArbitraryUtxoIndex ) import Test.Ctl.CoinSelection.RoundRobin (suite) as RoundRobin import Test.Ctl.CoinSelection.SelectionState (suite) as SelectionState import Test.Ctl.CoinSelection.UtxoIndex (suite) as UtxoIndex +import Test.Ctl.Internal.Hashing (blake2b224Hash) import Test.QuickCheck (class Testable, Result, assertEquals) import Test.QuickCheck (test) as QuickCheck import Test.QuickCheck.Arbitrary (arbitrary) import Test.QuickCheck.Gen (Gen, randomSampleOne) import Test.Spec.Assertions (shouldEqual) -import Test.Spec.QuickCheck (quickCheck) +import Test.Spec.QuickCheck (quickCheck') suite :: TestPlanM (Aff Unit) Unit suite = @@ -68,8 +65,8 @@ suite = SelectionState.suite UtxoIndex.suite group "performMultiAssetSelection" do - test "Performs a selection with zero outputs" do - quickCheck prop_performMultiAssetSelection_empty + test "Performs selection with zero outputs" do + quickCheck' 30 prop_performMultiAssetSelection_empty runSelectionTestWithFixture selFixture0 "Selects only from the 'singletons' subset if possible" runSelectionTestWithFixture selFixture1 @@ -96,10 +93,12 @@ runSelectionTestWithFixture mkFixture testLabel = td <- liftEffect $ selTestDataFromFixture (mkFixture strategy) selectedUtxos <- _.selectedUtxos <<< unwrap <$> - performMultiAssetSelection td.strategy td.utxoIndex td.requiredValue + performMultiAssetSelection td.strategy td.utxoIndex + (Val.fromValue td.requiredValue) liftEffect $ td.selectedValue `shouldEqual` - foldMap (_.amount <<< unwrap) (Map.values selectedUtxos) + unsafePartial + (foldMap (_.amount <<< unwrap) (Map.values selectedUtxos)) showSelStrategy :: SelectionStrategy -> String showSelStrategy strategy = @@ -134,28 +133,29 @@ type SelTestData = , selectedValue :: Value } -assetClassFromFixture :: AssetFixture -> CurrencySymbol /\ TokenName +assetClassFromFixture :: AssetFixture -> ScriptHash /\ AssetName assetClassFromFixture asset = currencySymbolFromAscii (show asset) /\ tokenNameFromAscii (show asset) where - currencySymbolFromAscii :: String -> CurrencySymbol + currencySymbolFromAscii :: String -> ScriptHash currencySymbolFromAscii str = unsafePartial fromJust $ - mkCurrencySymbol =<< map blake2b224Hash (byteArrayFromAscii str) + decodeCbor <<< wrap =<< map blake2b224Hash (byteArrayFromAscii str) - tokenNameFromAscii :: String -> TokenName + tokenNameFromAscii :: String -> AssetName tokenNameFromAscii = - unsafePartial fromJust <<< (mkTokenName <=< byteArrayFromAscii) + unsafePartial fromJust <<< (mkAssetName <=< byteArrayFromAscii) -assetFromFixture :: AssetFixture /\ Int -> NonAdaAsset +assetFromFixture :: AssetFixture /\ Int -> MultiAsset assetFromFixture (assetFixture /\ quantity) = - mkSingletonNonAdaAsset currencySymbol tokenName (BigInt.fromInt quantity) + MultiAsset.singleton currencySymbol tokenName (BigNum.fromInt quantity) where currencySymbol /\ tokenName = assetClassFromFixture assetFixture valueFromFixture :: TokenBundleFixture -> Value valueFromFixture (coin /\ assets) = - mkValue (mkCoin coin) (foldMap assetFromFixture assets) + mkValue (wrap $ BigNum.fromInt coin) + (unsafePartial $ foldMap assetFromFixture assets) selTestDataFromFixture :: SelFixture -> Effect SelTestData selTestDataFromFixture selFixture = do @@ -167,7 +167,8 @@ selTestDataFromFixture selFixture = do { strategy: selFixture.strategy , requiredValue: valueFromFixture selFixture.requiredValue , utxoIndex - , selectedValue: fold (valueFromFixture <$> selFixture.selectedUtxos) + , selectedValue: unsafePartial $ fold + (valueFromFixture <$> selFixture.selectedUtxos) } where txInputSample :: Effect TransactionInput @@ -176,9 +177,9 @@ selTestDataFromFixture selFixture = do mkTxOutput :: Value -> Effect TransactionOutput mkTxOutput amount = do - address <- unwrap <$> randomSampleOne (arbitrary :: Gen ArbitraryAddress) + address <- randomSampleOne (arbitrary :: Gen Address) pure $ TransactionOutput - { address, amount, datum: NoOutputDatum, scriptRef: Nothing } + { address, amount, datum: Nothing, scriptRef: Nothing } -------------------------------------------------------------------------------- diff --git a/test/CoinSelection/RoundRobin.purs b/test/CoinSelection/RoundRobin.purs index 13e95b6216..f2b22112a9 100644 --- a/test/CoinSelection/RoundRobin.purs +++ b/test/CoinSelection/RoundRobin.purs @@ -2,9 +2,8 @@ module Test.Ctl.CoinSelection.RoundRobin where import Prelude +import Cardano.Types.AssetName (AssetName) import Ctl.Internal.BalanceTx.CoinSelection (runRoundRobinM) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.TokenName (TokenName) import Data.Foldable (all, foldl, sum) import Data.Function (on) import Data.Generic.Rep (class Generic) @@ -33,6 +32,7 @@ import Data.Tuple.Nested (type (/\), (/\)) import Data.Unfoldable (replicateA) import Effect.Aff (Aff) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.Ctl.CoinSelection.Arbitrary (ArbitraryMap) import Test.QuickCheck (Result, (), (===)) import Test.QuickCheck.Arbitrary (class Arbitrary, arbitrary) @@ -95,7 +95,7 @@ prop_runRoundRobin_generationCount initialState = where finalState = runMockRoundRobin initialState - generationCounts :: Map TokenName Int + generationCounts :: Map AssetName Int generationCounts = (unwrap finalState).accumulatedEntries # groupByKey # map length @@ -106,7 +106,7 @@ prop_runRoundRobin_generationOrder initialState = where finalState = runMockRoundRobin initialState - generations :: Map Int (Set.Set TokenName) + generations :: Map Int (Set.Set AssetName) generations = (unwrap finalState).accumulatedEntries # map swap # groupByKey @@ -152,9 +152,9 @@ derive instance Generic (MockRoundRobinState k n) _ instance (Show k, Show n) => Show (MockRoundRobinState k n) where show = genericShow -type SimpleMockRoundRobinState = MockRoundRobinState TokenName Int +type SimpleMockRoundRobinState = MockRoundRobinState AssetName Int -derive instance Eq (MockRoundRobinState TokenName Int) +derive instance Eq (MockRoundRobinState AssetName Int) instance Arbitrary SimpleMockRoundRobinState where arbitrary = do @@ -163,12 +163,12 @@ instance Arbitrary SimpleMockRoundRobinState where pure $ MockRoundRobinState { processorLifetimes: lifetimes, accumulatedEntries: fromFoldable [] } where - genProcessorLifetimes :: Int -> Gen (Map.Map TokenName Int) + genProcessorLifetimes :: Int -> Gen (Map.Map AssetName Int) genProcessorLifetimes processorCount = Map.fromFoldable <$> (replicateA processorCount genProcessorLifetime :: Gen (Array _)) - genProcessorLifetime :: Gen (TokenName /\ Int) + genProcessorLifetime :: Gen (AssetName /\ Int) genProcessorLifetime = (/\) <$> arbitrary <*> chooseInt 0 127 -- Using `Arbitrary` leads to stack overflows in tests diff --git a/test/CoinSelection/SelectionState.purs b/test/CoinSelection/SelectionState.purs index aa87ebb307..ba0732f201 100644 --- a/test/CoinSelection/SelectionState.purs +++ b/test/CoinSelection/SelectionState.purs @@ -7,10 +7,10 @@ module Test.Ctl.CoinSelection.SelectionState import Prelude +import Cardano.Types.Asset (Asset) import Ctl.Internal.BalanceTx.CoinSelection (SelectionState) import Ctl.Internal.BalanceTx.CoinSelection as CoinSelection import Ctl.Internal.CoinSelection.UtxoIndex as UtxoIndex -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Data.Array.NonEmpty (cons') import Data.Maybe (Maybe(Just), isJust) import Data.Newtype (unwrap) @@ -18,6 +18,7 @@ import Data.Tuple.Nested ((/\)) import Effect.Aff (Aff) import Effect.Unsafe (unsafePerformEffect) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.Ctl.CoinSelection.Arbitrary ( ArbitrarySelectionState , ArbitraryTxUnspentOut @@ -54,7 +55,7 @@ prop_select_isValid u s = isValidSelection $ CoinSelection.selectUtxo (unwrap u) (unwrap s) prop_selectRandomWithPriority - :: ArbitraryUtxoIndex -> UtxoIndex.Asset -> UtxoIndex.Asset -> Boolean + :: ArbitraryUtxoIndex -> Asset -> Asset -> Boolean prop_selectRandomWithPriority index a1 a2 = if a1 == a2 then true else diff --git a/test/CoinSelection/UtxoIndex.purs b/test/CoinSelection/UtxoIndex.purs index 7def380dfc..23ca709d87 100644 --- a/test/CoinSelection/UtxoIndex.purs +++ b/test/CoinSelection/UtxoIndex.purs @@ -2,6 +2,7 @@ module Test.Ctl.CoinSelection.UtxoIndex (suite) where import Prelude +import Cardano.Types.TransactionInput (TransactionInput) import Ctl.Internal.CoinSelection.UtxoIndex ( SelectionFilter , UtxoIndex @@ -17,8 +18,6 @@ import Ctl.Internal.CoinSelection.UtxoIndex , utxoIndexInsertEntry , utxoIndexPartition ) as UtxoIndex -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.Transaction (TransactionInput) import Data.Map (empty) as Map import Data.Maybe (Maybe(Nothing, Just)) import Data.Newtype (unwrap) @@ -26,6 +25,7 @@ import Data.Tuple.Nested ((/\)) import Effect.Aff (Aff) import Effect.Unsafe (unsafePerformEffect) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.Ctl.CoinSelection.Arbitrary ( ArbitraryTxUnspentOut , ArbitraryUtxoIndex @@ -34,7 +34,7 @@ import Test.Ctl.CoinSelection.Arbitrary import Test.QuickCheck (Result(Failed, Success)) as QuickCheck import Test.QuickCheck ((===)) import Test.Spec.Assertions (shouldEqual) -import Test.Spec.QuickCheck (quickCheck) +import Test.Spec.QuickCheck (quickCheck, quickCheck') suite :: TestPlanM (Aff Unit) Unit suite = @@ -49,10 +49,10 @@ suite = quickCheck prop_partition_disjoint test "prop_utxoIndexInsertEntry_invariant" do - quickCheck prop_utxoIndexInsertEntry_invariant + quickCheck' 30 prop_utxoIndexInsertEntry_invariant test "prop_utxoIndexDeleteEntry_invariant" do - quickCheck prop_utxoIndexDeleteEntry_invariant + quickCheck' 30 prop_utxoIndexDeleteEntry_invariant group "SelectRandom" do test "prop_selectRandom_invariant" do diff --git a/test/CslGc.js b/test/CslGc.js new file mode 100644 index 0000000000..43539ec39a --- /dev/null +++ b/test/CslGc.js @@ -0,0 +1,28 @@ +import * as lib from "@mlabs-haskell/cardano-serialization-lib-gc"; + +import process from "process"; + +export const testExternalMemLeakImpl = config => async () => { + let externalMemUpperBound = null; + + for (let i = 0; i < config.numIterations; i++) { + // console.log(`\nIteration ${i}`); + + for (let j = 0; j < config.numArrays; j++) { + let bytes = new Uint8Array(Array(config.arrSize).fill(0)); + lib.PlutusData.new_bytes(bytes); + } + + await new Promise(r => setTimeout(r, config.delay)); + + const memUsage = process.memoryUsage(); + // console.log(memUsage); + + if (i == config.refIteration) { + externalMemUpperBound = memUsage.external * (1 + config.maxError / 100); + } + if (i > config.refIteration && memUsage.external > externalMemUpperBound) { + throw new Error("External memory leak detected."); + } + } +}; diff --git a/test/CslGc.purs b/test/CslGc.purs new file mode 100644 index 0000000000..6779b74e97 --- /dev/null +++ b/test/CslGc.purs @@ -0,0 +1,45 @@ +module Test.Ctl.CslGc + ( suite + ) where + +import Prelude + +import Control.Promise (Promise, toAffE) +import Effect (Effect) +import Effect.Aff (Aff) +import Mote (group, test) +import Mote.TestPlanM (TestPlanM) + +foreign import testExternalMemLeakImpl + :: CslGcTestConfig -> Effect (Promise Unit) + +suite :: TestPlanM (Aff Unit) Unit +suite = + group "CSL Garbage Collection" do + test "External memory does not leak" do + testExternalMemLeak + { numIterations: 15 + , refIteration: 5 + , maxError: 50 + , delay: 1200 + , numArrays: 20 + , arrSize: 1_000_000 + } + +type CslGcTestConfig = + { numIterations :: Int + , refIteration :: Int + , maxError :: Int -- percent + , delay :: Int -- msec + , numArrays :: Int + , arrSize :: Int + } + +-- We consider the test successfull if external memory consumption +-- stops growing after i-th iteration. +-- +-- Note, that wasm has no support for memory shrinking, i.e. once +-- the allocated memory is freed, it will be reused in subsequent +-- wasm allocations, but will not be returned to the process. +testExternalMemLeak :: CslGcTestConfig -> Aff Unit +testExternalMemLeak = toAffE <<< testExternalMemLeakImpl diff --git a/test/Data.purs b/test/Data.purs index 8271ca5a67..0b6515f7da 100644 --- a/test/Data.purs +++ b/test/Data.purs @@ -4,40 +4,37 @@ module Test.Ctl.Data (suite, tests, uniqueIndicesTests) where import Prelude hiding (conj) import Aeson (JsonDecodeError(TypeMismatch), decodeAeson, encodeAeson) -import Control.Lazy (fix) -import Control.Monad.Error.Class (class MonadThrow) -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.Deserialization.PlutusData as PDD -import Ctl.Internal.FromData (class FromData, fromData, genericFromData) -import Ctl.Internal.Helpers (showWithParens) -import Ctl.Internal.Plutus.Types.AssocMap (Map(Map)) -import Ctl.Internal.Plutus.Types.DataSchema +import Cardano.AsCbor (class AsCbor, encodeCbor) +import Cardano.FromData (class FromData, fromData, genericFromData) +import Cardano.Plutus.DataSchema ( class HasPlutusSchema + , class UniqueIndices , type (:+) , type (:=) , type (@@) - , I - , PNil - ) -import Ctl.Internal.Serialization (toBytes) -import Ctl.Internal.Serialization.PlutusData as PDS -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.ToData (class ToData, genericToData, toData) -import Ctl.Internal.TypeLevel.Nat (S, Z) -import Ctl.Internal.TypeLevel.RowList (class AllUniqueLabels) -import Ctl.Internal.TypeLevel.RowList.Unordered.Indexed - ( class UniqueIndices , ConsI + , I , NilI + , PNil + , S + , Z ) -import Ctl.Internal.Types.BigNum as BigNum -import Ctl.Internal.Types.ByteArray (hexToByteArrayUnsafe) -import Ctl.Internal.Types.PlutusData (PlutusData(Constr, Integer)) +import Cardano.Plutus.DataSchema.RowList (class AllUniqueLabels) +import Cardano.Plutus.Types.Map (Map(Map)) +import Cardano.Serialization.Lib (fromBytes) +import Cardano.ToData (class ToData, genericToData, toData) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.PlutusData (PlutusData(Constr, Integer)) +import Cardano.Types.PlutusData as PlutusData +import Control.Lazy (fix) +import Control.Monad.Error.Class (class MonadThrow) +import Ctl.Internal.Helpers (showWithParens) import Data.Array.NonEmpty (fromNonEmpty) as NEArray +import Data.ByteArray (hexToByteArrayUnsafe) import Data.Either (Either(Left, Right)) import Data.Generic.Rep as G import Data.Maybe (Maybe(Just, Nothing), fromJust, maybe) -import Data.Newtype (wrap) +import Data.Newtype (unwrap) import Data.NonEmpty ((:|)) import Data.Show.Generic (genericShow) import Data.Traversable (for_, traverse_) @@ -48,6 +45,7 @@ import Effect.Exception (Error) import JS.BigInt (BigInt) import JS.BigInt as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Test.QuickCheck ((===)) import Test.QuickCheck.Arbitrary (class Arbitrary, arbitrary, genericArbitrary) @@ -563,8 +561,8 @@ instance (FromData a) => FromData (Tree a) where Node <$> fromData a <*> (Tuple <$> worker ltree <*> worker rtree) fromBytesFromData :: forall a. FromData a => String -> Maybe a -fromBytesFromData binary = fromData <<< PDD.convertPlutusData =<< fromBytes - (wrap $ hexToByteArrayUnsafe binary) +fromBytesFromData binary = (fromData <<< PlutusData.fromCsl) =<< fromBytes + (hexToByteArrayUnsafe binary) testBinaryFixture :: forall a @@ -572,6 +570,7 @@ testBinaryFixture => Show a => FromData a => ToData a + => AsCbor a => a -> String -> TestPlanM (Aff Unit) Unit @@ -579,8 +578,8 @@ testBinaryFixture value binaryFixture = do test ("Deserialization: " <> show value) do fromBytesFromData binaryFixture `shouldEqual` Just value test ("Serialization: " <> show value) do - toBytes (PDS.convertPlutusData $ toData value) - `shouldEqual` wrap (hexToByteArrayUnsafe binaryFixture) + unwrap (encodeCbor value) + `shouldEqual` hexToByteArrayUnsafe binaryFixture -- | Poor man's type level tests tests :: Array String diff --git a/test/Data/Interval.purs b/test/Data/Interval.purs index 8808d9ad4d..490372c473 100644 --- a/test/Data/Interval.purs +++ b/test/Data/Interval.purs @@ -3,6 +3,15 @@ module Test.Ctl.Data.Interval (suite) where import Prelude +import Cardano.Plutus.DataSchema + ( class HasPlutusSchema + , type (:+) + , type (:=) + , type (@@) + , I + , PNil + , Z + ) import Contract.PlutusData ( class FromData , class ToData @@ -13,16 +22,6 @@ import Contract.PlutusData ) import Contract.Prelude (Aff, liftEffect) import Contract.Time (always, never) -import Ctl.Internal.Plutus.Types.DataSchema - ( class HasPlutusSchema - , type (:+) - , type (:=) - , type (@@) - , I - , PNil - ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.TypeLevel.Nat (Z) import Ctl.Internal.Types.Interval ( Extended(NegInf, Finite, PosInf) , Interval(EmptyInterval, StartAt, EndAt, AlwaysInterval, FiniteInterval) @@ -39,6 +38,7 @@ import Data.Show.Generic (genericShow) import JS.BigInt (BigInt) import JS.BigInt as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.QuickCheck (Result, arbitrary, quickCheck, (===)) import Test.QuickCheck.Gen (Gen) import Test.Spec.Assertions (shouldEqual) diff --git a/test/Deserialization.purs b/test/Deserialization.purs deleted file mode 100644 index d3af68ab9b..0000000000 --- a/test/Deserialization.purs +++ /dev/null @@ -1,292 +0,0 @@ -module Test.Ctl.Deserialization (suite) where - -import Prelude - -import Contract.Prim.ByteArray (ByteArray) -import Contract.TextEnvelope - ( TextEnvelope(TextEnvelope) - , TextEnvelopeType(Other) - , decodeTextEnvelope - ) -import Control.Monad.Error.Class (class MonadThrow, liftMaybe) -import Ctl.Internal.Cardano.Types.NativeScript (NativeScript(ScriptAny)) as T -import Ctl.Internal.Cardano.Types.Transaction (Transaction, TransactionOutput) as T -import Ctl.Internal.Cardano.Types.Transaction (Vkeywitness) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - ) as T -import Ctl.Internal.Deserialization.BigInt as DB -import Ctl.Internal.Deserialization.FromBytes (fromBytes, fromBytesEffect) -import Ctl.Internal.Deserialization.NativeScript as NSD -import Ctl.Internal.Deserialization.PlutusData as DPD -import Ctl.Internal.Deserialization.Transaction (convertTransaction) as TD -import Ctl.Internal.Deserialization.UnspentOutput - ( convertUnspentOutput - , mkTransactionUnspentOutput - ) -import Ctl.Internal.Deserialization.WitnessSet (convertWitnessSet) -import Ctl.Internal.Serialization (convertTransaction) as TS -import Ctl.Internal.Serialization (convertTxInput, convertTxOutput) as Serialization -import Ctl.Internal.Serialization.BigInt as SB -import Ctl.Internal.Serialization.NativeScript (convertNativeScript) as NSS -import Ctl.Internal.Serialization.PlutusData as SPD -import Ctl.Internal.Serialization.ToBytes (toBytes) -import Ctl.Internal.Serialization.ToBytes (toBytes) as Serialization -import Ctl.Internal.Serialization.Types (TransactionUnspentOutput) -import Ctl.Internal.Serialization.Types (Vkeywitness) as Serialization -import Ctl.Internal.Serialization.WitnessSet (convertVkeywitness) as Serialization -import Ctl.Internal.Serialization.WitnessSet as SW -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.BigNum (fromBigInt, toBigInt) as BigNum -import Ctl.Internal.Types.Transaction (TransactionInput) as T -import Data.Array as Array -import Data.Either (hush) -import Data.Foldable (fold) -import Data.Maybe (isJust, isNothing) -import Data.Newtype (unwrap, wrap) -import Data.Traversable (traverse) -import Effect (Effect) -import Effect.Aff (Aff) -import Effect.Class (class MonadEffect, liftEffect) -import Effect.Exception (Error, error) -import JS.BigInt as BigInt -import Mote (group, skip, test) -import Test.Ctl.Fixtures - ( nativeScriptFixture1 - , nativeScriptFixture2 - , nativeScriptFixture3 - , nativeScriptFixture4 - , nativeScriptFixture5 - , nativeScriptFixture6 - , nativeScriptFixture7 - , plutusDataFixture1 - , plutusDataFixture2 - , plutusDataFixture3 - , plutusDataFixture4 - , plutusDataFixture5 - , plutusDataFixture6 - , plutusDataFixture7 - , plutusDataFixture8 - , plutusDataFixture8Bytes - , plutusDataFixture8Bytes' - , txFixture1 - , txFixture2 - , txFixture3 - , txFixture4 - , txFixture5 - , txFixture6 - , txInputFixture1 - , txOutputFixture1 - , utxoFixture1 - , utxoFixture1' - , witnessSetFixture1 - , witnessSetFixture2 - , witnessSetFixture2Value - , witnessSetFixture3 - , witnessSetFixture3Value - , witnessSetFixture4 - ) -import Test.Ctl.Utils (errMaybe) -import Test.Spec.Assertions (expectError, shouldEqual, shouldSatisfy) - -suite :: TestPlanM (Aff Unit) Unit -suite = do - group "deserialization" $ do - group "BigInt" do - test "Deserialization is inverse to serialization" do - let bigInt = BigInt.fromInt 123 - res <- errMaybe "Failed to serialize BigInt" do - DB.convertBigInt =<< SB.convertBigInt bigInt - res `shouldEqual` bigInt - group "BigNum" do - test "Deserialization is inverse to serialization" do - let bigInt = BigInt.fromInt 123 - res <- errMaybe "Failed to serialize BigInt" $ BigNum.fromBigInt bigInt - <#> BigNum.toBigInt - res `shouldEqual` bigInt - group "CSL <-> CTL PlutusData roundtrip tests" do - let - pdRoundTripTest ctlPd = do - cslPd' <- errMaybe "Failed to fromBytes PlutusData" $ fromBytes - $ Serialization.toBytes - $ SPD.convertPlutusData ctlPd - let ctlPd' = DPD.convertPlutusData cslPd' - ctlPd' `shouldEqual` ctlPd - test "fixture #1" $ pdRoundTripTest plutusDataFixture1 - test "fixture #2" $ pdRoundTripTest plutusDataFixture2 - test "fixture #3" $ pdRoundTripTest plutusDataFixture3 - test "fixture #4" $ pdRoundTripTest plutusDataFixture4 - test "fixture #5" $ pdRoundTripTest plutusDataFixture5 - test "fixture #6" $ pdRoundTripTest plutusDataFixture6 - test "fixture #7" $ pdRoundTripTest plutusDataFixture7 - test "fixture #8" $ pdRoundTripTest plutusDataFixture8 - test - "fixture #8 different Cbor bytes encodings (compact vs general Constr tag encodings)" - $ do - cslPd' <- errMaybe "Failed to fromBytes PlutusData" $ fromBytes - $ wrap plutusDataFixture8Bytes - let ctlPd' = DPD.convertPlutusData cslPd' - ctlPd' `shouldEqual` plutusDataFixture8 - cslPdWp' <- errMaybe "Failed to fromBytes PlutusData" $ fromBytes - $ wrap plutusDataFixture8Bytes' - let ctlPdWp' = DPD.convertPlutusData cslPdWp' - ctlPdWp' `shouldEqual` plutusDataFixture8 - group "UnspentTransactionOutput" do - test "deserialization is inverse to serialization" do - unspentOutput <- liftEffect $ createUnspentOutput txInputFixture1 - txOutputFixture1 - T.TransactionUnspentOutput { input, output } <- - errMaybe "Failed deserialization 3" do - convertUnspentOutput unspentOutput - input `shouldEqual` txInputFixture1 - output `shouldEqual` txOutputFixture1 - test "fixture #1" do - res <- errMaybe "Failed deserialization 4" do - fromBytes (wrap utxoFixture1) >>= - convertUnspentOutput - res `shouldEqual` utxoFixture1' - group "Transaction Roundtrips" do - test "CSL <-> CTL Transaction roundtrip #1" $ txRoundtrip txFixture1 - test "CSL <-> CTL Transaction roundtrip #2" $ txRoundtrip txFixture2 - test "CSL <-> CTL Transaction roundtrip #3" $ txRoundtrip txFixture3 - test "CSL <-> CTL Transaction roundtrip #4" $ txRoundtrip txFixture4 - test "CSL <-> CTL Transaction roundtrip #5" $ txRoundtrip txFixture5 - test "CSL <-> CTL Transaction roundtrip #6" $ txRoundtrip txFixture6 - group "WitnessSet - deserialization" do - group "fixture #1" do - res <- errMaybe "Failed deserialization 5" do - fromBytes (wrap witnessSetFixture1) <#> convertWitnessSet - test "has vkeys" do - (unwrap res).vkeys `shouldSatisfy` isJust - test "has plutusData" do - (unwrap res).plutusData `shouldSatisfy` isJust - test "has plutusScripts" do - (unwrap res).plutusScripts `shouldSatisfy` isJust - test "has redeemers" do - (unwrap res).redeemers `shouldSatisfy` isJust - test "has redeemers" do - (unwrap res).redeemers `shouldSatisfy` isJust - test "does not have nativeScripts" do - (unwrap res).nativeScripts `shouldSatisfy` isNothing - test "fixture #2" do - res <- errMaybe "Failed deserialization 6" do - fromBytes (wrap witnessSetFixture2) <#> convertWitnessSet - res `shouldEqual` witnessSetFixture2Value - test "fixture #3" do - res <- errMaybe "Failed deserialization 7" do - fromBytes (wrap witnessSetFixture3) <#> convertWitnessSet - res `shouldEqual` witnessSetFixture3Value - group "fixture #4" do - res <- errMaybe "Failed deserialization 8" $ - fromBytes (wrap witnessSetFixture4) <#> convertWitnessSet - test "has nativeScripts" do - (unwrap res).nativeScripts `shouldSatisfy` isJust - group "NativeScript - deserializaton is inverse to serialization" do - test "fixture #1" do - liftEffect $ testNativeScript nativeScriptFixture1 - test "fixture #2" do - liftEffect $ testNativeScript nativeScriptFixture2 - test "fixture #3" do - liftEffect $ testNativeScript nativeScriptFixture3 - test "fixture #4" do - liftEffect $ testNativeScript nativeScriptFixture4 - test "fixture #5" do - liftEffect $ testNativeScript nativeScriptFixture5 - test "fixture #6" do - liftEffect $ testNativeScript nativeScriptFixture6 - test "fixture #7" do - liftEffect $ testNativeScript nativeScriptFixture7 - test "fixture #7" do - liftEffect $ testNativeScript nativeScriptFixture7 - -- This is here just to acknowledge the problem - skip $ test "too much nesting leads to recursion error" do - expectError $ do - let - longNativeScript = - Array.foldr (\_ acc -> T.ScriptAny [ acc ]) nativeScriptFixture1 $ - Array.range 0 50 -- change this to 50000 - liftEffect $ testNativeScript longNativeScript - group "WitnessSet - deserialization is inverse to serialization" do - let - vkeyWitnessesRoundtrip - :: ∀ (m :: Type -> Type) - . MonadEffect m - => MonadThrow Error m - => Array Vkeywitness - -> m Unit - vkeyWitnessesRoundtrip vks = do - cslVks <- traverse (liftEffect <<< Serialization.convertVkeywitness) - vks - let cslVksBytes = toBytes <$> cslVks - (_ :: Array Serialization.Vkeywitness) <- traverse - (liftEffect <<< fromBytesEffect) - cslVksBytes - pure unit - - witnessSetRoundTrip - :: ∀ (m :: Type -> Type) - . MonadEffect m - => MonadThrow Error m - => ByteArray - -> m Unit - witnessSetRoundTrip fixture = do - ws0 <- errMaybe "Failed deserialization" $ - fromBytes (wrap fixture) <#> convertWitnessSet - ws1 <- liftEffect $ SW.convertWitnessSet ws0 - let - ws2 = convertWitnessSet ws1 - vkeys = fold (unwrap ws2).vkeys - vkeyWitnessesRoundtrip vkeys - ws0 `shouldEqual` ws2 -- value representation - let wsBytes = unwrap $ Serialization.toBytes ws1 - wsBytes `shouldEqual` fixture -- byte representation - test "fixture #1" $ witnessSetRoundTrip witnessSetFixture1 - test "fixture #2" $ witnessSetRoundTrip witnessSetFixture2 - test "fixture #3" $ witnessSetRoundTrip witnessSetFixture3 - -- TODO: enable when nativeScripts are implemented - test "fixture #4" $ witnessSetRoundTrip witnessSetFixture4 - group "TextEnvelope decoding" do - test "Decoding TestEnvelope with some other type" do - let - otherTypeTextEnvelope = - """ - { - "cborHex": "484701000022120011", - "description": "other-type-text-envelope", - "type": "SomeOtherType" - } - """ - TextEnvelope envelope <- liftMaybe (error "Unexpected parsing error") $ - decodeTextEnvelope otherTypeTextEnvelope - envelope.type_ `shouldEqual` (Other "SomeOtherType") - -createUnspentOutput - :: T.TransactionInput - -> T.TransactionOutput - -> Effect TransactionUnspentOutput -createUnspentOutput input output = do - input' <- Serialization.convertTxInput input - output' <- Serialization.convertTxOutput output - pure $ mkTransactionUnspentOutput input' output' - -testNativeScript :: T.NativeScript -> Effect Unit -testNativeScript input = do - serialized <- pure $ NSS.convertNativeScript input - {- ^^^^ This is necessary here as convertNativeScript can throw - a maximum call stack size runtime error (see excessive nesting - test above). It needs to be lifted into the Effect monad for - purescript to handle it correctly. - -} - - let bytes = Serialization.toBytes serialized - res <- errMaybe "Failed deserialization" $ fromBytes bytes - let - res' = NSD.convertNativeScript res - res' `shouldEqual` input - -txRoundtrip :: T.Transaction -> Aff Unit -txRoundtrip tx = do - cslTX <- liftEffect $ TS.convertTransaction tx - expected <- errMaybe "Cannot convert TX from CSL to CTL" $ hush $ - TD.convertTransaction cslTX - tx `shouldEqual` expected diff --git a/test/E2E/Route.purs b/test/E2E/Route.purs index 8d20e41669..e8e1f91e01 100644 --- a/test/E2E/Route.purs +++ b/test/E2E/Route.purs @@ -3,10 +3,10 @@ module Test.Ctl.E2E.Route where import Prelude import Ctl.Internal.Test.E2E.Route (parseRoute) -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Data.Either (isRight) import Effect.Aff (Aff) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.Spec.Assertions (shouldSatisfy) suite :: TestPlanM (Aff Unit) Unit diff --git a/test/Fixtures.purs b/test/Fixtures.purs index 32872c7072..dbd26864f3 100644 --- a/test/Fixtures.purs +++ b/test/Fixtures.purs @@ -11,17 +11,13 @@ -- ``` module Test.Ctl.Fixtures ( addressString1 - , cip25MetadataFixture1 - , cip25MetadataFixture2 - , cip25MetadataFixture3 - , cip25MetadataFixture4 - , cip25MetadataJsonFixture1 - , cip25MetadataJsonFixture2 - , cip25MetadataJsonFixture3 , currencySymbol1 , ed25519KeyHash1 , ed25519KeyHashFixture1 , fullyAppliedScriptFixture + , int1 + , mint0 + , mint1 , mkSampleTx , mkTxInput , nativeScriptFixture1 @@ -32,8 +28,8 @@ module Test.Ctl.Fixtures , nativeScriptFixture6 , nativeScriptFixture7 , nullPaymentPubKeyHash - , ogmiosEvaluateTxFailScriptErrorsFixture , ogmiosEvaluateTxFailIncompatibleEraFixture + , ogmiosEvaluateTxFailScriptErrorsFixture , ogmiosEvaluateTxInvalidPointerFormatFixture , ogmiosEvaluateTxValidRespFixture , partiallyAppliedScriptFixture @@ -47,6 +43,9 @@ module Test.Ctl.Fixtures , plutusDataFixture8 , plutusDataFixture8Bytes , plutusDataFixture8Bytes' + , plutusScriptFixture1 + , plutusScriptFixture2 + , plutusScriptFixture3 , redeemerFixture1 , tokenName1 , tokenName2 @@ -57,164 +56,81 @@ module Test.Ctl.Fixtures , txBinaryFixture5 , txBinaryFixture6 , txFixture1 - , txFixture2 - , txFixture3 - , txFixture4 - , txFixture5 - , txFixture6 , txInputFixture1 , txOutputBinaryFixture1 , txOutputFixture1 , txOutputFixture2 , unappliedScriptFixture - , unsafeMkCip25String , utxoFixture1 , utxoFixture1' + , utxoMapFixture , witnessSetFixture1 , witnessSetFixture2 , witnessSetFixture2Value , witnessSetFixture3 , witnessSetFixture3Value , witnessSetFixture4 - , utxoMapFixture + , txMetadatumFixture ) where import Prelude import Aeson (Aeson, aesonNull, decodeAeson, fromString, parseJsonStringToAeson) -import Contract.Numeric.BigNum (BigNum) -import Contract.Numeric.BigNum (fromBigInt, fromInt, one, zero) as BigNum -import Contract.Transaction - ( PoolPubKeyHash(PoolPubKeyHash) - , vrfKeyHashFromBytes - ) -import Ctl.Internal.Cardano.Types.NativeScript - ( NativeScript - ( ScriptPubkey - , ScriptAll - , ScriptAny - , ScriptNOfK +import Cardano.AsCbor (decodeCbor) +import Cardano.Types + ( Bech32String + , Coin(Coin) + , Credential(PubKeyHashCredential) + , Ed25519KeyHash + , ExUnits(ExUnits) + , Language(PlutusV2) + , NativeScript + ( TimelockExpiry , TimelockStart - , TimelockExpiry - ) - ) -import Ctl.Internal.Cardano.Types.ScriptRef - ( ScriptRef(PlutusScriptRef, NativeScriptRef) - ) -import Ctl.Internal.Cardano.Types.Transaction - ( AuxiliaryData(AuxiliaryData) - , AuxiliaryDataHash(AuxiliaryDataHash) - , Certificate - ( MoveInstantaneousRewardsCert - , GenesisKeyDelegation - , PoolRetirement - , PoolRegistration - , StakeDelegation - , StakeDeregistration - , StakeRegistration + , ScriptNOfK + , ScriptAny + , ScriptAll + , ScriptPubkey ) - , Epoch(Epoch) - , GenesisDelegateHash(GenesisDelegateHash) - , GenesisHash(GenesisHash) - , Ipv4(Ipv4) - , Ipv6(Ipv6) - , MIRToStakeCredentials(MIRToStakeCredentials) - , Mint(Mint) - , MoveInstantaneousReward(ToStakeCreds, ToOtherPot) - , PoolMetadata(PoolMetadata) - , PoolMetadataHash(PoolMetadataHash) - , ProposedProtocolParameterUpdates(ProposedProtocolParameterUpdates) + , NetworkId(TestnetId, MainnetId) + , PaymentPubKeyHash(PaymentPubKeyHash) + , PlutusData(Integer, Bytes, Constr, List, Map) + , PlutusScript(PlutusScript) , Redeemer(Redeemer) - , Relay(MultiHostName, SingleHostName, SingleHostAddr) - , RequiredSigner(RequiredSigner) + , RedeemerTag(Spend) + , ScriptHash + , Slot(Slot) , Transaction(Transaction) + , TransactionBody(TransactionBody) + , TransactionInput(TransactionInput) , TransactionOutput(TransactionOutput) + , TransactionUnspentOutput(TransactionUnspentOutput) , TransactionWitnessSet(TransactionWitnessSet) - , TxBody(TxBody) - , URL(URL) , UtxoMap + , Value(Value) , Vkey(Vkey) , Vkeywitness(Vkeywitness) - , mkEd25519Signature - , mkPublicKey - ) -import Ctl.Internal.Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - ) -import Ctl.Internal.Cardano.Types.Value - ( Coin(Coin) - , CurrencySymbol - , Value(Value) - , mkCurrencySymbol - , mkNonAdaAsset - , mkSingletonNonAdaAsset - ) -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.Metadata.Cip25.Cip25String (Cip25String, mkCip25String) -import Ctl.Internal.Metadata.Cip25.Common (Cip25TokenName(Cip25TokenName)) -import Ctl.Internal.Metadata.Cip25.V2 - ( Cip25Metadata(Cip25Metadata) - , Cip25MetadataEntry(Cip25MetadataEntry) - , Cip25MetadataFile(Cip25MetadataFile) - ) -import Ctl.Internal.Serialization.Address - ( Address - , NetworkId(MainnetId, TestnetId) - , Slot(Slot) - , StakeCredential - , baseAddress - , baseAddressToAddress - , keyHashCredential - , rewardAddress - ) -import Ctl.Internal.Serialization.Hash - ( Ed25519KeyHash - , ScriptHash - , ed25519KeyHashFromBech32 - , ed25519KeyHashFromBytes - , scriptHashFromBytes ) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.ByteArray +import Cardano.Types.Address (Address(BaseAddress)) +import Cardano.Types.AssetName (AssetName, mkAssetName) +import Cardano.Types.Ed25519KeyHash as Ed25519KeyHash +import Cardano.Types.Ed25519Signature as Ed25519Signature +import Cardano.Types.Int as Int +import Cardano.Types.Mint (Mint(Mint)) +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.PlutusScript (plutusV1Script, plutusV2Script) +import Cardano.Types.PublicKey as PublicKey +import Contract.Numeric.BigNum (fromInt, one, zero) as BigNum +import Data.ByteArray ( ByteArray , byteArrayFromIntArrayUnsafe - , hexToByteArray , hexToByteArrayUnsafe ) -import Ctl.Internal.Types.CborBytes (CborBytes(CborBytes)) -import Ctl.Internal.Types.Int as Int -import Ctl.Internal.Types.OutputDatum (OutputDatum(NoOutputDatum, OutputDatum)) -import Ctl.Internal.Types.PlutusData as PD -import Ctl.Internal.Types.PubKeyHash - ( PaymentPubKeyHash(PaymentPubKeyHash) - , PubKeyHash(PubKeyHash) - ) -import Ctl.Internal.Types.RedeemerTag (RedeemerTag(Spend)) -import Ctl.Internal.Types.RewardAddress (RewardAddress(RewardAddress)) -import Ctl.Internal.Types.Scripts - ( MintingPolicyHash(MintingPolicyHash) - , PlutusScript - , Validator - , plutusV1Script - , plutusV2Script - ) -import Ctl.Internal.Types.TokenName (TokenName, mkTokenName) -import Ctl.Internal.Types.Transaction - ( TransactionHash(TransactionHash) - , TransactionInput(TransactionInput) - ) -import Ctl.Internal.Types.TransactionMetadata - ( GeneralTransactionMetadata(GeneralTransactionMetadata) - , TransactionMetadatum(Text) - , TransactionMetadatumLabel(TransactionMetadatumLabel) - ) -import Data.Array as Array import Data.Either (fromRight, hush) import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing), fromJust) import Data.Newtype (wrap) -import Data.Set (Set) -import Data.Set (singleton) as Set +import Data.Tuple (Tuple(Tuple)) import Data.Tuple.Nested ((/\)) import Data.UInt as UInt import Effect (Effect) @@ -222,28 +138,29 @@ import JS.BigInt as BigInt import Node.Encoding (Encoding(UTF8)) import Node.FS.Sync (readTextFile) import Partial.Unsafe (unsafePartial) -import Test.Ctl.Fixtures.CostModels (costModelsFixture1) txOutputFixture1 :: TransactionOutput txOutputFixture1 = TransactionOutput - { address: baseAddressToAddress $ baseAddress - { network: TestnetId - , delegationCred: - keyHashCredential $ unsafePartial $ fromJust - $ ed25519KeyHashFromBytes + { address: BaseAddress + { networkId: TestnetId + , stakeCredential: + wrap $ PubKeyHashCredential $ unsafePartial $ fromJust + $ decodeCbor + $ wrap -- $ T.Bech32 "hstk_1rsf0q0q77t5nttxrtmpwd7tvv58a80a686t92pgy65ekz0s8ncu" $ hexToByteArrayUnsafe "1c12f03c1ef2e935acc35ec2e6f96c650fd3bfba3e96550504d53361" - , paymentCred: - keyHashCredential $ unsafePartial $ fromJust - $ ed25519KeyHashFromBytes + , paymentCredential: + wrap $ PubKeyHashCredential $ unsafePartial $ fromJust + $ decodeCbor + $ wrap -- "hbas_1xranhpfej50zdup5jy995dlj9juem9x36syld8wm465hz92acfp" $ hexToByteArrayUnsafe "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" } - , amount: Value (Coin $ BigInt.fromInt 0) mempty - , datum: NoOutputDatum + , amount: Value (Coin $ BigNum.fromInt 0) MultiAsset.empty + , datum: Nothing , scriptRef: Nothing } @@ -254,31 +171,28 @@ txOutputFixture2 = { stake: "1c12f03c1ef2e935acc35ec2e6f96c650fd3bfba3e96550504d53361" , payment: "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" } - , amount: Value (Coin $ BigInt.fromInt 0) $ - mkSingletonNonAdaAsset currencySymbol1 tokenName1 - (BigInt.fromInt 1000000) - , datum: NoOutputDatum + , amount: Value (Coin $ BigNum.fromInt 0) $ + MultiAsset.singleton currencySymbol1 tokenName1 + (BigNum.fromInt 1000000) + , datum: Nothing , scriptRef: Nothing } -currencySymbol1 :: CurrencySymbol -currencySymbol1 = unsafePartial $ fromJust $ mkCurrencySymbol $ +currencySymbol1 :: ScriptHash +currencySymbol1 = unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "1d6445ddeda578117f393848e685128f1e78ad0c4e48129c5964dc2e" -tokenNameFromString :: String -> TokenName -tokenNameFromString s = unsafePartial $ fromJust $ mkTokenName $ +tokenNameFromString :: String -> AssetName +tokenNameFromString s = unsafePartial $ fromJust $ mkAssetName $ hexToByteArrayUnsafe s -tokenName1 :: TokenName +tokenName1 :: AssetName tokenName1 = tokenNameFromString "4974657374546f6b656e" -tokenName2 :: TokenName +tokenName2 :: AssetName tokenName2 = tokenNameFromString "54657374546f6b656e32" -tokenName4 :: TokenName -tokenName4 = tokenNameFromString "abcdef" - txOutputBinaryFixture1 :: String txOutputBinaryFixture1 = "8258390030fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea9711c12f03c1ef2\ @@ -287,62 +201,12 @@ txOutputBinaryFixture1 = pkhBech32 :: Bech32String pkhBech32 = "addr_vkh1zuctrdcq6ctd29242w8g84nlz0q38t2lnv3zzfcrfqktx0c9tzp" -stake1 :: StakeCredential -stake1 = unsafePartial $ fromJust do - keyHashCredential <$> ed25519KeyHashFromBech32 pkhBech32 - ed25519KeyHash1 :: Ed25519KeyHash -ed25519KeyHash1 = unsafePartial $ fromJust $ ed25519KeyHashFromBech32 pkhBech32 - -bigNumOne :: BigNum -bigNumOne = unsafePartial $ fromJust $ BigNum.fromBigInt $ BigInt.fromInt 1 - -rewardAddress1 :: RewardAddress -rewardAddress1 = RewardAddress $ rewardAddress - { network: TestnetId, paymentCred: stake1 } - -proposedProtocolParameterUpdates1 :: ProposedProtocolParameterUpdates -proposedProtocolParameterUpdates1 = ProposedProtocolParameterUpdates $ - Map.fromFoldable - [ GenesisHash - ( hexToByteArrayUnsafe - "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" - ) /\ - { minfeeA: Just $ Coin $ BigInt.fromInt 1 - , minfeeB: Just $ Coin $ BigInt.fromInt 1 - , maxBlockBodySize: Just $ UInt.fromInt 10000 - , maxTxSize: Just $ UInt.fromInt 10000 - , maxBlockHeaderSize: Just $ UInt.fromInt 1000 - , keyDeposit: Just $ Coin $ BigInt.fromInt 1 - , poolDeposit: Just $ Coin $ BigInt.fromInt 1 - , maxEpoch: Just $ Epoch one - , nOpt: Just $ UInt.fromInt 1 - , poolPledgeInfluence: Just - { numerator: bigNumOne, denominator: bigNumOne } - , expansionRate: Just { numerator: bigNumOne, denominator: bigNumOne } - , treasuryGrowthRate: Just - { numerator: bigNumOne, denominator: bigNumOne } - , protocolVersion: Just - { major: UInt.fromInt 1, minor: UInt.fromInt 1 } - , minPoolCost: Just bigNumOne - , adaPerUtxoByte: Just bigNumOne - , costModels: Just costModelsFixture1 - , executionCosts: Just - { memPrice: { numerator: bigNumOne, denominator: bigNumOne } - , stepPrice: { numerator: bigNumOne, denominator: bigNumOne } - } - , maxTxExUnits: Just { mem: BigInt.fromInt 1, steps: BigInt.fromInt 1 } - , maxBlockExUnits: Just - { mem: BigInt.fromInt 1, steps: BigInt.fromInt 1 } - , maxValueSize: Just $ UInt.fromInt 1 - , collateralPercentage: Just $ UInt.fromInt 140 - , maxCollateralInputs: Just $ UInt.fromInt 10 - } - ] +ed25519KeyHash1 = unsafePartial $ fromJust $ Ed25519KeyHash.fromBech32 pkhBech32 -- | Extend this for your needs. type SampleTxConfig = - { inputs :: Set TransactionInput } + { inputs :: Array TransactionInput } -- | Build a sample transaction using convenient config -- | and existing one as a base. @@ -356,19 +220,18 @@ mkSampleTx startTx changes = where buildChanges :: Transaction -> (SampleTxConfig -> SampleTxConfig) -> SampleTxConfig - buildChanges (Transaction { body: TxBody { inputs } }) mkChanges = + buildChanges (Transaction { body: TransactionBody { inputs } }) mkChanges = mkChanges { inputs } applyChanges :: Transaction -> SampleTxConfig -> Transaction applyChanges ( Transaction - { body: TxBody + { body: TransactionBody { outputs , fee , ttl , certs , withdrawals - , update , auxiliaryDataHash , validityStartInterval , mint @@ -379,6 +242,10 @@ mkSampleTx startTx changes = , networkId , collateralReturn , totalCollateral + , votingProposals + , votingProcedures + , currentTreasuryValue + , donation } , witnessSet , isValid @@ -387,14 +254,13 @@ mkSampleTx startTx changes = ) { inputs: newInputs } = ( Transaction - { body: TxBody + { body: TransactionBody { inputs: newInputs , outputs , fee , ttl , certs , withdrawals - , update , auxiliaryDataHash , validityStartInterval , mint @@ -405,6 +271,10 @@ mkSampleTx startTx changes = , networkId , collateralReturn , totalCollateral + , votingProposals + , votingProcedures + , currentTreasuryValue + , donation } , witnessSet , isValid @@ -423,350 +293,73 @@ plutusScriptFixture2 = unsafePartial $ fromJust $ map plutusV2Script $ hush $ decodeAeson $ fromString "4d010000deadbeef33222220051200120011" +txMetadatumFixture :: ByteArray +txMetadatumFixture = hexToByteArrayUnsafe "60" -- "a11902d1a278383733336136646663363063613639396261616236346336353836663464633138653263613733343232363730333439666361396235346339a174537061636550756773476c617373504334393730ab646e616d65781b5370616365205075677320476c617373202d20504320233439373065696d6167657835697066733a2f2f516d516f4d61554e3239554278776154515373566b48783748324d57627365794e6d4c78386f745a7a5167395a34696d656469615479706569696d6167652f6769666b6465736372697074696f6e606566696c657381a3646e616d6574537061636550756773476c617373504334393730696d656469615479706569766964656f2f6d7034637372637835697066733a2f2f516d57646b7231634b42345065764739784a4b76536e71336d33354a5478726771673158725742475062456f62696a4261636b67726f756e646b507572706c652046656c7463546f706e517565656e204f6620436c75627366426f74746f6d754a61636b204f662048656172747320426f74746f6d6644657369676e75323920284d616420446f672043617220436c756229664578747261737157696e73746f6e20436875726368696c6c684c69676874696e676c4e6f726d616c204c696768746776657273696f6e63312e30" + +plutusScriptFixture3 :: PlutusScript +plutusScriptFixture3 = + ( PlutusScript + ( Tuple + ( hexToByteArrayUnsafe + "59088501000032332232323233223232323232323232323322323232323232322223232533532325335001101b13357389211d556e657870656374656420646174756d206174206f776e20696e7075740001a323253335002153335001101c2101c2101c2153335002101c21333573466ebc00800407807484074854ccd400840708407484ccd5cd19b8f00200101e01d323500122220023235001220013553353500222350022222222222223333500d2501e2501e2501e233355302d12001321233001225335002210031001002501e2350012253355335333573466e3cd400888008d4010880080b40b04ccd5cd19b873500222001350042200102d02c102c1350220031502100d21123001002162001300a0053333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4054058d5d0a80619a80a80b1aba1500b33501501735742a014666aa034eb94064d5d0a804999aa80d3ae501935742a01066a02a0426ae85401cccd54068089d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b1d69aba15002302d357426ae8940088c98c80bccd5ce01901881689aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8163ad35742a004605a6ae84d5d1280111931901799ab9c03203102d135573ca00226ea8004d5d09aba2500223263202b33573805c05a05226aae7940044dd50009aba1500533501575c6ae854010ccd540680788004d5d0a801999aa80d3ae200135742a00460406ae84d5d1280111931901399ab9c02a029025135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460206ae84d5d1280111931900c99ab9c01c01b017101a132632018335738921035054350001a135573ca00226ea800448c88c008dd6000990009aa80d111999aab9f0012501c233501b30043574200460066ae8800805c8c8c8cccd5cd19b8735573aa004900011991091980080180118069aba150023005357426ae8940088c98c8054cd5ce00c00b80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180b1aba1500233500e015357426ae8940088c98c8068cd5ce00e80e00c09aab9e5001137540026ae854010ccd54025d728041aba150033232323333573466e1d400520042300b357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae7007c0780680640604d55cea80089baa00135742a00466a014eb8d5d09aba2500223263201633573803203002826ae8940044d5d1280089aab9e500113754002424446004008266aa002eb9d6889119118011bab00132001355016223233335573e0044a032466a03066442466002006004600c6aae754008c014d55cf280118021aba200301413574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900919ab9c01501401000f135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900819ab9c01301200e00d00c00b135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900619ab9c00f00e00a135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8028cd5ce00680600409baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c804ccd5ce00b00a80880800780700680600589aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401866ae7003c0380280244d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200933573801801600e00c26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401466ae7003403002001c0184d55cea80089baa0012323333573466e1d40052002200623333573466e1d40092000200623263200633573801201000800626aae74dd5000a4c24400424400224002920103505431003200135500322112225335001135003220012213335005220023004002333553007120010050040011122002122122330010040031123230010012233003300200200101" + ) + PlutusV2 + ) + ) + txFixture1 :: Transaction txFixture1 = Transaction - { body: TxBody - { inputs: Set.singleton txInputFixture1 + { body: TransactionBody + { inputs: [ txInputFixture1 ] , outputs: [ txOutputFixture1 ] - , fee: Coin $ BigInt.fromInt 177513 + , fee: Coin $ BigNum.fromInt 177513 , ttl: Nothing - , certs: Nothing - , withdrawals: Nothing - , update: Nothing + , certs: [] + , withdrawals: Map.empty , auxiliaryDataHash: Nothing , validityStartInterval: Nothing , mint: Nothing , referenceInputs: mempty , scriptDataHash: Nothing - , collateral: Nothing - , requiredSigners: Nothing + , collateral: [] + , requiredSigners: [] , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing + , votingProposals: [] + , votingProcedures: mempty + , currentTreasuryValue: Nothing + , donation: Nothing } , witnessSet: TransactionWitnessSet - { vkeys: Nothing - , nativeScripts: Nothing - , bootstraps: Nothing - , plutusScripts: Nothing - , plutusData: Nothing - , redeemers: Nothing + { vkeys: [] + , nativeScripts: [] + , bootstraps: [] + , plutusScripts: [] + , plutusData: [] + , redeemers: [] } , isValid: true - , auxiliaryData: Nothing + , auxiliaryData: mempty } -txFixture2 :: Transaction -txFixture2 = - Transaction - { body: TxBody - { inputs: Set.singleton txInputFixture1 - , outputs: [ txOutputFixture2 ] - , fee: Coin $ BigInt.fromInt 177513 - , ttl: Nothing - , certs: Nothing - , withdrawals: Nothing - , update: Nothing - , auxiliaryDataHash: Nothing - , validityStartInterval: Nothing - , mint: Nothing - , referenceInputs: mempty - , scriptDataHash: Nothing - , collateral: Nothing - , requiredSigners: Nothing - , networkId: Just MainnetId - , collateralReturn: Nothing - , totalCollateral: Nothing - } - , witnessSet: TransactionWitnessSet - { vkeys: Nothing - , nativeScripts: Nothing - , bootstraps: Nothing - , plutusScripts: Nothing - , plutusData: Nothing - , redeemers: Nothing - } - , isValid: true - , auxiliaryData: Nothing - } - -txFixture3 :: Transaction -txFixture3 = - Transaction - { body: TxBody - { inputs: Set.singleton txInputFixture1 - , outputs: - [ TransactionOutput - { address: keyHashBaseAddress - { stake: - "0f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f97546" - -- $ T.Bech32 "hbas_1xranhpfej50zdup5jy995dlj9juem9x36syld8wm465hz92acfp" - , payment: - "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" - } - , amount: Value (Coin $ BigInt.fromInt 2353402) mempty - , datum: NoOutputDatum - , scriptRef: Nothing - } - , TransactionOutput - { address: keyHashBaseAddress - { stake: - "0f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f97546" - -- $ T.Bech32 "hbas_1xranhpfej50zdup5jy995dlj9juem9x36syld8wm465hz92acfp" - , payment: - "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" - } - , amount: Value (Coin $ BigInt.fromInt 1000000) mempty - , datum: NoOutputDatum - , scriptRef: Nothing - } - ] - , fee: Coin $ BigInt.fromInt 177513 - , ttl: Nothing - , certs: Nothing - , withdrawals: Nothing - , update: Nothing - , referenceInputs: Set.singleton txInputFixture1 - , auxiliaryDataHash: Nothing - , validityStartInterval: Nothing - , mint: Nothing - , scriptDataHash: Nothing - , collateral: Nothing - , requiredSigners: Nothing - , networkId: Just MainnetId - , collateralReturn: Nothing - , totalCollateral: Nothing - } - , witnessSet: TransactionWitnessSet - { vkeys: Nothing - , nativeScripts: Nothing - , bootstraps: Nothing - , plutusScripts: Nothing - , plutusData: Nothing - , redeemers: Nothing - } - , isValid: true - , auxiliaryData: Nothing - } - -txFixture4 :: Transaction -txFixture4 = - Transaction - { body: TxBody - { inputs: Set.singleton txInputFixture1 - , outputs: - [ TransactionOutput - { address: keyHashBaseAddress - { stake: - "0f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f97546" - -- $ T.Bech32 "hbas_1xranhpfej50zdup5jy995dlj9juem9x36syld8wm465hz92acfp" - , payment: - "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" - } - , amount: Value (Coin $ BigInt.fromInt 2353402) mempty - , datum: OutputDatum $ wrap plutusDataFixture1 - , scriptRef: Just $ PlutusScriptRef plutusScriptFixture1 - } - , TransactionOutput - { address: keyHashBaseAddress - { stake: - "0f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f97546" - -- $ T.Bech32 "hbas_1xranhpfej50zdup5jy995dlj9juem9x36syld8wm465hz92acfp" - , payment: - "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" - } - , amount: Value (Coin $ BigInt.fromInt 1000000) mempty - , datum: NoOutputDatum - , scriptRef: Just $ NativeScriptRef nativeScriptFixture5 - } - ] - , fee: Coin $ BigInt.fromInt 177513 - , ttl: Just $ Slot $ BigNum.fromInt 123 - , certs: Just - [ StakeRegistration stake1 - , StakeDeregistration stake1 - , StakeDelegation stake1 - (PoolPubKeyHash $ PubKeyHash ed25519KeyHash1) - , PoolRegistration - { operator: PoolPubKeyHash $ PubKeyHash ed25519KeyHash1 - , vrfKeyhash: unsafePartial $ fromJust $ - hexToByteArray - "fbf6d41985670b9041c5bf362b5262cf34add5d265975de176d613ca05f37096" - >>= vrfKeyHashFromBytes - , pledge: bigNumOne - , cost: bigNumOne - , margin: { numerator: bigNumOne, denominator: bigNumOne } - , rewardAccount: RewardAddress $ rewardAddress - { network: MainnetId, paymentCred: stake1 } - , poolOwners: [ wrap $ wrap ed25519KeyHash1 ] - , relays: - [ SingleHostAddr - { port: Just 8080 - , ipv4: Just $ Ipv4 $ byteArrayFromIntArrayUnsafe - [ 127, 0, 0, 1 ] - , ipv6: Just $ Ipv6 $ byteArrayFromIntArrayUnsafe - $ Array.replicate 16 123 - } - , SingleHostName - { port: Just 8080 - , dnsName: "example.com" - } - , MultiHostName { dnsName: "example.com" } - ] - , poolMetadata: Just $ PoolMetadata - { url: URL "https://example.com/" - , hash: PoolMetadataHash $ - hexToByteArrayUnsafe - "94b8cac47761c1140c57a48d56ab15d27a842abff041b3798b8618fa84641f5a" - } - } - , PoolRetirement - { poolKeyHash: PoolPubKeyHash $ PubKeyHash ed25519KeyHash1 - , epoch: Epoch one - } - , GenesisKeyDelegation - { genesisHash: GenesisHash $ - hexToByteArrayUnsafe - "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" - , genesisDelegateHash: GenesisDelegateHash $ - hexToByteArrayUnsafe - "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" - , vrfKeyhash: unsafePartial $ fromJust $ - hexToByteArray - "fbf6d41985670b9041c5bf362b5262cf34add5d265975de176d613ca05f37096" - >>= vrfKeyHashFromBytes - } - , MoveInstantaneousRewardsCert $ ToOtherPot - { pot: one - , amount: bigNumOne - } - , MoveInstantaneousRewardsCert $ ToStakeCreds - { pot: one - , amounts: MIRToStakeCredentials $ Map.fromFoldable - [ stake1 /\ Int.newPositive bigNumOne ] - } - ] - , withdrawals: Just $ Map.fromFoldable - [ rewardAddress1 /\ Coin one ] - , update: Just - { proposedProtocolParameterUpdates: - proposedProtocolParameterUpdates1 - , epoch: Epoch one - } - , auxiliaryDataHash: Just $ AuxiliaryDataHash - $ byteArrayFromIntArrayUnsafe - $ Array.replicate 32 0 - , validityStartInterval: Just $ Slot $ BigNum.fromInt 124 - , mint: Just $ Mint $ mkNonAdaAsset $ Map.fromFoldable - [ currencySymbol1 /\ Map.fromFoldable [ tokenName1 /\ one ] ] - , referenceInputs: mempty - , scriptDataHash: Nothing - , collateral: Nothing - , requiredSigners: Just [ RequiredSigner ed25519KeyHashFixture1 ] - , networkId: Just MainnetId - , collateralReturn: Just txOutputFixture1 - , totalCollateral: Just $ Coin $ BigInt.fromInt 5_000_000 - } - , witnessSet: TransactionWitnessSet - { vkeys: Nothing - , nativeScripts: Nothing - , bootstraps: Nothing - , plutusScripts: Nothing - , plutusData: Nothing - , redeemers: Nothing - } - , isValid: true - , auxiliaryData: Nothing - } +mint1 :: Mint +mint1 = Mint $ Map.fromFoldable + [ currencySymbol1 /\ Map.fromFoldable + [ tokenName2 /\ Int.newPositive BigNum.one + ] + ] -txFixture5 :: Transaction -txFixture5 = - Transaction - { body: TxBody - { inputs: Set.singleton txInputFixture1 - , outputs: - [ TransactionOutput - { address: keyHashBaseAddress - { stake: - "0f45aaf1b2959db6e5ff94dbb1f823bf257680c3c723ac2d49f97546" - -- $ T.Bech32 "hbas_1xranhpfej50zdup5jy995dlj9juem9x36syld8wm465hz92acfp" - , payment: - "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" - } - , amount: Value (Coin $ BigInt.fromInt 490234098) mempty - , datum: OutputDatum $ wrap plutusDataFixture1 - , scriptRef: Just $ PlutusScriptRef plutusScriptFixture2 - } - ] - , fee: Coin $ BigInt.fromInt 89489324 - , ttl: Nothing - , certs: Nothing - , withdrawals: Nothing - , update: Nothing - , auxiliaryDataHash: Nothing - , validityStartInterval: Nothing - , mint: Nothing - , referenceInputs: mempty - , scriptDataHash: Nothing - , collateral: Nothing - , requiredSigners: Nothing - , networkId: Just MainnetId - , collateralReturn: Nothing - , totalCollateral: Nothing - } - , witnessSet: TransactionWitnessSet - { vkeys: Nothing - , nativeScripts: Nothing - , bootstraps: Nothing - , plutusScripts: Nothing - , plutusData: Nothing - , redeemers: Nothing - } - , isValid: true - , auxiliaryData: Nothing - } +mint0 :: Mint +mint0 = Mint $ Map.fromFoldable + [ currencySymbol1 /\ Map.fromFoldable + [ tokenName2 /\ Int.newPositive BigNum.zero + ] + ] -txFixture6 :: Transaction -txFixture6 = - Transaction - { body: TxBody - { inputs: Set.singleton txInputFixture1 - , outputs: [ txOutputFixture1 ] - , fee: Coin $ BigInt.fromInt 177513 - , ttl: Nothing - , certs: Nothing - , withdrawals: Nothing - , update: Nothing - , auxiliaryDataHash: Nothing - , validityStartInterval: Nothing - , mint: Nothing - , referenceInputs: mempty - , scriptDataHash: Nothing - , collateral: Nothing - , requiredSigners: Nothing - , networkId: Just MainnetId - , collateralReturn: Nothing - , totalCollateral: Nothing - } - , witnessSet: TransactionWitnessSet - { vkeys: Nothing - , nativeScripts: Nothing - , bootstraps: Nothing - , plutusScripts: Nothing - , plutusData: Nothing - , redeemers: Nothing - } - , isValid: true - , auxiliaryData: Just $ AuxiliaryData - { metadata: Just $ GeneralTransactionMetadata - ( Map.fromFoldable - [ TransactionMetadatumLabel (BigInt.fromInt 8) /\ Text "foo" ] - ) - , nativeScripts: Nothing - , plutusScripts: Nothing - } - } +int1 :: Int.Int +int1 = Int.newPositive BigNum.one -- | To quickly check a serialized tx, create a file with the following contents: -- | @@ -885,7 +478,7 @@ utxoFixture1 = hexToByteArrayUnsafe input :: TransactionInput input = TransactionInput { index: UInt.fromInt 0 - , transactionId: TransactionHash + , transactionId: unsafePartial $ fromJust $ decodeCbor $ wrap ( byteArrayFromIntArrayUnsafe [ 198 , 181 @@ -926,10 +519,12 @@ input = TransactionInput output :: TransactionOutput output = ( TransactionOutput - { address: baseAddressToAddress $ baseAddress - { network: TestnetId - , paymentCred: keyHashCredential $ unsafePartial $ fromJust - $ ed25519KeyHashFromBytes + { address: BaseAddress + { networkId: TestnetId + , paymentCredential: wrap $ PubKeyHashCredential $ unsafePartial + $ fromJust + $ decodeCbor + $ wrap $ byteArrayFromIntArrayUnsafe [ 243 @@ -961,43 +556,44 @@ output = , 223 , 36 ] - , delegationCred: keyHashCredential $ unsafePartial $ fromJust - $ ed25519KeyHashFromBytes - $ - ( byteArrayFromIntArrayUnsafe - [ 57 - , 3 - , 16 - , 58 - , 231 - , 6 - , 129 - , 67 - , 155 - , 84 - , 118 - , 254 - , 245 - , 159 - , 67 - , 155 - , 139 - , 200 - , 109 - , 132 - , 191 - , 178 - , 211 - , 118 - , 252 - , 63 - , 86 - , 23 - ] - ) + , stakeCredential: wrap $ PubKeyHashCredential $ unsafePartial + $ fromJust + $ decodeCbor + $ wrap + ( byteArrayFromIntArrayUnsafe + [ 57 + , 3 + , 16 + , 58 + , 231 + , 6 + , 129 + , 67 + , 155 + , 84 + , 118 + , 254 + , 245 + , 159 + , 67 + , 155 + , 139 + , 200 + , 109 + , 132 + , 191 + , 178 + , 211 + , 118 + , 252 + , 63 + , 86 + , 23 + ] + ) } - , amount: Value (Coin (BigInt.fromInt 5000000)) mempty - , datum: NoOutputDatum + , amount: Value (Coin (BigNum.fromInt 5000000)) MultiAsset.empty + , datum: Nothing , scriptRef: Nothing } ) @@ -1094,24 +690,24 @@ witnessSetFixture2 = hexToByteArrayUnsafe witnessSetFixture2Value :: TransactionWitnessSet witnessSetFixture2Value = TransactionWitnessSet - { bootstraps: Nothing - , nativeScripts: Nothing - , plutusData: Nothing - , plutusScripts: Nothing - , redeemers: Nothing - , vkeys: Just + { bootstraps: [] + , nativeScripts: [] + , plutusData: [] + , plutusScripts: [] + , redeemers: [] + , vkeys: [ Vkeywitness - ( Vkey - ( unsafePartial $ fromJust $ mkPublicKey + { vkey: Vkey + ( unsafePartial $ fromJust $ PublicKey.fromBech32 "ed25519_pk1p9sf9wz3t46u9ghht44203gerxt82kzqaqw74fqrmwjmdy8sjxmqknzq8j" ) - /\ - ( unsafePartial $ fromJust <<< mkEd25519Signature $ - "ed25519_sig1mr6pm5kanam2wkmae70jx7fjkzepghefj0lmnczu6fra\ - \6auf2urgrte5axxhunw4x34l3l8tj9c0t4le39tj8lpjdgxmqnujw07t\ - \kzs9m6t6x" - ) - ) + , signature: + ( unsafePartial $ fromJust <<< Ed25519Signature.fromBech32 $ + "ed25519_sig1mr6pm5kanam2wkmae70jx7fjkzepghefj0lmnczu6fra\ + \6auf2urgrte5axxhunw4x34l3l8tj9c0t4le39tj8lpjdgxmqnujw07t\ + \kzs9m6t6x" + ) + } ] } @@ -1125,62 +721,61 @@ witnessSetFixture3 = hexToByteArrayUnsafe witnessSetFixture3Value :: TransactionWitnessSet witnessSetFixture3Value = TransactionWitnessSet - { bootstraps: Nothing - , nativeScripts: Nothing + { bootstraps: [] + , nativeScripts: [] , plutusData: - Just - [ PD.Bytes - ( byteArrayFromIntArrayUnsafe - [ 43 - , 184 - , 13 - , 83 - , 123 - , 29 - , 163 - , 227 - , 139 - , 211 - , 3 - , 97 - , 170 - , 133 - , 86 - , 134 - , 189 - , 224 - , 234 - , 205 - , 113 - , 98 - , 254 - , 246 - , 162 - , 95 - , 233 - , 123 - , 245 - , 39 - , 162 - , 91 - ] - ) - ] - , plutusScripts: Nothing - , redeemers: Nothing - , vkeys: Just + [ Bytes + ( byteArrayFromIntArrayUnsafe + [ 43 + , 184 + , 13 + , 83 + , 123 + , 29 + , 163 + , 227 + , 139 + , 211 + , 3 + , 97 + , 170 + , 133 + , 86 + , 134 + , 189 + , 224 + , 234 + , 205 + , 113 + , 98 + , 254 + , 246 + , 162 + , 95 + , 233 + , 123 + , 245 + , 39 + , 162 + , 91 + ] + ) + ] + , plutusScripts: [ plutusScriptFixture3 ] + , redeemers: [] + , vkeys: [ Vkeywitness - ( Vkey - ( unsafePartial $ fromJust $ mkPublicKey + { vkey: Vkey + ( unsafePartial $ fromJust $ PublicKey.fromBech32 "ed25519_pk1p9sf9wz3t46u9ghht44203gerxt82kzqaqw74fqrmwjmdy8sjxmqknzq8j" ) - /\ - ( unsafePartial $ fromJust <<< mkEd25519Signature $ - "ed25519_sig1clmhgxx9e9t24wzgkmcsr44uq98j935evsjnrj8nn7ge08\ - \qrz0mgdxv5qtz8dyghs47q3lxwk4akq3u2ty8v4egeqvtl02ll0nfcqqq\ - \6faxl6" - ) - ) + , signature: + ( unsafePartial $ fromJust <<< Ed25519Signature.fromBech32 $ + "ed25519_sig1clmhgxx9e9t24wzgkmcsr44uq98j935evsjnrj8nn7ge08\ + \qrz0mgdxv5qtz8dyghs47q3lxwk4akq3u2ty8v4egeqvtl02ll0nfcqqq\ + \6faxl6" + ) + } ] } @@ -1198,7 +793,7 @@ addressString1 = mkTxInput :: { txId :: String, ix :: Int } -> TransactionInput mkTxInput { txId, ix } = TransactionInput - { transactionId: TransactionHash $ + { transactionId: unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe txId , index: UInt.fromInt ix } @@ -1213,7 +808,8 @@ ed25519KeyHashFixture1 :: Ed25519KeyHash ed25519KeyHashFixture1 = -- $ Bech32 "hstk_1rsf0q0q77t5nttxrtmpwd7tvv58a80a686t92pgy65ekz0s8ncu" unsafePartial $ fromJust - $ ed25519KeyHashFromBytes + $ decodeCbor + $ wrap $ hexToByteArrayUnsafe "1c12f03c1ef2e935acc35ec2e6f96c650fd3bfba3e96550504d53361" @@ -1221,7 +817,8 @@ ed25519KeyHashFixture2 :: Ed25519KeyHash ed25519KeyHashFixture2 = -- "hbas_1xranhpfej50zdup5jy995dlj9juem9x36syld8wm465hz92acfp" unsafePartial $ fromJust - $ ed25519KeyHashFromBytes + $ decodeCbor + $ wrap $ hexToByteArrayUnsafe "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" @@ -1248,45 +845,47 @@ nativeScriptFixture7 :: NativeScript nativeScriptFixture7 = TimelockExpiry $ Slot $ BigNum.fromInt 2000 keyHashBaseAddress :: { payment :: String, stake :: String } -> Address -keyHashBaseAddress { payment, stake } = baseAddressToAddress $ baseAddress - { network: TestnetId - , delegationCred: - keyHashCredential $ unsafePartial $ fromJust $ ed25519KeyHashFromBytes +keyHashBaseAddress { payment, stake } = BaseAddress + { networkId: TestnetId + , stakeCredential: + wrap $ PubKeyHashCredential $ unsafePartial $ fromJust $ decodeCbor -- $ T.Bech32 "hstk_1rsf0q0q77t5nttxrtmpwd7tvv58a80a686t92pgy65ekz0s8ncu" + $ wrap $ hexToByteArrayUnsafe stake - , paymentCred: - keyHashCredential $ unsafePartial $ fromJust $ ed25519KeyHashFromBytes + , paymentCredential: + wrap $ PubKeyHashCredential $ unsafePartial $ fromJust $ decodeCbor -- "hbas_1xranhpfej50zdup5jy995dlj9juem9x36syld8wm465hz92acfp" + $ wrap $ hexToByteArrayUnsafe payment } -plutusDataFixture1 :: PD.PlutusData -plutusDataFixture1 = PD.List [] +plutusDataFixture1 :: PlutusData +plutusDataFixture1 = List [] -plutusDataFixture2 :: PD.PlutusData -plutusDataFixture2 = PD.List [ plutusDataFixture1 ] +plutusDataFixture2 :: PlutusData +plutusDataFixture2 = List [ plutusDataFixture1 ] -plutusDataFixture3 :: PD.PlutusData -plutusDataFixture3 = PD.Bytes +plutusDataFixture3 :: PlutusData +plutusDataFixture3 = Bytes ( hexToByteArrayUnsafe "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" ) -plutusDataFixture4 :: PD.PlutusData -plutusDataFixture4 = PD.Constr BigNum.one +plutusDataFixture4 :: PlutusData +plutusDataFixture4 = Constr BigNum.one [ plutusDataFixture2, plutusDataFixture3 ] -plutusDataFixture5 :: PD.PlutusData -plutusDataFixture5 = PD.Integer (BigInt.fromInt 42) +plutusDataFixture5 :: PlutusData +plutusDataFixture5 = Integer (BigInt.fromInt 42) -plutusDataFixture6 :: PD.PlutusData -plutusDataFixture6 = PD.Map +plutusDataFixture6 :: PlutusData +plutusDataFixture6 = Map [ plutusDataFixture1 /\ plutusDataFixture2 , plutusDataFixture3 /\ plutusDataFixture4 ] -plutusDataFixture7 :: PD.PlutusData -plutusDataFixture7 = PD.List +plutusDataFixture7 :: PlutusData +plutusDataFixture7 = List [ plutusDataFixture1 , plutusDataFixture2 , plutusDataFixture3 @@ -1295,23 +894,23 @@ plutusDataFixture7 = PD.List , plutusDataFixture6 ] -plutusDataFixture8 :: PD.PlutusData -plutusDataFixture8 = PD.Constr BigNum.zero - [ PD.Bytes +plutusDataFixture8 :: PlutusData +plutusDataFixture8 = Constr BigNum.zero + [ Bytes ( hexToByteArrayUnsafe "da13ed22b9294f1d86bbd530e99b1456884c7364bf16c90edc1ae41e" ) - , PD.Integer (BigInt.fromInt 500000000) - , PD.Bytes + , Integer (BigInt.fromInt 500000000) + , Bytes ( hexToByteArrayUnsafe "82325cbfc20b85bd1ca12e5d12b44b83f68662d8395167b45f1ff7fa" ) - , PD.Bytes (hexToByteArrayUnsafe "746f6e6573206f6620736b7920") - , PD.Bytes + , Bytes (hexToByteArrayUnsafe "746f6e6573206f6620736b7920") + , Bytes ( hexToByteArrayUnsafe "da13ed22b9294f1d86bbd530e99b1456884c7364bf16c90edc1ae41e" ) - , PD.Integer (BigInt.fromInt 45) + , Integer (BigInt.fromInt 45) ] plutusDataFixture8Bytes :: ByteArray @@ -1328,122 +927,12 @@ plutusDataFixture8Bytes' = hexToByteArrayUnsafe \206f6620736b7920581cda13ed22b9294f1d86bbd530e99b1456884c7364bf16c90edc1ae41e\ \182d" -scriptHashFromString :: String -> ScriptHash -scriptHashFromString s = unsafePartial $ fromJust $ scriptHashFromBytes $ - hexToByteArrayUnsafe s - -scriptHash1 :: ScriptHash -scriptHash1 = scriptHashFromString - "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" - -scriptHash4 :: ScriptHash -scriptHash4 = scriptHashFromString - "1e4409ba69fb38887c23d15a766476384085b66a755530934938abfe" - -policyId :: MintingPolicyHash -policyId = MintingPolicyHash scriptHash1 - -policyId4 :: MintingPolicyHash -policyId4 = MintingPolicyHash scriptHash4 - -cip25MetadataFilesFixture1 :: Array Cip25MetadataFile -cip25MetadataFilesFixture1 = Cip25MetadataFile <$> - [ { name: unsafeMkCip25String "file_name_1" - , mediaType: unsafeMkCip25String "media_type" - , src: "uri1" - } - , { name: unsafeMkCip25String "file_name_2" - , mediaType: unsafeMkCip25String "media_type_2" - , src: "uri4" - } - ] - -cip25MetadataEntryFixture1 :: Cip25MetadataEntry -cip25MetadataEntryFixture1 = Cip25MetadataEntry - { policyId: policyId - , assetName: Cip25TokenName tokenName1 - , name: unsafeMkCip25String "ItestToken" - , image: "image_uri1" - , mediaType: Just $ unsafeMkCip25String "media_type" - , description: Just "desc1" - , files: cip25MetadataFilesFixture1 - } - -cip25MetadataEntryFixture2 :: Cip25MetadataEntry -cip25MetadataEntryFixture2 = Cip25MetadataEntry - { policyId: policyId - , assetName: Cip25TokenName tokenName2 - , name: unsafeMkCip25String "TestToken2" - , image: "image_uri1" - , mediaType: Nothing - , description: Nothing - , files: [] - } - -cip25MetadataFixture1 :: Cip25Metadata -cip25MetadataFixture1 = Cip25Metadata - [ cip25MetadataEntryFixture1, cip25MetadataEntryFixture2 ] - -cip25MetadataFixture2 :: Cip25Metadata -cip25MetadataFixture2 = Cip25Metadata - [ Cip25MetadataEntry - { policyId: policyId - , assetName: Cip25TokenName tokenName1 - , name: unsafeMkCip25String "ItestToken" - , image: "image_uri1" - , mediaType: Nothing - , description: Nothing - , files: [] - } - ] - -cip25MetadataFixture3 :: Cip25Metadata -cip25MetadataFixture3 = Cip25Metadata - [ Cip25MetadataEntry - { policyId: policyId - , assetName: Cip25TokenName tokenName1 - , name: unsafeMkCip25String "monkey.jpg" - , image: - -- checking long strings - "https://upload.wikimedia.org/wikipedia/commons/3/35/Olive_baboon_Ngorongoro.jpg?download" - , mediaType: Nothing - , description: Nothing - , files: [] - } - ] - -cip25MetadataFixture4 :: Cip25Metadata -cip25MetadataFixture4 = Cip25Metadata - [ Cip25MetadataEntry - { policyId: policyId4 - , assetName: Cip25TokenName tokenName4 - , name: unsafeMkCip25String "Allium" - , image: "ipfs://k2cwuee3arxg398hwxx6c0iferxitu126xntuzg8t765oo020h5y6npn" - , mediaType: Nothing - , description: Just "From pixabay" - , files: [] - } - ] - -unsafeMkCip25String :: String -> Cip25String -unsafeMkCip25String str = unsafePartial $ fromJust $ mkCip25String str - readJsonFixtureFile :: String -> Effect Aeson readJsonFixtureFile path = readTextFile UTF8 path >>= pure <<< fromRight aesonNull <<< parseJsonStringToAeson -cip25MetadataJsonFixture1 :: Effect Aeson -cip25MetadataJsonFixture1 = - readJsonFixtureFile "test/Fixtures/cip25MetadataJsonFixture1.json" - -cip25MetadataJsonFixture2 :: Effect Aeson -cip25MetadataJsonFixture2 = - readJsonFixtureFile "test/Fixtures/cip25MetadataJsonFixture2.json" - -cip25MetadataJsonFixture3 :: Effect Aeson -cip25MetadataJsonFixture3 = - readJsonFixtureFile "test/Fixtures/cip25MetadataJsonFixture3.json" +-- TODO: remove CIP25 fixtures below ogmiosEvaluateTxValidRespFixture :: Effect Aeson ogmiosEvaluateTxValidRespFixture = @@ -1467,43 +956,43 @@ ogmiosEvaluateTxFailScriptErrorsFixture = redeemerFixture1 :: Redeemer redeemerFixture1 = Redeemer { tag: Spend - , index: BigInt.fromInt 0 - , data: plutusDataFixture7 - , exUnits: - { mem: BigInt.fromInt 1 - , steps: BigInt.fromInt 1 + , index: BigNum.fromInt 0 + , data: wrap plutusDataFixture7 + , exUnits: ExUnits + { mem: BigNum.fromInt 1 + , steps: BigNum.fromInt 1 } } -unappliedScriptFixture :: Validator +unappliedScriptFixture :: PlutusScript unappliedScriptFixture = - wrap $ plutusV1Script $ hexToByteArrayUnsafe $ + plutusV1Script $ wrap $ hexToByteArrayUnsafe $ "586f010000333222323233222233222225335300c33225335300e0021001100f333500b223\ \33573466e1c00800404003c0152002333500b22333573466e3c00800404003c01122010010\ \091326353008009498cd4015d680119a802bae001120012001120011200112200212200120\ \0101" -partiallyAppliedScriptFixture :: Validator +partiallyAppliedScriptFixture :: PlutusScript partiallyAppliedScriptFixture = - wrap $ plutusV1Script $ hexToByteArrayUnsafe $ + plutusV1Script $ wrap $ hexToByteArrayUnsafe $ "58750100003333222323233222233222225335300c33225335300e0021001100f333500b22\ \333573466e1c00800404003c0152002333500b22333573466e3c00800404003c0112210010\ \091326353008009498cd4015d680119a802bae001120012001120011200112200212200120\ \014c010218200001" -fullyAppliedScriptFixture :: Validator +fullyAppliedScriptFixture :: PlutusScript fullyAppliedScriptFixture = - wrap $ plutusV1Script $ hexToByteArrayUnsafe $ + plutusV1Script $ wrap $ hexToByteArrayUnsafe $ "587f01000033333222323233222233222225335300c33225335300e0021001100f333500b2\ \2333573466e1c00800404003c0152002333500b22333573466e3c00800404003c011220100\ \10091326353008009498cd4015d680119a802bae0011200120011200112001122002122001\ \20014c01021820004c010544746573740001" nullPaymentPubKeyHash :: PaymentPubKeyHash -nullPaymentPubKeyHash = PaymentPubKeyHash $ PubKeyHash +nullPaymentPubKeyHash = PaymentPubKeyHash $ unsafePartial $ fromJust - $ fromBytes - $ CborBytes + $ decodeCbor + $ wrap $ hexToByteArrayUnsafe "f9dca21a6c826ec8acb4cf395cbc24351937bfe6560b2683ab8b415f" diff --git a/test/Fixtures/CostModels.js b/test/Fixtures/CostModels.js new file mode 100644 index 0000000000..63dfcffabf --- /dev/null +++ b/test/Fixtures/CostModels.js @@ -0,0 +1,5 @@ +import * as CSL from "@mlabs-haskell/cardano-serialization-lib-gc"; + +export function defaultCostmdls() { + return CSL.TxBuilderConstants.plutus_vasil_cost_models(); +} diff --git a/test/Fixtures/CostModels.purs b/test/Fixtures/CostModels.purs index 9c4ddc4c91..543b5bc36a 100644 --- a/test/Fixtures/CostModels.purs +++ b/test/Fixtures/CostModels.purs @@ -4,14 +4,17 @@ module Test.Ctl.Fixtures.CostModels import Prelude -import Control.Monad.Error.Class (liftEither) -import Ctl.Internal.Cardano.Types.Transaction (Costmdls) -import Ctl.Internal.Deserialization.Error (toError) -import Ctl.Internal.Deserialization.Transaction (convertCostModels) -import Ctl.Internal.Serialization (defaultCostmdls) -import Data.Bifunctor (lmap) +import Cardano.Serialization.Lib (Costmdls, unpackMapContainerToMapWith) +import Cardano.Types (CostModel, Language) +import Cardano.Types.CostModel as CostModel +import Cardano.Types.Language as Language +import Data.Map (Map) +import Effect (Effect) import Effect.Unsafe (unsafePerformEffect) -costModelsFixture1 :: Costmdls -costModelsFixture1 = unsafePerformEffect - (defaultCostmdls >>= convertCostModels >>> lmap toError >>> liftEither) +foreign import defaultCostmdls :: Effect Costmdls + +costModelsFixture1 :: Map Language CostModel +costModelsFixture1 = unsafePerformEffect do + defaultCostmdls <#> unpackMapContainerToMapWith Language.fromCsl + CostModel.fromCsl diff --git a/test/Fixtures/OgmiosEvaluateTxFailScriptErrorsFixture.json b/test/Fixtures/OgmiosEvaluateTxFailScriptErrorsFixture.json index ead071bbe6..5b29765649 100644 --- a/test/Fixtures/OgmiosEvaluateTxFailScriptErrorsFixture.json +++ b/test/Fixtures/OgmiosEvaluateTxFailScriptErrorsFixture.json @@ -1 +1,64 @@ -{"jsonrpc":"2.0","method":"evaluateTransaction","error":{"code":3010,"message":"Some scripts of the transactions terminated with error(s).","data":[{"validator":"certificate:11","error":{"code":3117,"message":"The transaction contains unknown UTxO references as inputs. This can happen if the inputs you're trying to spend have already been spent, or if you've simply referred to non-existing UTxO altogether. The field 'data.unknownOutputReferences' indicates all unknown inputs.","data":{"unknownOutputReferences":[{"transaction":{"id":"731392618255aff0cd24712e6bd234db958cc065f8eff4f5e4476d4825cda180"},"index":1}]}}},{"validator":"certificate:15","error":{"code":3011,"message":"An associated script witness is missing. Indeed, any script used in a transaction (when spending, minting, withdrawing or publishing certificates) must be provided in full with the transaction. Scripts must therefore be added either to the witness set or provided as a reference inputs should you use Plutus V2+ and a format from Babbage and beyond.","data":{"missingScripts":["mint:11"]}}},{"validator":"withdrawal:16","error":{"code":3111,"message":"Transaction failed because some Plutus scripts are missing their associated datums. 'data.missingDatums' contains a set of data hashes for the missing datums. Ensure all Plutus scripts have an associated datum in the transaction's witness set or, are provided through inline datums in reference inputs.","data":{"missingDatums":["342ab6aef80f619bb09dfe2e8a24f8937734d4150d00cb1aa93222ce808c290f"]}}}]},"id":"mK9IYY6GandR"} +{ + "jsonrpc": "2.0", + "method": "evaluateTransaction", + "error": { + "code": 3010, + "message": "Some scripts of the transactions terminated with error(s).", + "data": [ + { + "validator": { + "index": 11, + "purpose": "publish" + }, + "error": { + "code": 3117, + "message": "The transaction contains unknown UTxO references as inputs. This can happen if the inputs you're trying to spend have already been spent, or if you've simply referred to non-existing UTxO altogether. The field 'data.unknownOutputReferences' indicates all unknown inputs.", + "data": { + "unknownOutputReferences": [ + { + "transaction": { + "id": "731392618255aff0cd24712e6bd234db958cc065f8eff4f5e4476d4825cda180" + }, + "index": 1 + } + ] + } + } + }, + { + "validator": { + "index": 11, + "purpose": "publish" + }, + "error": { + "code": 3011, + "message": "An associated script witness is missing. Indeed, any script used in a transaction (when spending, minting, withdrawing or publishing certificates) must be provided in full with the transaction. Scripts must therefore be added either to the witness set or provided as a reference inputs should you use Plutus V2+ and a format from Babbage and beyond.", + "data": { + "missingScripts": [ + { + "index": 11, + "purpose": "mint" + } + ] + } + } + }, + { + "validator": { + "index": 16, + "purpose": "withdraw" + }, + "error": { + "code": 3111, + "message": "Transaction failed because some Plutus scripts are missing their associated datums. 'data.missingDatums' contains a set of data hashes for the missing datums. Ensure all Plutus scripts have an associated datum in the transaction's witness set or, are provided through inline datums in reference inputs.", + "data": { + "missingDatums": [ + "342ab6aef80f619bb09dfe2e8a24f8937734d4150d00cb1aa93222ce808c290f" + ] + } + } + } + ] + }, + "id": "mK9IYY6GandR" +} diff --git a/test/Fixtures/OgmiosEvaluateTxInvalidPointerFormatFixture.json b/test/Fixtures/OgmiosEvaluateTxInvalidPointerFormatFixture.json index 57a1e35071..d4cfab2e66 100644 --- a/test/Fixtures/OgmiosEvaluateTxInvalidPointerFormatFixture.json +++ b/test/Fixtures/OgmiosEvaluateTxInvalidPointerFormatFixture.json @@ -3,21 +3,30 @@ "method": "evaluateTransaction", "result": [ { - "validator": "spend", + "validator": { + "index": 0, + "purpose": "invalid" + }, "budget": { "memory": 2766916028110716146, "cpu": 6325731070934221229 } }, { - "validator": "certificate:3", + "validator": { + "index": 3, + "purpose": "publish" + }, "budget": { "memory": 4926587050210136942, "cpu": 2982577810151428748 } }, { - "validator": "withdrawal:8", + "validator": { + "index": 8, + "purpose": "withdraw" + }, "budget": { "memory": 3603965291794951667, "cpu": 937555587227912939 diff --git a/test/Fixtures/OgmiosEvaluateTxValidRespFixture.json b/test/Fixtures/OgmiosEvaluateTxValidRespFixture.json index dd82d93adf..0b2782ecde 100644 --- a/test/Fixtures/OgmiosEvaluateTxValidRespFixture.json +++ b/test/Fixtures/OgmiosEvaluateTxValidRespFixture.json @@ -3,21 +3,30 @@ "method": "evaluateTransaction", "result": [ { - "validator": "spend:1", + "validator": { + "index": 1, + "purpose": "spend" + }, "budget": { "memory": 2766916028110716146, "cpu": 6325731070934221229 } }, { - "validator": "certificate:3", + "validator": { + "index": 3, + "purpose": "publish" + }, "budget": { "memory": 4926587050210136942, "cpu": 2982577810151428748 } }, { - "validator": "withdrawal:0", + "validator": { + "index": 0, + "purpose": "withdraw" + }, "budget": { "memory": 3603965291794951667, "cpu": 937555587227912939 diff --git a/test/Hashing.purs b/test/Hashing.purs index 11c92b5a28..db741fb1e6 100644 --- a/test/Hashing.purs +++ b/test/Hashing.purs @@ -2,31 +2,21 @@ module Test.Ctl.Hashing (suite) where import Prelude -import Ctl.Internal.Hashing - ( blake2b256Hash - , blake2b256HashHex - , datumHash - , plutusScriptHash - , sha256Hash - , sha256HashHex - , sha3_256Hash - , sha3_256HashHex - ) as Hashing -import Ctl.Internal.Serialization.Hash (ScriptHash, scriptHashFromBytes) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.ByteArray - ( ByteArray - , byteArrayFromAscii - , hexToByteArrayUnsafe - ) -import Ctl.Internal.Types.PlutusData (PlutusData(Integer)) -import Ctl.Internal.Types.Scripts (PlutusScript, plutusV1Script, plutusV2Script) -import Ctl.Internal.Types.Transaction (DataHash) +import Cardano.AsCbor (decodeCbor) +import Cardano.Types (ScriptHash) +import Cardano.Types.DataHash (DataHash) +import Cardano.Types.PlutusData (PlutusData(Integer)) +import Cardano.Types.PlutusScript (plutusV1Script, plutusV2Script) +import Cardano.Types.PlutusScript as PlutusScript +import Contract.Hashing (datumHash) as Hashing +import Contract.Scripts (PlutusScript) +import Data.ByteArray (hexToByteArrayUnsafe) import Data.Maybe (fromJust) import Data.Newtype (wrap) import Effect.Aff (Aff) import JS.BigInt (fromInt) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Test.Ctl.Fixtures (plutusDataFixture7) import Test.Spec.Assertions (shouldEqual) @@ -34,95 +24,56 @@ import Test.Spec.Assertions (shouldEqual) suite :: TestPlanM (Aff Unit) Unit suite = group "Hashing" do - test "blake2b256 hash of an arbitrary byte array" do - Hashing.blake2b256Hash inputDataFixture - `shouldEqual` (hexToByteArrayUnsafe blake2b256HexDigestFixture) - - test "blake2b256 hash of an arbitrary byte array as a hex string" do - Hashing.blake2b256HashHex inputDataFixture - `shouldEqual` blake2b256HexDigestFixture test "blake2b224 hash of a PlutusV1 script" do - Hashing.plutusScriptHash plutusV1ScriptFixture + PlutusScript.hash plutusV1ScriptFixture `shouldEqual` plutusV1ScriptHashFixture test "blake2b224 hash of a PlutusV2 script" do - Hashing.plutusScriptHash plutusV2ScriptFixture + PlutusScript.hash plutusV2ScriptFixture `shouldEqual` plutusV2ScriptHashFixture test "blake2b256 hash of Plutus data" do - Hashing.datumHash (wrap plutusDataFixture7) + Hashing.datumHash plutusDataFixture7 `shouldEqual` datumHashFixture test "blake2b256 hash of Plutus data - Integer 0 (regression to \ \https://github.com/Plutonomicon/cardano-transaction-lib/issues/488 ?)" do - Hashing.datumHash (wrap $ Integer (fromInt 0)) + Hashing.datumHash (Integer (fromInt 0)) `shouldEqual` zeroIntDatumHashFixture - test "sha256 hash of an arbitrary byte array" do - Hashing.sha256Hash inputDataFixture - `shouldEqual` (hexToByteArrayUnsafe sha256HexDigestFixture) - - test "sha256 hash of an arbitrary byte array as a hex string" do - Hashing.sha256HashHex inputDataFixture - `shouldEqual` sha256HexDigestFixture - - test "sha3_256 hash of an arbitrary byte array" do - Hashing.sha3_256Hash inputDataFixture - `shouldEqual` (hexToByteArrayUnsafe sha3_256HexDigestFixture) - - test "sha3_256 hash of an arbitrary byte array as a hex string" do - Hashing.sha3_256HashHex inputDataFixture - `shouldEqual` sha3_256HexDigestFixture - -inputDataFixture :: ByteArray -inputDataFixture = - unsafePartial $ fromJust $ byteArrayFromAscii "some message" - -blake2b256HexDigestFixture :: String -blake2b256HexDigestFixture = - "e04294b4b3a1b6e031af82eca8847d2c7be14f588fe326b78a7cc5060da35480" - -sha256HexDigestFixture :: String -sha256HexDigestFixture = - "c47757abe4020b9168d0776f6c91617f9290e790ac2f6ce2bd6787c74ad88199" - -sha3_256HexDigestFixture :: String -sha3_256HexDigestFixture = - "832978c1119fe706ddfe32de31f1986ba3654198b3b7656b050e2ab3b1fe3de3" - -- Checked that it corresponds to blake2b256(\00) ie. Integer 0 zeroIntDatumHashFixture :: DataHash zeroIntDatumHashFixture = - wrap $ + unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314" datumHashFixture :: DataHash datumHashFixture = - wrap $ + unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "0ba47e574456db8938e56f889d4c30099256f96008e0d4b6c4688f47ec342c9d" plutusV1ScriptFixture :: PlutusScript plutusV1ScriptFixture = - plutusV1Script $ + plutusV1Script $ wrap $ hexToByteArrayUnsafe "4d01000033222220051200120011" plutusV1ScriptHashFixture :: ScriptHash plutusV1ScriptHashFixture = - unsafePartial $ fromJust $ scriptHashFromBytes $ + unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656" plutusV2ScriptFixture :: PlutusScript plutusV2ScriptFixture = - plutusV2Script + plutusV2Script $ wrap $ hexToByteArrayUnsafe "4d01000033222220051200120011" plutusV2ScriptHashFixture :: ScriptHash plutusV2ScriptHashFixture = - unsafePartial $ fromJust $ scriptHashFromBytes $ + unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "793f8c8cffba081b2a56462fc219cc8fe652d6a338b62c7b134876e7" diff --git a/test/Integration.purs b/test/Integration.purs index 697b2fa5a7..3984de7c37 100644 --- a/test/Integration.purs +++ b/test/Integration.purs @@ -2,7 +2,8 @@ module Test.Ctl.Integration (main, testPlan, stakingSuite) where import Prelude -import Contract.Address (Ed25519KeyHash, StakePubKeyHash(StakePubKeyHash)) +import Cardano.AsCbor (decodeCbor) +import Contract.Address (Ed25519KeyHash) import Contract.Backend.Ogmios (getPoolParameters) import Contract.Config (testnetConfig) import Contract.Monad (runContract) @@ -13,7 +14,6 @@ import Contract.Test.Mote (TestPlanM, interpretWithConfig) import Contract.Test.Utils (exitCode, interruptOnSignal) import Contract.Time (getEraSummaries, getSystemStart) import Ctl.Internal.Contract.Monad (wrapQueryM) -import Ctl.Internal.Serialization.Hash (ed25519KeyHashFromBytes) import Data.Maybe (Maybe(Just, Nothing), fromJust) import Data.Newtype (wrap) import Data.Posix.Signal (Signal(SIGINT)) @@ -77,15 +77,13 @@ stakingSuite = do void $ getPoolIds test "getPubKeyHashDelegationsAndRewards #1" do noWallet do - res <- getPubKeyHashDelegationsAndRewards $ StakePubKeyHash $ wrap - ed25519KeyHash1 + res <- getPubKeyHashDelegationsAndRewards ed25519KeyHash1 res `shouldEqual` Nothing test "getPubKeyHashDelegationsAndRewards #2" do noWallet do - void $ getPubKeyHashDelegationsAndRewards $ StakePubKeyHash $ wrap - ed25519KeyHash2 + void $ getPubKeyHashDelegationsAndRewards ed25519KeyHash2 ed25519KeyHash2 :: Ed25519KeyHash -ed25519KeyHash2 = unsafePartial $ fromJust $ ed25519KeyHashFromBytes $ +ed25519KeyHash2 = unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "541d6a23b07ebe1363671f49c833f6c33176ec968de1482fdf15cc1f" diff --git a/test/Logging.purs b/test/Logging.purs index 247d3143e0..7bbab86074 100644 --- a/test/Logging.purs +++ b/test/Logging.purs @@ -5,7 +5,6 @@ import Prelude import Contract.Config (testnetConfig) import Contract.Log (logWarn') import Contract.Monad (runContract) -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Data.Log.Level (LogLevel(Error)) import Data.Maybe (Maybe(Just)) import Effect.Aff (Aff, try) @@ -13,6 +12,7 @@ import Effect.Class (liftEffect) import Effect.Exception (throw) import Effect.Ref as Ref import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.Spec.Assertions (shouldEqual) suite :: TestPlanM (Aff Unit) Unit diff --git a/test/Metadata/Cip25.purs b/test/Metadata/Cip25.purs deleted file mode 100644 index 8bcea4953c..0000000000 --- a/test/Metadata/Cip25.purs +++ /dev/null @@ -1,119 +0,0 @@ -module Test.Ctl.Metadata.Cip25 (suite) where - -import Prelude - -import Aeson (decodeAeson) -import Ctl.Internal.FromData (fromData) -import Ctl.Internal.Metadata.Cip25.Cip25String - ( fromDataString - , fromMetadataString - , toCip25Strings - , toDataString - , toMetadataString - ) -import Ctl.Internal.Metadata.MetadataType - ( fromGeneralTxMetadata - , toGeneralTxMetadata - ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.ToData (toData) -import Data.Either (Either(Right), hush) -import Data.Maybe (Maybe(Just)) -import Data.TextDecoder (decodeUtf8) -import Data.TextEncoder (encodeUtf8) -import Effect.Aff (Aff) -import Effect.Class (liftEffect) -import Mote (group, test) -import Test.Ctl.Fixtures - ( cip25MetadataFixture1 - , cip25MetadataFixture2 - , cip25MetadataFixture3 - , cip25MetadataFixture4 - , cip25MetadataJsonFixture1 - , cip25MetadataJsonFixture2 - , unsafeMkCip25String - ) -import Test.QuickCheck ((===)) -import Test.QuickCheck.Combinators ((==>)) -import Test.Spec.Assertions (shouldEqual) -import Test.Spec.QuickCheck (quickCheck) - -suite :: TestPlanM (Aff Unit) Unit -suite = do - group "CIP25 Metadata" do - test "Long string ToData encoding" do - -- decodeUtf8 is not an inverse of encodeUtf8 - quickCheck $ \str -> do - (hush (decodeUtf8 (encodeUtf8 str)) === Just str) ==> - (fromDataString (toDataString str) === Just str) - test "Long string ToMetadata encoding" do - -- decodeUtf8 is not an inverse of encodeUtf8 - quickCheck $ \str -> do - (hush (decodeUtf8 (encodeUtf8 str)) === Just str) ==> - (fromMetadataString (toMetadataString str) === Just str) - test "toCip25Strings #1" do - toCip25Strings "asd" `shouldEqual` [ unsafeMkCip25String "asd" ] - test "toCip25Strings #2" do - toCip25Strings str80Chars - `shouldEqual` - [ unsafeMkCip25String - "0123456789012345678901234567890123456789012345678901234567890123" - , unsafeMkCip25String "4567890123456789" - ] - test "toCip25Strings #3" do - toCip25Strings str160Chars - `shouldEqual` - [ unsafeMkCip25String - "0123456789012345678901234567890123456789012345678901234567890123" - , unsafeMkCip25String - "4567890123456789012345678901234567890123456789012345678901234567" - , unsafeMkCip25String "89012345678901234567890123456789" - ] - test "toCip25Strings #4" do - toCip25Strings - "0123456789012345678901234567890123456789012345678901234567890123" - `shouldEqual` - [ unsafeMkCip25String - "0123456789012345678901234567890123456789012345678901234567890123" - ] - test "MetadataType instance #1" do - fromGeneralTxMetadata (toGeneralTxMetadata cip25MetadataFixture1) - `shouldEqual` Just cip25MetadataFixture1 - test "MetadataType instance #2" do - fromGeneralTxMetadata (toGeneralTxMetadata cip25MetadataFixture2) - `shouldEqual` Just cip25MetadataFixture2 - test "MetadataType instance #3" do - fromGeneralTxMetadata (toGeneralTxMetadata cip25MetadataFixture3) - `shouldEqual` Just cip25MetadataFixture3 - test "MetadataType instance #4" do - fromGeneralTxMetadata (toGeneralTxMetadata cip25MetadataFixture4) - `shouldEqual` Just cip25MetadataFixture4 - test "FromData / ToData instances #1" do - fromData (toData cip25MetadataFixture1) `shouldEqual` - Just cip25MetadataFixture1 - test "FromData / ToData instances #2" do - fromData (toData cip25MetadataFixture2) `shouldEqual` - Just cip25MetadataFixture2 - test "FromData / ToData instances #3" do - fromData (toData cip25MetadataFixture3) `shouldEqual` - Just cip25MetadataFixture3 - test "FromData / ToData instances #4" do - fromData (toData cip25MetadataFixture4) `shouldEqual` - Just cip25MetadataFixture4 - test "DecodeJson instance #1" do - jsonFixture <- liftEffect cip25MetadataJsonFixture1 - decodeAeson jsonFixture `shouldEqual` - Right cip25MetadataFixture1 - test "DecodeJson instance #2" do - jsonFixture <- liftEffect cip25MetadataJsonFixture2 - decodeAeson jsonFixture `shouldEqual` - Right cip25MetadataFixture2 - -str40Chars :: String -str40Chars = "0123456789012345678901234567890123456789" - -str80Chars :: String -str80Chars = str40Chars <> str40Chars - -str160Chars :: String -str160Chars = str80Chars <> str80Chars diff --git a/test/MustSpendTotal.purs b/test/MustSpendTotal.purs deleted file mode 100644 index 4de25b9b48..0000000000 --- a/test/MustSpendTotal.purs +++ /dev/null @@ -1,60 +0,0 @@ -module Test.Ctl.MustSpendTotal - ( main - , suite - ) where - -import Prelude hiding (join) - -import Contract.TxConstraints - ( TxConstraints - , mustProduceAtLeast - , mustProduceAtLeastTotal - , mustSpendAtLeast - , mustSpendAtLeastTotal - ) -import Contract.Value as Value -import Ctl.Internal.Test.TestPlanM (TestPlanM, interpret) -import Data.Lattice (join) -import Effect (Effect) -import Effect.Aff (Aff, launchAff_) -import Mote (group, test) -import Test.QuickCheck (Result, (), (===)) -import Test.Spec.QuickCheck (quickCheck) - --- Run with `spago test --main Test.Ctl.MustSpendTotal` -main :: Effect Unit -main = launchAff_ do - interpret suite - -suite :: TestPlanM (Aff Unit) Unit -suite = do - group "mustXAtLeastTotal works correctly" do - test "mustSpendAtLeastTotal is roundtrip to mustSpendAtLeast" $ do - quickCheck $ prop_roundtrip mustSpendAtLeast mustSpendAtLeastTotal - test "mustSpendAtLeastTotal is homomorphism" do - quickCheck $ - prop_roundtripOverMonoid mustSpendAtLeast mustSpendAtLeastTotal - test "mustProduceAtLeastTotal is roundtrip to mustProduceAtLeast" $ do - quickCheck $ prop_roundtrip mustProduceAtLeast mustProduceAtLeastTotal - test "mustProduceAtLeastTotal is homomorphism" do - quickCheck $ - prop_roundtripOverMonoid mustProduceAtLeast mustProduceAtLeastTotal - --- Properties - -prop_roundtripOverMonoid - :: (Value.Value -> TxConstraints) - -> (TxConstraints -> Value.Value) - -> Value.Value - -> Value.Value - -> Result -prop_roundtripOverMonoid must total x y = - (x `join` y) == total (must x <> must y) - "On value 1 " <> show x <> " and value 2 " <> show y - -prop_roundtrip - :: (Value.Value -> TxConstraints) - -> (TxConstraints -> Value.Value) - -> Value.Value - -> Result -prop_roundtrip must total x = (must >>> total) x === x diff --git a/test/NativeScript.purs b/test/NativeScript.purs index 29b90adf79..6788312813 100644 --- a/test/NativeScript.purs +++ b/test/NativeScript.purs @@ -3,23 +3,22 @@ module Test.Ctl.NativeScript (suite) where import Prelude import Aeson (decodeAeson, encodeAeson) -import Ctl.Internal.Cardano.Types.NativeScript +import Cardano.AsCbor (decodeCbor) +import Cardano.Types (Ed25519KeyHash) +import Cardano.Types.Ed25519KeyHash as Ed25519KeyHash +import Cardano.Types.NativeScript ( NativeScript(ScriptPubkey, ScriptAll, ScriptAny, ScriptNOfK) ) import Ctl.Internal.NativeScripts (getMaximumSigners) -import Ctl.Internal.Serialization.Hash - ( Ed25519KeyHash - , ed25519KeyHashFromBech32 - , ed25519KeyHashFromBytes - ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.ByteArray (hexToByteArrayUnsafe) +import Data.ByteArray (hexToByteArrayUnsafe) import Data.Either (Either(Right)) import Data.Maybe (fromJust) +import Data.Newtype (wrap) import Data.Set as Set import Effect.Aff (Aff) import Effect.Class (liftEffect) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Test.QuickCheck (quickCheck, (===)) import Test.Spec.Assertions (shouldEqual) @@ -222,26 +221,26 @@ suite = do decodeAeson (encodeAeson script) === Right script pk1 :: Ed25519KeyHash -pk1 = unsafePartial $ fromJust $ ed25519KeyHashFromBytes $ +pk1 = unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "1c12f03c1ef2e935acc35ec2e6f96c650fd3bfba3e96550504d53361" pk2 :: Ed25519KeyHash -pk2 = unsafePartial $ fromJust $ ed25519KeyHashFromBytes $ +pk2 = unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" pk3 :: Ed25519KeyHash pk3 = unsafePartial $ fromJust do - ed25519KeyHashFromBech32 + Ed25519KeyHash.fromBech32 "addr_vkh1zuctrdcq6ctd29242w8g84nlz0q38t2lnv3zzfcrfqktx0c9tzp" pk4 :: Ed25519KeyHash -pk4 = unsafePartial $ fromJust $ ed25519KeyHashFromBytes $ +pk4 = unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "30fb3b8529951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" pk5 :: Ed25519KeyHash -pk5 = unsafePartial $ fromJust $ ed25519KeyHashFromBytes $ +pk5 = unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe "30fb3b8529951e26f034919a5a37f22cb99d94d1d409f69ddbaea971" diff --git a/test/Ogmios/Address.purs b/test/Ogmios/Address.purs deleted file mode 100644 index 1708f24b00..0000000000 --- a/test/Ogmios/Address.purs +++ /dev/null @@ -1,35 +0,0 @@ -module Test.Ctl.Ogmios.Address (suite) where - -import Prelude - -import Control.Monad.Except (throwError) -import Ctl.Internal.Address (addressToOgmiosAddress, ogmiosAddressToAddress) -import Ctl.Internal.QueryM.Ogmios (OgmiosAddress) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Data.Maybe (Maybe(Just, Nothing)) -import Effect.Aff (Aff, error) -import Mote (group, test) -import Test.Spec.Assertions (shouldEqual) - -testnetAddrFixture1 :: OgmiosAddress -testnetAddrFixture1 = - "addr_test1qr7g8nrv76fc7k4ueqwecljxx9jfwvsgawhl55hck3n8uwaz26mpcwu58zdkhpdnc6nuq3fa8vylc8ak9qvns7r2dsysp7ll4d" - -addrFixture1 :: OgmiosAddress -addrFixture1 = - "addr1qyc0kwu98x23ufhsxjgs5k3h7gktn8v5682qna5amwh2juguztcrc8hjay66es67ctn0jmr9plfmlw37je2s2px4xdssgvxerq" - -suite :: TestPlanM (Aff Unit) Unit -suite = do - -- Test inverse in one direction. - group "Address loop" do - test "Ogmios Address to Address & back Testnet" - $ testFromOgmiosAddress testnetAddrFixture1 - test "Ogmios Address to Address & back non-Testnet" - $ testFromOgmiosAddress addrFixture1 - -testFromOgmiosAddress :: OgmiosAddress -> Aff Unit -testFromOgmiosAddress testAddr = do - case ogmiosAddressToAddress testAddr of - Nothing -> throwError $ error "Failed Address loop" - Just addr -> addressToOgmiosAddress addr `shouldEqual` testAddr diff --git a/test/Ogmios/Aeson.purs b/test/Ogmios/Aeson.purs index 783e027e4a..b60492e4a9 100644 --- a/test/Ogmios/Aeson.purs +++ b/test/Ogmios/Aeson.purs @@ -23,14 +23,13 @@ import Ctl.Internal.QueryM.Ogmios , aesonObject ) import Ctl.Internal.QueryM.Ogmios as O -import Ctl.Internal.Test.TestPlanM (TestPlanM, interpret) import Data.Array (catMaybes, groupAllBy, nubBy) import Data.Array.NonEmpty (NonEmptyArray, head, length, tail) import Data.Bifunctor (lmap) import Data.Either (Either(Left, Right), hush) import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing), maybe) -import Data.String (toLower) +import Data.String (null, toLower) as String import Data.String.Regex (match, regex) import Data.String.Regex.Flags (noFlags) import Data.Traversable (for_) @@ -41,6 +40,7 @@ import Effect.Class (liftEffect) import Effect.Exception (throw) import Foreign.Object (update) as Object import Mote (group, skip, test) +import Mote.TestPlanM (TestPlanM, interpret) import Node.Encoding (Encoding(UTF8)) import Node.FS.Aff (readTextFile, readdir) import Node.Path (FilePath, basename, concat) @@ -127,16 +127,19 @@ loadFixtures = do catMaybes <$> flip parTraverse (ourFixtures <> ogmiosFixtures) \fp -> do let bn = basename fp contents <- readTextFile UTF8 fp - aeson <- liftEither $ lmap - (error <<< ((bn <> "\n ") <> _) <<< printJsonDecodeError) - (Aeson.parseJsonStringToAeson contents) - pure case pattern >>= flip match bn >>> map tail of - Just [ Just query ] -> Just - { query - , bn - , aeson - } - _ -> Nothing + -- ignore empty (corrupted) fixtures + if String.null contents then pure Nothing + else do + aeson <- liftEither $ lmap + (error <<< ((bn <> "\n ") <> _) <<< printJsonDecodeError) + (Aeson.parseJsonStringToAeson contents) + pure case pattern >>= flip match bn >>> map tail of + Just [ Just query ] -> Just + { query + , bn + , aeson + } + _ -> Nothing let groupedFiles = @@ -151,12 +154,12 @@ suite = group "Ogmios Aeson tests" do groupedFiles <- lift loadFixtures let (tested' :: Map.Map String Check) = Map.fromFoldable $ map - (\(q /\ c) -> (toLower q /\ c)) + (\(q /\ c) -> (String.toLower q /\ c)) tested for_ groupedFiles \(query /\ files') -> let - query' = toLower query + query' = String.toLower query in let test' ch = test (query <> " (" <> show (length files') <> ")") $ for_ diff --git a/test/Ogmios/EvaluateTx.purs b/test/Ogmios/EvaluateTx.purs index 3047dc4d9c..e7040703f7 100644 --- a/test/Ogmios/EvaluateTx.purs +++ b/test/Ogmios/EvaluateTx.purs @@ -3,7 +3,9 @@ module Test.Ctl.Ogmios.EvaluateTx (suite) where import Prelude import Aeson (JsonDecodeError(TypeMismatch)) -import Contract.Numeric.Natural (Natural, fromBigInt') +import Cardano.Types (BigNum) +import Cardano.Types.BigNum as BigNum +import Cardano.Types.RedeemerTag (RedeemerTag(Spend, Cert, Reward)) import Ctl.Internal.QueryM.JsonRpc2 ( OgmiosDecodeError(ResultDecodingError) , decodeOgmios @@ -15,16 +17,14 @@ import Ctl.Internal.QueryM.Ogmios , TxEvaluationR(TxEvaluationR) , TxEvaluationResult(TxEvaluationResult) ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.RedeemerTag (RedeemerTag(Spend, Cert, Reward)) import Data.Either (Either(Left, Right)) import Data.Map as Map import Data.Maybe (fromJust) import Data.Tuple.Nested (type (/\), (/\)) import Effect.Aff (Aff) import Effect.Class (liftEffect) -import JS.BigInt as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Test.Ctl.Fixtures ( ogmiosEvaluateTxFailIncompatibleEraFixture @@ -73,23 +73,24 @@ suite = do _ -> false ogmiosEvaluateTxValidRespDecoded :: Array (RedeemerPointer /\ ExecutionUnits) -ogmiosEvaluateTxValidRespDecoded = Map.toUnfoldable $ Map.fromFoldable - [ { redeemerTag: Cert, redeemerIndex: one + one + one } - /\ - { memory: naturalLiteral "4926587050210136942" - , steps: naturalLiteral "2982577810151428748" - } - , { redeemerTag: Spend, redeemerIndex: one } - /\ - { memory: naturalLiteral "2766916028110716146" - , steps: naturalLiteral "6325731070934221229" - } - , { redeemerTag: Reward, redeemerIndex: zero } - /\ - { memory: naturalLiteral "3603965291794951667" - , steps: naturalLiteral "937555587227912939" - } - ] +ogmiosEvaluateTxValidRespDecoded = unsafePartial $ Map.toUnfoldable $ + Map.fromFoldable + [ { redeemerTag: Cert, redeemerIndex: one + one + one } + /\ + { memory: naturalLiteral "4926587050210136942" + , steps: naturalLiteral "2982577810151428748" + } + , { redeemerTag: Spend, redeemerIndex: one } + /\ + { memory: naturalLiteral "2766916028110716146" + , steps: naturalLiteral "6325731070934221229" + } + , { redeemerTag: Reward, redeemerIndex: zero } + /\ + { memory: naturalLiteral "3603965291794951667" + , steps: naturalLiteral "937555587227912939" + } + ] -naturalLiteral :: String -> Natural -naturalLiteral x = fromBigInt' $ unsafePartial $ fromJust $ BigInt.fromString x +naturalLiteral :: Partial => String -> BigNum +naturalLiteral x = fromJust $ BigNum.fromString x diff --git a/test/Ogmios/GenerateFixtures.purs b/test/Ogmios/GenerateFixtures.purs index d8c001f3c4..f1ae3eca67 100644 --- a/test/Ogmios/GenerateFixtures.purs +++ b/test/Ogmios/GenerateFixtures.purs @@ -6,7 +6,6 @@ import Prelude import Aeson (class EncodeAeson, Aeson, encodeAeson, stringifyAeson) import Control.Parallel (parTraverse) -import Ctl.Internal.Hashing (md5HashHex) import Ctl.Internal.Helpers (logString) import Ctl.Internal.JsWebSocket ( _mkWebSocket @@ -45,6 +44,7 @@ import Effect.Ref as Ref import Node.Encoding (Encoding(UTF8)) import Node.FS.Aff (writeTextFile) import Node.Path (concat) +import Test.Ctl.Internal.Hashing (md5HashHex) -- A simple websocket for testing mkWebSocket @@ -127,7 +127,6 @@ main = , mkQuery' "queryLedgerState/protocolParameters" , mkQuery' "queryLedgerState/stakePools" ] - resps <- flip parTraverse queries \(Query qc method args) -> do resp <- mkRequestAff listeners ws (\_ _ -> pure unit) qc identity args pure { resp, method } diff --git a/test/Partition.purs b/test/Partition.purs index b636be4003..f263cf30c1 100644 --- a/test/Partition.purs +++ b/test/Partition.purs @@ -8,7 +8,6 @@ import Ctl.Internal.Partition , equipartition , partition ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Data.Array (elem) as Array import Data.Array.NonEmpty (NonEmptyArray, (:)) import Data.Array.NonEmpty (length, singleton, sort, zip) as NEArray @@ -22,6 +21,7 @@ import Effect.Aff (Aff) import JS.BigInt (BigInt) import JS.BigInt (fromInt) as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.QuickCheck.Arbitrary (class Arbitrary, arbitrary) import Test.QuickCheck.Gen (suchThat) import Test.Spec.QuickCheck (quickCheck, quickCheck') diff --git a/test/Plutip/Common.purs b/test/Plutip/Common.purs deleted file mode 100644 index 267dc89a78..0000000000 --- a/test/Plutip/Common.purs +++ /dev/null @@ -1,23 +0,0 @@ -module Test.Ctl.Plutip.Common - ( config - , privateStakeKey - ) where - -import Prelude - -import Contract.Test.Plutip (defaultPlutipConfig) -import Contract.Wallet (privateKeyFromBytes) -import Ctl.Internal.Plutip.Types (PlutipConfig) -import Ctl.Internal.Types.RawBytes (hexToRawBytes) -import Ctl.Internal.Wallet.Key (PrivateStakeKey) -import Data.Maybe (fromJust) -import Data.Newtype (wrap) -import Partial.Unsafe (unsafePartial) - -config :: PlutipConfig -config = defaultPlutipConfig - -privateStakeKey :: PrivateStakeKey -privateStakeKey = wrap $ unsafePartial $ fromJust - $ privateKeyFromBytes =<< hexToRawBytes - "633b1c4c4a075a538d37e062c1ed0706d3f0a94b013708e8f5ab0a0ca1df163d" diff --git a/test/Plutip/Contract/NetworkId.purs b/test/Plutip/Contract/NetworkId.purs deleted file mode 100644 index 1a08d09fa4..0000000000 --- a/test/Plutip/Contract/NetworkId.purs +++ /dev/null @@ -1,26 +0,0 @@ -module Test.Ctl.Plutip.Contract.NetworkId - ( suite - ) where - -import Prelude - -import Contract.Address (addressFromBech32) as Address -import Contract.Test (ContractTest) -import Contract.Test.Mote (TestPlanM) -import Contract.Test.Plutip (noWallet) -import Ctl.Internal.Plutus.Conversion.Address (fromPlutusAddress) -import Ctl.Internal.Serialization.Address (NetworkId(MainnetId), addressBech32) -import Mote (group, test) -import Test.Spec.Assertions (shouldEqual) - -suite :: TestPlanM ContractTest Unit -suite = group "NetworkId Tests" $ do - test "Mainnet Address in Mainnet Env" testMainnetAddress - -testMainnetAddress :: ContractTest -testMainnetAddress = noWallet do - let - bechstr = - "addr1qyc0kwu98x23ufhsxjgs5k3h7gktn8v5682qna5amwh2juguztcrc8hjay66es67ctn0jmr9plfmlw37je2s2px4xdssgvxerq" - addr <- Address.addressFromBech32 bechstr - addressBech32 (fromPlutusAddress MainnetId addr) `shouldEqual` bechstr diff --git a/test/Plutip/Staking.purs b/test/Plutip/Staking.purs deleted file mode 100644 index 8674bcf210..0000000000 --- a/test/Plutip/Staking.purs +++ /dev/null @@ -1,712 +0,0 @@ -module Test.Ctl.Plutip.Staking - ( main - , suite - ) where - -import Prelude - -import Contract.Address - ( PaymentPubKeyHash(PaymentPubKeyHash) - , getNetworkId - ) -import Contract.Backend.Ogmios (getPoolParameters) -import Contract.Credential (Credential(ScriptCredential)) -import Contract.Hashing (plutusScriptStakeValidatorHash, publicKeyHash) -import Contract.Log (logInfo') -import Contract.Monad (Contract, liftedM) -import Contract.Numeric.BigNum as BigNum -import Contract.PlutusData (unitDatum, unitRedeemer) -import Contract.Prelude (liftM) -import Contract.Prim.ByteArray (hexToByteArray) -import Contract.RewardAddress (stakePubKeyHashRewardAddress) -import Contract.ScriptLookups as Lookups -import Contract.Scripts - ( NativeScript(ScriptPubkey, ScriptAny) - , NativeScriptHash(NativeScriptHash) - , NativeScriptStakeValidator(NativeScriptStakeValidator) - , PlutusScriptStakeValidator(PlutusScriptStakeValidator) - , ValidatorHash(ValidatorHash) - , nativeScriptStakeValidatorHash - ) -import Contract.Staking - ( getPoolIds - , getPubKeyHashDelegationsAndRewards - , getValidatorHashDelegationsAndRewards - ) -import Contract.Test.Mote (TestPlanM, interpretWithConfig) -import Contract.Test.Plutip (runPlutipContract, withStakeKey) -import Contract.Test.Utils (exitCode, interruptOnSignal) -import Contract.Time (getCurrentEpoch) -import Contract.Transaction - ( Epoch(Epoch) - , PoolPubKeyHash(PoolPubKeyHash) - , balanceTx - , mkPoolPubKeyHash - , signTransaction - , vrfKeyHashFromBytes - ) -import Contract.TxConstraints - ( DatumPresence(DatumWitness) - , mustDelegateStakeNativeScript - , mustDelegateStakePlutusScript - , mustDelegateStakePubKey - , mustDeregisterStakeNativeScript - , mustDeregisterStakePlutusScript - , mustDeregisterStakePubKey - , mustPayToNativeScriptAddress - , mustPayToScriptAddress - , mustRegisterPool - , mustRegisterStakePubKey - , mustRegisterStakeScript - , mustRetirePool - , mustWithdrawStakeNativeScript - , mustWithdrawStakePlutusScript - , mustWithdrawStakePubKey - ) -import Contract.UnbalancedTx (mkUnbalancedTx) -import Contract.Value (lovelaceValueOf) -import Contract.Wallet - ( ownPaymentPubKeyHashes - , ownStakePubKeyHashes - , withKeyWallet - ) -import Contract.Wallet.Key (keyWalletPrivateStakeKey, publicKeyFromPrivateKey) -import Ctl.Examples.AlwaysSucceeds (alwaysSucceedsScript) -import Ctl.Examples.IncludeDatum (only42Script) -import Data.Array (head, (!!)) -import Data.Array as Array -import Data.Foldable (for_) -import Data.Maybe (Maybe(Just, Nothing), fromJust) -import Data.Newtype (unwrap) -import Data.Posix.Signal (Signal(SIGINT)) -import Data.Time.Duration (Seconds(Seconds)) -import Data.Tuple (Tuple(Tuple)) -import Data.Tuple.Nested ((/\)) -import Data.UInt as UInt -import Effect (Effect) -import Effect.Aff - ( Aff - , Milliseconds(Milliseconds) - , cancelWith - , delay - , effectCanceler - , launchAff - ) -import Effect.Aff.Class (liftAff) -import Effect.Class (liftEffect) -import Effect.Exception (error) -import JS.BigInt as BigInt -import Mote (group, skip, test) -import Partial.Unsafe (unsafePartial) -import Test.Ctl.Plutip.Common (config) as Common -import Test.Ctl.Plutip.Common (privateStakeKey) -import Test.Ctl.Plutip.Utils (submitAndLog) -import Test.Spec.Assertions (shouldEqual, shouldSatisfy) -import Test.Spec.Runner (defaultConfig) - -main :: Effect Unit -main = interruptOnSignal SIGINT =<< launchAff do - flip cancelWith (effectCanceler (exitCode 1)) do - interpretWithConfig - defaultConfig { timeout = Just $ Milliseconds 450_000.0, exit = true } - suite - -suite :: TestPlanM (Aff Unit) Unit -suite = do - -- We must never select this pool, because it retires at the third epoch - -- (this is Plutip internal knowledge) - -- https://github.com/mlabs-haskell/plutip/blob/7f2d59abd911dd11310404863cdedb2886902ebf/src/Test/Plutip/Internal/Cluster.hs#L692 - retiringPoolId <- liftEffect $ liftM (error "unable to decode poolId bech32") - $ mkPoolPubKeyHash - "pool1rv7ur8r2hz02lly9q8ehtwcrcydl3m2arqmndvwcqsfavgaemt6" - let - -- A routine function that filters out retiring pool from the list of available - -- pools - selectPoolId :: Contract PoolPubKeyHash - selectPoolId = do - pools <- getPoolIds - logInfo' "Pool IDs:" - logInfo' $ show pools - for_ pools \poolId -> do - logInfo' "Pool parameters" - logInfo' <<< show =<< getPoolParameters poolId - liftM (error "unable to get any pools") - (Array.filter (_ /= retiringPoolId) pools !! 1) - group "Staking" do - group "Stake keys: register & deregister" do - test "PubKey" do - let - distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 2_000_000_000 - ] - runPlutipContract config distribution $ flip withKeyWallet do - alicePkh /\ aliceStakePkh <- do - Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> - liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) - - -- Register - do - let - constraints = mustRegisterStakePubKey aliceStakePkh - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Deregister stake key - do - let - constraints = mustDeregisterStakePubKey aliceStakePkh - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - test "PlutusScript" do - let - distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 2_000_000_000 - ] - runPlutipContract config distribution $ flip withKeyWallet do - alicePkh /\ aliceStakePkh <- do - Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> - liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) - validator1 <- alwaysSucceedsScript <#> unwrap >>> - PlutusScriptStakeValidator - validator2 <- only42Script <#> unwrap >>> - PlutusScriptStakeValidator - let - validatorHash1 = plutusScriptStakeValidatorHash validator1 - validatorHash2 = plutusScriptStakeValidatorHash validator2 - - -- Register - do - let - constraints = mustRegisterStakeScript validatorHash1 - <> mustRegisterStakeScript validatorHash2 - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Deregister stake key - do - let - constraints = - mustDeregisterStakePlutusScript validator1 - unitRedeemer - <> mustDeregisterStakePlutusScript validator2 - unitRedeemer - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - test "NativeScript" do - let - distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 2_000_000_000 - ] - runPlutipContract config distribution $ flip withKeyWallet do - alicePkh /\ aliceStakePkh <- do - Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> - liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) - let - nativeScript = ScriptAny - [ ScriptPubkey $ unwrap $ unwrap alicePkh ] - validator = NativeScriptStakeValidator nativeScript - stakeValidatorHash = - nativeScriptStakeValidatorHash validator - - -- Register - do - let - constraints = mustRegisterStakeScript stakeValidatorHash - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Deregister stake key - do - let - constraints = mustDeregisterStakeNativeScript validator - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - test "Pool registration & retirement" do - let - distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 2_000_000_000 - ] - runPlutipContract config distribution \alice -> withKeyWallet alice do - alicePkh /\ aliceStakePkh <- Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) - - -- Register stake key - do - let - constraints = mustRegisterStakePubKey aliceStakePkh - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - privateStakeKey <- liftM (error "Failed to get private stake key") $ - keyWalletPrivateStakeKey alice - networkId <- getNetworkId - let - poolOperator = PoolPubKeyHash $ publicKeyHash $ - publicKeyFromPrivateKey (unwrap privateStakeKey) - - -- Register pool - do - vrfKeyHash <- liftM (error "Unable to decode VRFKeyHash") do - hexToByteArray - "fbf6d41985670b9041c5bf362b5262cf34add5d265975de176d613ca05f37096" - >>= vrfKeyHashFromBytes - let - rewardAccount = stakePubKeyHashRewardAddress networkId aliceStakePkh - - poolParams = - { operator: poolOperator - , vrfKeyhash: vrfKeyHash -- needed to prove that the pool won the lottery - , pledge: unsafePartial $ fromJust $ BigNum.fromBigInt $ - BigInt.fromInt 1 - , cost: unsafePartial $ fromJust $ BigNum.fromBigInt $ - BigInt.fromInt 1 - , margin: - { numerator: unsafePartial $ fromJust $ BigNum.fromBigInt $ - BigInt.fromInt 1 - , denominator: unsafePartial $ fromJust $ BigNum.fromBigInt $ - BigInt.fromInt 1 - } - , rewardAccount - , poolOwners: - [ PaymentPubKeyHash $ publicKeyHash $ - publicKeyFromPrivateKey - (unwrap privateStakeKey) - ] - , relays: [] - , poolMetadata: Nothing - } - - constraints = mustRegisterPool poolParams - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- List pools: the pool must appear in the list - do - pools <- getPoolIds - pools `shouldSatisfy` Array.elem poolOperator - - currentEpoch <- getCurrentEpoch - let - -- NOTE: this is a source of flaky-ness - -- (there's no guarantee that the tx will pass before the specified epoch). - -- You will get something like this error if it's not the case: - -- Error: `submit` call failed. Error from Ogmios: [{"wrongRetirementEpoch":{"currentEpoch":114,"firstUnreachableEpoch":1000114,"requestedEpoch":95}}] - retirementEpoch :: Epoch - retirementEpoch = Epoch (unwrap currentEpoch + UInt.fromInt 5) - - -- Retire pool - do - let - constraints = mustRetirePool poolOperator retirementEpoch - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - let - waitEpoch :: Epoch -> Contract Epoch - waitEpoch epoch = do - epochNow <- getCurrentEpoch - if unwrap epochNow >= unwrap epoch then pure epochNow - else do - liftAff $ delay $ Milliseconds 1000.0 - waitEpoch epoch - - void $ waitEpoch retirementEpoch - - -- List pools: the pool must not appear in the list - do - pools <- getPoolIds - pools `shouldSatisfy` Array.notElem poolOperator - - skip $ test - "Plutus Stake script: delegate to existing pool & withdraw rewards" - do - let - distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 1_000_000_000 * BigInt.fromInt 1_000 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 1_000 - ] - runPlutipContract config distribution \alice -> - withKeyWallet alice do - alicePkh /\ aliceStakePkh <- Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) - validator <- alwaysSucceedsScript <#> unwrap >>> - PlutusScriptStakeValidator - let - stakeValidatorHash = plutusScriptStakeValidatorHash validator - validatorHash = ValidatorHash $ unwrap stakeValidatorHash - - -- Lock funds on the stake script - do - let - constraints = - mustPayToScriptAddress validatorHash - (ScriptCredential validatorHash) - unitDatum - DatumWitness - $ lovelaceValueOf - $ BigInt.fromInt 1_000_000_000 * BigInt.fromInt 100 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Register stake script - do - let - constraints = - mustRegisterStakeScript stakeValidatorHash - - lookups :: Lookups.ScriptLookups - lookups = mempty - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Select a pool - poolId <- selectPoolId - - -- Delegate - do - let - constraints = - mustDelegateStakePlutusScript validator unitRedeemer poolId - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Wait until rewards - let - -- No need for limit on number of retries, because we have a - -- timeout for tests. - waitUntilRewards = do - mbDelegationsAndRewards <- - getValidatorHashDelegationsAndRewards stakeValidatorHash - case mbDelegationsAndRewards of - Just dels@{ rewards } | unwrap <$> rewards > Just zero -> - pure dels - _ -> do - liftAff $ delay $ Milliseconds 5000.0 - waitUntilRewards - - { rewards: rewardsBefore, delegate } <- waitUntilRewards - delegate `shouldEqual` Just poolId - - -- Withdraw - do - let - constraints = - mustWithdrawStakePlutusScript validator unitRedeemer - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Check rewards. - -- Not going to deregister here, because the rewards are added too - -- soon, and we can't deregister the stake key if there are rewards - -- left. - -- This will not happen in real life scenarios, because epoch are - -- (usually) significantly longer. - do - { rewards: rewardsAfter } <- liftedM "Unable to get rewards" $ - getValidatorHashDelegationsAndRewards stakeValidatorHash - rewardsAfter `shouldSatisfy` \after -> after < rewardsBefore - - skip $ test - "Native Stake script: delegate to existing pool & withdraw rewards" - do - let - distribution = - [ BigInt.fromInt 1_000_000_000 * BigInt.fromInt 1_000 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 1_000 - ] /\ - withStakeKey privateStakeKey - [ BigInt.fromInt 1_000_000_000 * BigInt.fromInt 1_000 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 1_000 - ] - runPlutipContract config distribution \(alice /\ bob) -> do - bobPkh /\ bobStakePkh <- withKeyWallet bob do - Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) - let - nativeScript = ScriptAny - [ ScriptPubkey $ unwrap $ unwrap bobStakePkh ] - validator = NativeScriptStakeValidator nativeScript - stakeValidatorHash = - nativeScriptStakeValidatorHash validator - - -- Alice - withKeyWallet alice do - -- She locks funds on the stake script (no need for her to validate - -- the script in order to do that) - do - let - constraints = - mustPayToNativeScriptAddress - (NativeScriptHash $ unwrap stakeValidatorHash) - ( ScriptCredential $ ValidatorHash $ unwrap - stakeValidatorHash - ) - $ lovelaceValueOf - $ BigInt.fromInt 1_000_000_000 * BigInt.fromInt 100 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Alice registers stake script (again, no need to validate it) - do - let - constraints = - mustRegisterStakeScript stakeValidatorHash - - lookups :: Lookups.ScriptLookups - lookups = mempty - - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Bob performs operations with the stake script that require his - -- (and only his) signature. - withKeyWallet bob do - - -- Select first pool - poolId <- selectPoolId - - -- Delegate - do - let - constraints = - mustDelegateStakeNativeScript validator poolId - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash bobPkh <> - Lookups.ownStakePubKeyHash bobStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Wait until rewards - let - -- No need for limit on number of retries, because we have a - -- timeout for tests. - waitUntilRewards = do - mbDelegationsAndRewards <- - getValidatorHashDelegationsAndRewards stakeValidatorHash - case mbDelegationsAndRewards of - Just dels@{ rewards } | unwrap <$> rewards > Just zero -> - pure dels - _ -> do - liftAff $ delay $ Milliseconds 5000.0 - waitUntilRewards - - { rewards: rewardsBefore, delegate } <- waitUntilRewards - delegate `shouldEqual` Just poolId - - -- Withdraw - do - let - constraints = - mustWithdrawStakeNativeScript validator - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash bobPkh <> - Lookups.ownStakePubKeyHash bobStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Check rewards. - -- Not going to deregister here, because the rewards are added too - -- soon, and we can't deregister the stake key if there are rewards - -- left. - -- This will not happen in real life scenarios, because epoch are - -- (usually) significantly longer. - do - { rewards: rewardsAfter } <- liftedM "Unable to get rewards" $ - getValidatorHashDelegationsAndRewards stakeValidatorHash - rewardsAfter `shouldSatisfy` \after -> after < rewardsBefore - - skip $ test "PubKey: delegate to existing pool & withdraw rewards" do - let - distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 1_000_000_000 * BigInt.fromInt 1_000 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 1_000 - ] - runPlutipContract config distribution \alice -> - withKeyWallet alice do - alicePkh /\ aliceStakePkh <- Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) - - -- Register stake key - do - let - constraints = mustRegisterStakePubKey aliceStakePkh - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Select a pool ID - poolId <- selectPoolId - - -- Delegate - do - let - constraints = - mustDelegateStakePubKey aliceStakePkh poolId - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Wait until rewards - let - -- No need for limit on number of retries, because we have a - -- timeout for tests. - waitUntilRewards = do - mbDelegationsAndRewards <- - getPubKeyHashDelegationsAndRewards aliceStakePkh - case mbDelegationsAndRewards of - Just dels@{ rewards } | unwrap <$> rewards > Just zero -> - pure dels - _ -> do - liftAff $ delay $ Milliseconds 5000.0 - waitUntilRewards - - { rewards: rewardsBefore, delegate: _ } <- waitUntilRewards - - -- TODO: why does the query layer return Nothing even though - -- the rewards are received? Potential Ogmios bug, need to investigate - -- delegate `shouldEqual` Just poolId - - -- Withdraw - do - let - constraints = - mustWithdrawStakePubKey aliceStakePkh - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog - - -- Check rewards. - -- Not going to deregister here, because the rewards are added too - -- soon, and we can't deregister the stake key if there are rewards - -- left. - -- This will not happen in real life scenarios, because epoch are - -- (usually) significantly longer. - do - { rewards: rewardsAfter } <- - liftedM "Unable to get rewards" - $ getPubKeyHashDelegationsAndRewards aliceStakePkh - rewardsAfter `shouldSatisfy` \after -> after < rewardsBefore - where - config = - Common.config - { clusterConfig = - Common.config.clusterConfig - -- changing these constants breaks rewards - -- https://github.com/mlabs-haskell/plutip/issues/149 - { slotLength = Seconds 0.05 - , epochSize = Just $ UInt.fromInt 80 - } - } diff --git a/test/Plutus/Conversion/Address.purs b/test/Plutus/Conversion/Address.purs deleted file mode 100644 index 7faf5e7650..0000000000 --- a/test/Plutus/Conversion/Address.purs +++ /dev/null @@ -1,192 +0,0 @@ -module Test.Ctl.Internal.Plutus.Conversion.Address (suite) where - -import Prelude - -import Contract.Numeric.BigNum (BigNum) -import Contract.Numeric.BigNum (fromInt) as BigNum -import Ctl.Internal.Plutus.Conversion (fromPlutusAddress, toPlutusAddress) -import Ctl.Internal.Plutus.Types.Address (Address) as Plutus -import Ctl.Internal.Plutus.Types.Credential - ( Credential(PubKeyCredential, ScriptCredential) - , StakingCredential(StakingHash, StakingPtr) - ) -import Ctl.Internal.Serialization.Address - ( NetworkId(MainnetId, TestnetId) - , addressFromBech32 - ) -import Ctl.Internal.Serialization.Hash - ( ed25519KeyHashFromBech32 - , scriptHashFromBech32 - ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.Aliases (Bech32String) -import Data.Array (length, range, zip) -import Data.Maybe (Maybe(Just, Nothing), fromJust) -import Data.Newtype (class Newtype, wrap) -import Data.Traversable (for_) -import Data.Tuple.Nested ((/\)) -import Effect.Aff (Aff) -import Mote (group, test) -import Partial.Unsafe (unsafePartial) -import Test.Ctl.Utils (errMaybe, toFromAesonTest) -import Test.Spec.Assertions (shouldEqual) - -suite :: TestPlanM (Aff Unit) Unit -suite = do - group "Conversion: Plutus Address <-> CSL Address" do - group "Shelley mainnet addresses" do - addressConversionTests MainnetId - group "Shelley testnet addresses" do - addressConversionTests TestnetId - group "Aeson tests" $ do - group "Roundtrip tests" - $ for_ addresses - $ toFromAesonTest "Address" - -addressConversionTests :: NetworkId -> TestPlanM (Aff Unit) Unit -addressConversionTests networkId = - let - addressesBech32 = - case networkId of - MainnetId -> addressesBech32Mainnet - TestnetId -> addressesBech32Testnet - indices = 0 `range` (length addresses - 1) - testData = zip (zip addressesBech32 addresses) indices - in - for_ testData $ \((addrBech32 /\ addr) /\ addrType) -> - toFromPlutusAddressTest networkId addrType addrBech32 addr - -toFromPlutusAddressTest - :: NetworkId - -> Int - -> Bech32String - -> Plutus.Address - -> TestPlanM (Aff Unit) Unit -toFromPlutusAddressTest networkId addrType addrBech32 addrPlutus = do - let testLabel = "Performs conversion between addresses of type " - test (testLabel <> show addrType) $ do - addrForeign <- - errMaybe "addressFromBech32 failed on valid bech32" $ - addressFromBech32 addrBech32 - resAddrPlutus <- - errMaybe "toPlutusAddress failed on valid foreign address" $ - toPlutusAddress addrForeign - resAddrPlutus `shouldEqual` addrPlutus - let resAddrForeign = fromPlutusAddress networkId resAddrPlutus - resAddrForeign `shouldEqual` addrForeign - --- Mainnet addresses. --- Test vectors are taken from the CIP-0019 specification. --- https://github.com/cardano-foundation/CIPs/tree/master/CIP-0019#test-vectors -addressesBech32Mainnet :: Array Bech32String -addressesBech32Mainnet = - [ "addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3n0d3vllmyqwsx5wktcd8" - <> "cc3sq835lu7drv2xwl2wywfgse35a3x" - - , "addr1z8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gten0d3vllmyqwsx5wktcd8" - <> "cc3sq835lu7drv2xwl2wywfgs9yc0hh" - - , "addr1yx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerkr0vd4msrxnuwnccdxlhd" - <> "jar77j6lg0wypcc9uar5d2shs2z78ve" - - , "addr1x8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gt7r0vd4msrxnuwnccdxlhd" - <> "jar77j6lg0wypcc9uar5d2shskhj42g" - - , "addr1gx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer5pnz75xxcrzqf96k" - - , "addr128phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtupnz75xxcrtw79hu" - - , "addr1vx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzers66hrl8" - - , "addr1w8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcyjy7wx" - ] - --- Testnet addresses. --- Test vectors are taken from the CIP-0019 specification. --- https://github.com/cardano-foundation/CIPs/tree/master/CIP-0019#test-vectors -addressesBech32Testnet :: Array Bech32String -addressesBech32Testnet = - [ "addr_test1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3n0d3vllmyqwsx5w" - <> "ktcd8cc3sq835lu7drv2xwl2wywfgs68faae" - - , "addr_test1zrphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gten0d3vllmyqwsx5w" - <> "ktcd8cc3sq835lu7drv2xwl2wywfgsxj90mg" - - , "addr_test1yz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerkr0vd4msrxnuwncc" - <> "dxlhdjar77j6lg0wypcc9uar5d2shsf5r8qx" - - , "addr_test1xrphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gt7r0vd4msrxnuwncc" - <> "dxlhdjar77j6lg0wypcc9uar5d2shs4p04xh" - - , "addr_test1gz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer5pnz75xxcrdw5vky" - - , "addr_test12rphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtupnz75xxcryqrvmw" - - , "addr_test1vz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerspjrlsz" - - , "addr_test1wrphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcl6szpr" - ] - -addresses :: Array Plutus.Address -addresses = wrap <$> - [ { addressCredential: pubKeyCredential - , addressStakingCredential: Just stakingHash - } - , { addressCredential: scriptCredential - , addressStakingCredential: Just stakingHash - } - , { addressCredential: pubKeyCredential - , addressStakingCredential: Just $ StakingHash scriptCredential - } - , { addressCredential: scriptCredential - , addressStakingCredential: Just $ StakingHash scriptCredential - } - , { addressCredential: pubKeyCredential - , addressStakingCredential: Just stakingPtr - } - , { addressCredential: scriptCredential - , addressStakingCredential: Just stakingPtr - } - , { addressCredential: pubKeyCredential - , addressStakingCredential: Nothing - } - , { addressCredential: scriptCredential - , addressStakingCredential: Nothing - } - ] - -paymentKeyBech32 :: Bech32String -paymentKeyBech32 = - "addr_vkh1jjfnzhxe966a33psfenm0ct2udkkr569qf55v4uprgkgu8zsvmg" - -pubKeyCredential :: Credential -pubKeyCredential = - PubKeyCredential <<< wrap <<< unsafePartial fromJust $ - ed25519KeyHashFromBech32 paymentKeyBech32 - -scriptBech32 :: Bech32String -scriptBech32 = - "script1cda3khwqv60360rp5m7akt50m6ttapacs8rqhn5w342z7r35m37" - -scriptCredential :: Credential -scriptCredential = - ScriptCredential <<< wrap <<< unsafePartial fromJust $ - scriptHashFromBech32 scriptBech32 - -stakeKeyBech32 :: Bech32String -stakeKeyBech32 = - "stake_vkh1xdak9nllvsp6q636e0p5lrzxqq7xnlne5d3gemafc3e9z3v4vud" - -stakingHash :: StakingCredential -stakingHash = - StakingHash <<< PubKeyCredential <<< wrap <<< unsafePartial fromJust $ - (ed25519KeyHashFromBech32 stakeKeyBech32) - -stakingPtr :: StakingCredential -stakingPtr = - let - wrapBn :: forall (t :: Type). Newtype t BigNum => Int -> t - wrapBn = wrap <<< BigNum.fromInt - in - StakingPtr - { slot: wrapBn 2498243, txIx: wrapBn 27, certIx: wrapBn 3 } diff --git a/test/Plutus/Conversion/Value.purs b/test/Plutus/Conversion/Value.purs deleted file mode 100644 index 36d8a44386..0000000000 --- a/test/Plutus/Conversion/Value.purs +++ /dev/null @@ -1,79 +0,0 @@ -module Test.Ctl.Internal.Plutus.Conversion.Value (suite) where - -import Prelude - -import Ctl.Internal.Cardano.Types.Value (Value) as Types -import Ctl.Internal.Cardano.Types.Value as Value -import Ctl.Internal.Plutus.Conversion (fromPlutusValue, toPlutusValue) -import Ctl.Internal.Plutus.Types.CurrencySymbol (CurrencySymbol) as Plutus -import Ctl.Internal.Plutus.Types.CurrencySymbol as Plutus.CurrencySymbol -import Ctl.Internal.Plutus.Types.Value (Value) as Plutus -import Ctl.Internal.Plutus.Types.Value as Plutus.Value -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Data.Array (length, range, zip) -import Data.Maybe (fromJust) -import Data.Traversable (for_) -import Data.Tuple (fst, snd) -import Data.Tuple.Nested (type (/\), (/\)) -import Effect.Aff (Aff) -import JS.BigInt (fromInt) -import Mote (group, test) -import Partial.Unsafe (unsafePartial) -import Test.Ctl.Fixtures (currencySymbol1, tokenName1, tokenName2) -import Test.Spec.Assertions (shouldEqual) - -suite :: TestPlanM (Aff Unit) Unit -suite = do - group "Conversion: Plutus Value <-> Types.Value" $ do - let indices = 0 `range` (length testData - 1) - for_ (zip testData indices) $ \((valuePlutus /\ value) /\ i) -> - toFromPlutusValueTest i valuePlutus value - -toFromPlutusValueTest - :: Int -> Plutus.Value -> Types.Value -> TestPlanM (Aff Unit) Unit -toFromPlutusValueTest i valuePlutus value = do - test (show i <> ": Performs conversion between `Value`s") $ do - let resValue = fromPlutusValue valuePlutus - resValue `shouldEqual` value - let resValuePlutus = toPlutusValue resValue - resValuePlutus `shouldEqual` valuePlutus - -testData :: Array (Plutus.Value /\ Types.Value) -testData = [ emptyValues, adaValues, nonAdaValues, compositeValues ] - where - amount1 /\ amount2 = fromInt 5000 /\ fromInt 6000 - - currencySymbol1' :: Plutus.CurrencySymbol - currencySymbol1' = unsafePartial $ fromJust $ - Plutus.CurrencySymbol.mkCurrencySymbol - (Value.getCurrencySymbol currencySymbol1) - - nonAdaAsset1 :: Value.NonAdaAsset - nonAdaAsset1 = - Value.mkSingletonNonAdaAsset currencySymbol1 tokenName1 amount1 - - nonAdaAsset2 :: Value.NonAdaAsset - nonAdaAsset2 = - Value.mkSingletonNonAdaAsset currencySymbol1 tokenName2 amount2 - - emptyValues :: Plutus.Value /\ Types.Value - emptyValues = mempty /\ mempty - - adaValues :: Plutus.Value /\ Types.Value - adaValues = - Plutus.Value.lovelaceValueOf amount1 /\ - Value.lovelaceValueOf amount1 - - nonAdaValues :: Plutus.Value /\ Types.Value - nonAdaValues = - Plutus.Value.singleton currencySymbol1' tokenName1 amount1 /\ - Value.mkValue mempty nonAdaAsset1 - - compositeValues :: Plutus.Value /\ Types.Value - compositeValues = - ( fst adaValues <> fst nonAdaValues <> - Plutus.Value.singleton currencySymbol1' tokenName2 amount2 - ) /\ - ( snd adaValues <> snd nonAdaValues <> - Value.mkValue mempty nonAdaAsset2 - ) diff --git a/test/Plutus/Credential.purs b/test/Plutus/Credential.purs index 2ab82efdb9..a1b30a860c 100644 --- a/test/Plutus/Credential.purs +++ b/test/Plutus/Credential.purs @@ -5,20 +5,17 @@ module Test.Ctl.Internal.Plutus.Credential import Prelude -import Ctl.Internal.Plutus.Types.Credential - ( Credential(ScriptCredential, PubKeyCredential) +import Cardano.Types (Bech32String) +import Cardano.Types.Credential + ( Credential(ScriptHashCredential, PubKeyHashCredential) ) -import Ctl.Internal.Serialization.Hash - ( ed25519KeyHashFromBech32 - , scriptHashFromBech32 - ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.Aliases (Bech32String) +import Cardano.Types.Ed25519KeyHash as Ed25519KeyHash +import Cardano.Types.ScriptHash as ScriptHash import Data.Maybe (fromJust) -import Data.Newtype (wrap) import Data.Traversable (for_) import Effect.Aff (Aff) import Mote (group) +import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Test.Ctl.Utils (toFromAesonTest) @@ -40,8 +37,8 @@ paymentKeyBech32 = pubKeyCredential :: Credential pubKeyCredential = - PubKeyCredential <<< wrap <<< unsafePartial fromJust $ - ed25519KeyHashFromBech32 paymentKeyBech32 + PubKeyHashCredential <<< unsafePartial fromJust $ + Ed25519KeyHash.fromBech32 paymentKeyBech32 scriptBech32 :: Bech32String scriptBech32 = @@ -49,5 +46,5 @@ scriptBech32 = scriptCredential :: Credential scriptCredential = - ScriptCredential <<< wrap <<< unsafePartial fromJust $ - scriptHashFromBech32 scriptBech32 + ScriptHashCredential <<< unsafePartial fromJust $ + ScriptHash.fromBech32 scriptBech32 diff --git a/test/Plutus/Time.purs b/test/Plutus/Time.purs index 41e92e977c..29bda59abc 100644 --- a/test/Plutus/Time.purs +++ b/test/Plutus/Time.purs @@ -4,14 +4,12 @@ module Test.Ctl.Internal.Plutus.Time import Prelude +import Cardano.Types (Epoch(Epoch), Slot(Slot)) +import Cardano.Types.BigNum as BigNum import Ctl.Internal.QueryM.Ogmios ( OgmiosEraSummaries(OgmiosEraSummaries) , OgmiosSystemStart ) -import Ctl.Internal.Serialization.Address (Slot(Slot)) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.BigNum as BigNum -import Ctl.Internal.Types.Epoch (Epoch(Epoch)) import Ctl.Internal.Types.EraSummaries ( EpochLength(EpochLength) , EraSummaries(EraSummaries) @@ -45,11 +43,13 @@ import Ctl.Internal.Types.Interval import Ctl.Internal.Types.SystemStart (sysStartFromOgmiosTimestampUnsafe) import Data.Int as Int import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (unwrap, wrap) +import Data.Newtype (wrap) +import Data.UInt as UInt import Effect.Aff (Aff) import JS.BigInt as BigInt import Mote (group) -import Test.Ctl.Utils (toFromAesonTest, toFromAesonTestWith) +import Mote.TestPlanM (TestPlanM) +import Test.Ctl.Utils (toFromAesonTest) slotFixture :: Slot slotFixture = mkSlot 34892625 @@ -79,7 +79,7 @@ relSlotFixture :: RelSlot relSlotFixture = RelSlot $ BigInt.fromInt 12855 currentEpochFixture :: Epoch -currentEpochFixture = Epoch $ BigInt.fromInt 58326646 +currentEpochFixture = Epoch $ UInt.fromInt 58326646 systemStartFixture :: OgmiosSystemStart systemStartFixture = @@ -95,7 +95,7 @@ mkSlot :: Int -> Slot mkSlot = Slot <<< BigNum.fromInt mkEpoch :: Int -> Epoch -mkEpoch = Epoch <<< BigInt.fromInt +mkEpoch = Epoch <<< UInt.fromInt mkEpochLength :: Int -> EpochLength mkEpochLength = EpochLength <<< BigInt.fromInt @@ -217,21 +217,6 @@ eraSummariesFixture = EraSummaries } ] -eraSummaryLengthToSeconds :: EraSummary -> EraSummary -eraSummaryLengthToSeconds old@(EraSummary { parameters }) = - let - newSlotLength :: SlotLength - newSlotLength = wrap $ 1e-3 * unwrap (unwrap parameters).slotLength - - newParameters :: EraSummaryParameters - newParameters = wrap $ (unwrap parameters) { slotLength = newSlotLength } - in - wrap (unwrap old) { parameters = newParameters } - -eraSummariesLengthToSeconds :: OgmiosEraSummaries -> OgmiosEraSummaries -eraSummariesLengthToSeconds (OgmiosEraSummaries values) = - wrap $ wrap (eraSummaryLengthToSeconds <$> unwrap values) - suite :: TestPlanM (Aff Unit) Unit suite = do group "Time-related Aeson representation tests" do @@ -260,7 +245,6 @@ suite = do toFromAesonTest "AbsTime" absTimeFixture toFromAesonTest "RelSlot" relSlotFixture toFromAesonTest "RelTime" relTimeFixture - toFromAesonTestWith "EraSummaries" eraSummariesLengthToSeconds $ - OgmiosEraSummaries eraSummariesFixture + toFromAesonTest "EraSummaries" $ OgmiosEraSummaries eraSummariesFixture toFromAesonTest "SystemStart" systemStartFixture toFromAesonTest "CurrentEpoch" currentEpochFixture diff --git a/test/PrivateKey.purs b/test/PrivateKey.purs index d91b1c2b3b..72e631c642 100644 --- a/test/PrivateKey.purs +++ b/test/PrivateKey.purs @@ -2,22 +2,20 @@ module Test.Ctl.PrivateKey where import Prelude -import Contract.Config (testnetConfig) -import Contract.Monad (runContract) -import Contract.Transaction - ( FinalizedTransaction(FinalizedTransaction) - , signTransaction - ) -import Ctl.Internal.Cardano.Types.Transaction +import Cardano.Types ( Ed25519Signature - , Transaction(Transaction) , TransactionWitnessSet(TransactionWitnessSet) , Vkeywitness(Vkeywitness) - , mkEd25519Signature + , _witnessSet + ) +import Cardano.Types.Ed25519Signature as Ed25519Signature +import Contract.Config (testnetConfig) +import Contract.Hashing (publicKeyHash) +import Contract.Monad (runContract) +import Contract.Transaction + ( signTransaction ) -import Ctl.Internal.Serialization (publicKeyHash) -import Ctl.Internal.Serialization.Keys (publicKeyFromPrivateKey) -import Ctl.Internal.Test.TestPlanM (TestPlanM) +import Contract.Wallet.Key (publicKeyFromPrivateKey) import Ctl.Internal.Wallet.KeyFile ( privatePaymentKeyFromFile , privatePaymentKeyToFile @@ -29,15 +27,16 @@ import Ctl.Internal.Wallet.Spec , PrivateStakeKeySource(PrivateStakeKeyFile) , WalletSpec(UseKeys) ) -import Data.Lens (_2, _Just, (^?)) +import Data.Lens (_Just, (^?)) import Data.Lens.Index (ix) import Data.Lens.Iso.Newtype (unto) import Data.Lens.Record (prop) -import Data.Maybe (Maybe(Just), fromJust) +import Data.Maybe (Maybe(Just, Nothing), fromJust) import Data.Newtype (unwrap) import Effect.Aff (Aff) import Effect.Class (liftEffect) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Node.FS.Sync (unlink) import Partial.Unsafe (unsafePartial) import Test.Ctl.Fixtures (txFixture1) @@ -58,24 +57,23 @@ suite = do ( Just $ PrivateStakeKeyFile "fixtures/test/parsing/PrivateKey/stake.skey" ) + Nothing , suppressLogs = true } runContract cfg do - signedTx <- unwrap <$> signTransaction (FinalizedTransaction txFixture1) + signedTx <- signTransaction txFixture1 let signature :: Maybe Ed25519Signature signature = Just signedTx ^? _Just - <<< unto Transaction - <<< prop (Proxy :: Proxy "witnessSet") + <<< _witnessSet <<< unto TransactionWitnessSet <<< prop (Proxy :: Proxy "vkeys") - <<< _Just <<< ix 0 <<< unto Vkeywitness - <<< _2 + <<< prop (Proxy :: Proxy "signature") signature `shouldEqual` Just - ( unsafePartial $ fromJust $ mkEd25519Signature $ + ( unsafePartial $ fromJust $ Ed25519Signature.fromBech32 $ "ed25519_sig1w7nkmvk57r6094j9u85r4pddve0hg3985ywl9yzwecx03aa9fnfspl9zmtngmqmczd284lnusjdwkysgukxeq05a548dyepr6vn62qs744wxz" ) test "privateKeyToFile round-trips" do diff --git a/test/ProtocolParams.purs b/test/ProtocolParams.purs index d5918bc36c..e76972d95b 100644 --- a/test/ProtocolParams.purs +++ b/test/ProtocolParams.purs @@ -6,17 +6,17 @@ import Prelude import Aeson (decodeAeson) import Ctl.Internal.QueryM.Ogmios (OgmiosProtocolParameters) -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Data.Either (Either, isRight) import Effect.Aff (Aff) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.Ctl.Utils as Utils import Test.Spec.Assertions (shouldSatisfy) suite :: TestPlanM (Aff Unit) Unit suite = do aeson <- Utils.readAeson - "./fixtures/test/ogmios/queryLedgerState-protocolParameters-68ba1141d17af9326cad70407ea3d7fb.json" + "./fixtures/test/ogmios/queryLedgerState-protocolParameters-1d8c6233b8bfb7c028f1dd60eb113d40.json" group "ProtocolParameters parser" $ do test "is able to parse ogmios response fixture" $ (decodeAeson aeson :: Either _ { result :: OgmiosProtocolParameters }) diff --git a/test/QueryM/AffInterface.purs b/test/QueryM/AffInterface.purs index 0403920f98..324410a747 100644 --- a/test/QueryM/AffInterface.purs +++ b/test/QueryM/AffInterface.purs @@ -2,19 +2,22 @@ module Test.Ctl.QueryM.AffInterface (suite) where import Prelude +import Cardano.Serialization.Lib (fromBytes) +import Contract.Transaction (TransactionHash(TransactionHash)) import Control.Monad.Except (throwError) import Ctl.Internal.QueryM (QueryM, getChainTip, submitTxOgmios) import Ctl.Internal.QueryM.CurrentEpoch (getCurrentEpoch) import Ctl.Internal.QueryM.EraSummaries (getEraSummaries) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.ByteArray (hexToByteArrayUnsafe) +import Data.ByteArray (hexToByteArrayUnsafe) import Data.Either (Either(Left, Right)) -import Data.Maybe (isJust) +import Data.Maybe (fromJust, isJust) import Data.Newtype (wrap) import Data.String.CodeUnits (indexOf) import Data.String.Pattern (Pattern(Pattern)) import Effect.Aff (error, try) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) +import Partial.Unsafe (unsafePartial) import Test.Spec.Assertions (shouldSatisfy) -- note: currently this suite relies on Ogmios being open and running against the @@ -53,8 +56,11 @@ testGetEraSummaries = do testSubmitTxFailure :: QueryM Unit testSubmitTxFailure = do - let bytes = hexToByteArrayUnsafe "00" - void $ submitTxOgmios bytes (wrap bytes) + let + someBytes = hexToByteArrayUnsafe + "ffffffffffff55555555555555555555a1af1b7534b51e60fad3fe9c164313e8" + txHash = TransactionHash $ unsafePartial $ fromJust $ fromBytes someBytes + void $ submitTxOgmios txHash (wrap someBytes) testGetCurrentEpoch :: QueryM Unit testGetCurrentEpoch = do diff --git a/test/Serialization.purs b/test/Serialization.purs index 64c3a6fb39..e0971729ba 100644 --- a/test/Serialization.purs +++ b/test/Serialization.purs @@ -2,52 +2,26 @@ module Test.Ctl.Serialization (suite) where import Prelude -import Ctl.Internal.Cardano.Types.Transaction - ( PublicKey - , Transaction - , convertPubKey - , mkFromCslPubKey - , mkPublicKey - ) -import Ctl.Internal.Deserialization.FromBytes (fromBytes, fromBytesEffect) -import Ctl.Internal.Deserialization.Transaction (convertTransaction) as TD +import Cardano.AsCbor (decodeCbor, encodeCbor) +import Cardano.Serialization.Lib (publicKey_fromBytes) +import Cardano.Types (PublicKey, TransactionHash) +import Cardano.Types.BigNum (fromString, one) as BN +import Cardano.Types.PlutusData as PD +import Cardano.Types.PublicKey as PublicKey +import Contract.Keys (publicKeyFromBech32) import Ctl.Internal.Helpers (liftM) -import Ctl.Internal.Serialization (convertTransaction) as TS -import Ctl.Internal.Serialization (convertTxOutput, serializeData, toBytes) -import Ctl.Internal.Serialization.Keys (bytesFromPublicKey) -import Ctl.Internal.Serialization.PlutusData (convertPlutusData) -import Ctl.Internal.Serialization.Types (TransactionHash) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.BigNum (fromString, one) as BN -import Ctl.Internal.Types.ByteArray (byteArrayToHex, hexToByteArrayUnsafe) -import Ctl.Internal.Types.CborBytes (cborBytesToHex) -import Ctl.Internal.Types.PlutusData as PD -import Data.Either (hush) +import Data.ByteArray (byteArrayToHex, hexToByteArrayUnsafe) import Data.Maybe (Maybe, isJust, isNothing) import Data.Newtype (unwrap, wrap) +import Data.Nullable (toMaybe) import Data.Tuple.Nested ((/\)) import Effect.Aff (Aff) import Effect.Class (liftEffect) import Effect.Exception (error) import JS.BigInt as BigInt import Mote (group, test) -import Test.Ctl.Fixtures - ( txBinaryFixture1 - , txBinaryFixture2 - , txBinaryFixture3 - , txBinaryFixture4 - , txBinaryFixture5 - , txBinaryFixture6 - , txFixture1 - , txFixture2 - , txFixture3 - , txFixture4 - , txFixture5 - , txFixture6 - , txOutputBinaryFixture1 - , txOutputFixture1 - ) -import Test.Ctl.Utils (errMaybe) +import Mote.TestPlanM (TestPlanM) +import Test.Ctl.Fixtures (txOutputBinaryFixture1, txOutputFixture1) import Test.Spec.Assertions (shouldEqual, shouldSatisfy) suite :: TestPlanM (Aff Unit) Unit @@ -58,24 +32,28 @@ suite = do let pkStr = "ed25519_pk1p9sf9wz3t46u9ghht44203gerxt82kzqaqw74fqrmwjmdy8sjxmqknzq8j" - mPk = mkPublicKey pkStr + mPk = publicKeyFromBech32 pkStr pk <- liftM (error $ "Failed to create PubKey from bech32string: " <> pkStr) mPk let - pkBytes = bytesFromPublicKey $ convertPubKey pk - (pk'' :: Maybe PublicKey) = mkFromCslPubKey <$> fromBytes - (wrap $ unwrap pkBytes) + pkBytes = PublicKey.toRawBytes pk + (pk'' :: Maybe PublicKey) = wrap <$> toMaybe + ( publicKey_fromBytes + $ unwrap pkBytes + ) pk'' `shouldSatisfy` isJust test "newTransactionHash" do let txString = "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65ad959996" - txBytes = wrap $ hexToByteArrayUnsafe txString - _txHash :: TransactionHash <- liftEffect $ fromBytesEffect txBytes + txBytes = hexToByteArrayUnsafe txString + _txHash :: TransactionHash <- liftM (error $ "newTransactionHash") + $ decodeCbor + $ wrap txBytes pure unit test "PlutusData #1 - Constr" $ do let @@ -83,7 +61,7 @@ suite = do [ PD.Integer (BigInt.fromInt 1) , PD.Integer (BigInt.fromInt 2) ] - let _ = convertPlutusData datum -- Checking no exception raised + let _ = encodeCbor datum -- Checking no exception raised pure unit test "PlutusData #2 - Map" $ do let @@ -92,58 +70,32 @@ suite = do [ PD.Integer (BigInt.fromInt 1) /\ PD.Integer (BigInt.fromInt 2) , PD.Integer (BigInt.fromInt 3) /\ PD.Integer (BigInt.fromInt 4) ] - let _ = convertPlutusData datum -- Checking no exception raised + let _ = encodeCbor datum -- Checking no exception raised pure unit test "PlutusData #3 - List" $ do let datum = PD.List [ PD.Integer (BigInt.fromInt 1), PD.Integer (BigInt.fromInt 2) ] - let _ = convertPlutusData datum -- Checking no exception raised + let _ = encodeCbor datum -- Checking no exception raised pure unit test "PlutusData #4 - List" $ do let datum = PD.List [ PD.Integer (BigInt.fromInt 1), PD.Integer (BigInt.fromInt 2) ] - let _ = convertPlutusData datum -- Checking no exception raised + let _ = encodeCbor datum -- Checking no exception raised pure unit test "PlutusData #5 - Bytes" $ do let datum = PD.Bytes $ hexToByteArrayUnsafe "00ff" - let _ = convertPlutusData datum -- Checking no exception raised + let _ = encodeCbor datum -- Checking no exception raised pure unit test "PlutusData #6 - Integer 0 (regression to https://github.com/Plutonomicon/cardano-transaction-lib/issues/488 ?)" $ do - let bytes = serializeData $ PD.Integer (BigInt.fromInt 0) - cborBytesToHex bytes `shouldEqual` "00" + let bytes = encodeCbor $ PD.Integer (BigInt.fromInt 0) + byteArrayToHex (unwrap bytes) `shouldEqual` "00" test "TransactionOutput serialization" $ liftEffect do - txo <- convertTxOutput txOutputFixture1 - let bytes = toBytes txo - byteArrayToHex (unwrap bytes) `shouldEqual` txOutputBinaryFixture1 - test "Transaction serialization #1" $ - serializeTX txFixture1 txBinaryFixture1 - test "Transaction serialization #2 - tokens" $ - serializeTX txFixture2 txBinaryFixture2 - test "Transaction serialization #3 - ada" $ - serializeTX txFixture3 txBinaryFixture3 - test "Transaction serialization #4 - ada + mint + certificates" $ - serializeTX txFixture4 txBinaryFixture4 - test "Transaction serialization #5 - plutus script" $ - serializeTX txFixture5 txBinaryFixture5 - test "Transaction serialization #6 - metadata" $ - serializeTX txFixture6 txBinaryFixture6 - group "Transaction Roundtrips" $ do - test "Deserialization is inverse to serialization #1" $ - txSerializedRoundtrip txFixture1 - test "Deserialization is inverse to serialization #2" $ - txSerializedRoundtrip txFixture2 - test "Deserialization is inverse to serialization #3" $ - txSerializedRoundtrip txFixture3 - test "Deserialization is inverse to serialization #4" $ - txSerializedRoundtrip txFixture4 - test "Deserialization is inverse to serialization #5" $ - txSerializedRoundtrip txFixture5 - test "Deserialization is inverse to serialization #6" $ - txSerializedRoundtrip txFixture6 + let bytes = unwrap $ encodeCbor txOutputFixture1 + byteArrayToHex bytes `shouldEqual` txOutputBinaryFixture1 group "BigNum tests" $ do test "BigNum ok" $ do let bn = "18446744073709551615" @@ -154,19 +106,3 @@ suite = do test "BigNum negative" $ do let bnNeg = "-1" BN.fromString bnNeg `shouldSatisfy` isNothing - -serializeTX :: Transaction -> String -> Aff Unit -serializeTX tx fixture = - liftEffect $ do - cslTX <- TS.convertTransaction $ tx - let bytes = toBytes cslTX - byteArrayToHex (unwrap bytes) `shouldEqual` fixture - -txSerializedRoundtrip :: Transaction -> Aff Unit -txSerializedRoundtrip tx = do - cslTX <- liftEffect $ TS.convertTransaction tx - let serialized = toBytes cslTX - deserialized <- errMaybe "Cannot deserialize bytes" $ fromBytes serialized - expected <- errMaybe "Cannot convert TX from CSL to CTL" $ hush $ - TD.convertTransaction deserialized - tx `shouldEqual` expected diff --git a/test/Serialization/Address.purs b/test/Serialization/Address.purs deleted file mode 100644 index a67c88d9e1..0000000000 --- a/test/Serialization/Address.purs +++ /dev/null @@ -1,192 +0,0 @@ -module Test.Ctl.Serialization.Address (suite) where - -import Prelude - -import Contract.Address (addressWithNetworkTagFromBech32) -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.Serialization.Address - ( NetworkId(MainnetId, TestnetId) - , addressBech32 - , addressFromBech32 - , addressNetworkId - , baseAddressDelegationCred - , baseAddressFromAddress - , baseAddressPaymentCred - , baseAddressToAddress - , enterpriseAddress - , enterpriseAddressFromAddress - , enterpriseAddressPaymentCred - , enterpriseAddressToAddress - , keyHashCredential - , paymentKeyHashStakeKeyHashAddress - , pointerAddress - , pointerAddressFromAddress - , pointerAddressPaymentCred - , pointerAddressStakePointer - , pointerAddressToAddress - , rewardAddress - , rewardAddressFromAddress - , rewardAddressPaymentCred - , rewardAddressToAddress - , scriptHashCredential - , stakeCredentialToKeyHash - , stakeCredentialToScriptHash - ) -import Ctl.Internal.Serialization.Hash - ( Ed25519KeyHash - , ScriptHash - , ed25519KeyHashFromBech32 - , scriptHashFromBytes - ) -import Ctl.Internal.Serialization.ToBytes (toBytes) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.BigNum (fromInt, fromStringUnsafe) as BigNum -import Ctl.Internal.Types.ByteArray (hexToByteArrayUnsafe) -import Data.Maybe (Maybe(Nothing)) -import Data.Newtype (unwrap, wrap) -import Effect.Aff (Aff) -import Effect.Class.Console (log) -import Mote (group, test) -import Test.Ctl.Fixtures (ed25519KeyHashFixture1) -import Test.Ctl.Utils (errMaybe) -import Test.Spec.Assertions (shouldEqual) - -doesNotThrow - :: forall (f :: Type -> Type) (a :: Type). Applicative f => a -> f a -doesNotThrow = pure - -pkhBech32 :: Bech32String -pkhBech32 = "addr_vkh1zuctrdcq6ctd29242w8g84nlz0q38t2lnv3zzfcrfqktx0c9tzp" - -scriptHashHex :: String -scriptHashHex = "463e9264962cea64efafa576d44c8d2821d09c0c7495c253d4101a9a" - -mPkh :: Maybe Ed25519KeyHash -mPkh = ed25519KeyHashFromBech32 pkhBech32 - -mScriptHash :: Maybe ScriptHash -mScriptHash = scriptHashFromBytes $ hexToByteArrayUnsafe scriptHashHex - -addressFunctionsTest :: TestPlanM (Aff Unit) Unit -addressFunctionsTest = test "Address tests" $ do - let - bechstr = - "addr1qyc0kwu98x23ufhsxjgs5k3h7gktn8v5682qna5amwh2juguztcrc8hjay66es67ctn0jmr9plfmlw37je2s2px4xdssgvxerq" - testnetBech = - "addr_test1qqm0z9quxyefwwq902p5f9t4s35smhegjthhhqpeclnpx2rzhuq2p6jahnky7qqua9nz9tcw6nlgy6cpjvmlaaye4apqzc6ppq" - addr1 <- errMaybe "addressFromBech32 failed on valid bech32" $ - addressFromBech32 bechstr - bechstr `shouldEqual` addressBech32 addr1 - addressFromBech32 "randomstuff" `shouldEqual` Nothing - let addrBts = toBytes addr1 - addr2 <- errMaybe "addressFromBech32 failed on valid bech32" $ - fromBytes addrBts - addr2 `shouldEqual` addr1 - addressNetworkId addr2 `shouldEqual` MainnetId - testnetAddr <- - errMaybe "addressWithNetworkTagFromBech32 failed on valid bech32" $ - addressWithNetworkTagFromBech32 testnetBech - mainnetAddr <- - errMaybe "addressWithNetworkTagFromBech32 failed on valid bech32" $ - addressWithNetworkTagFromBech32 bechstr - _.networkId (unwrap testnetAddr) `shouldEqual` TestnetId - _.networkId (unwrap mainnetAddr) `shouldEqual` MainnetId - -stakeCredentialTests :: TestPlanM (Aff Unit) Unit -stakeCredentialTests = test "StakeCredential tests" $ do - pkh <- errMaybe "Error ed25519KeyHashFromBech32:" mPkh - scrh <- errMaybe "Error scriptHashFromBech32:" mScriptHash - - let - pkhCred = keyHashCredential $ pkh - schCred = scriptHashCredential $ scrh - pkhCredBytes = toBytes pkhCred - schCredBytes = toBytes schCred - - pkhCred2 <- errMaybe "StakeCredential FromBytes failed on valid bytes" $ - fromBytes pkhCredBytes - pkh2 <- errMaybe "stakeCredentialToKeyHash failed" $ stakeCredentialToKeyHash - pkhCred2 - pkh2 `shouldEqual` pkh - stakeCredentialToScriptHash pkhCred2 `shouldEqual` Nothing - - schCred2 <- errMaybe "StakeCredential FromBytes failed on valid bytes" $ - fromBytes schCredBytes - sch2 <- errMaybe "stakeCredentialToScriptHash failed" $ - stakeCredentialToScriptHash schCred2 - sch2 `shouldEqual` scrh - stakeCredentialToKeyHash schCred2 `shouldEqual` Nothing - -baseAddressFunctionsTest :: TestPlanM (Aff Unit) Unit -baseAddressFunctionsTest = test "BaseAddress tests" $ do - pkh <- errMaybe "Error ed25519KeyHashFromBech32:" mPkh - baddr <- doesNotThrow $ - paymentKeyHashStakeKeyHashAddress MainnetId pkh ed25519KeyHashFixture1 - addr <- doesNotThrow $ baseAddressToAddress baddr - baddr2 <- errMaybe "baseAddressFromAddress failed on valid base address" $ - baseAddressFromAddress - addr - baddr2 `shouldEqual` baddr - baseAddressDelegationCred baddr `shouldEqual` keyHashCredential - ed25519KeyHashFixture1 - baseAddressPaymentCred baddr `shouldEqual` keyHashCredential pkh - -rewardAddressFunctionsTest :: TestPlanM (Aff Unit) Unit -rewardAddressFunctionsTest = test "RewardAddress tests" $ do - pkh <- errMaybe "Error ed25519KeyHashFromBech32:" mPkh - raddr <- doesNotThrow $ rewardAddress - { network: TestnetId, paymentCred: keyHashCredential pkh } - addr <- doesNotThrow $ rewardAddressToAddress raddr - raddr2 <- errMaybe "rewardAddressFromAddress failed on valid reward address" $ - rewardAddressFromAddress addr - raddr2 `shouldEqual` raddr - rewardAddressPaymentCred raddr `shouldEqual` keyHashCredential pkh - -enterpriseAddressFunctionsTest :: TestPlanM (Aff Unit) Unit -enterpriseAddressFunctionsTest = test "EnterpriseAddress tests" $ do - pkh <- errMaybe "Error ed25519KeyHashFromBech32:" mPkh - eaddr <- doesNotThrow $ enterpriseAddress - { network: MainnetId, paymentCred: keyHashCredential pkh } - addr <- doesNotThrow $ enterpriseAddressToAddress eaddr - eaddr2 <- - errMaybe "enterpriseAddressFromAddress failed on valid enterprise address" $ - enterpriseAddressFromAddress addr - eaddr2 `shouldEqual` eaddr - enterpriseAddressPaymentCred eaddr `shouldEqual` keyHashCredential pkh - -pointerAddressFunctionsTest :: TestPlanM (Aff Unit) Unit -pointerAddressFunctionsTest = test "PointerAddress tests" $ do - pkh <- errMaybe "Error ed25519KeyHashFromBech32:" mPkh - let - pointer = - { slot: wrap (BigNum.fromStringUnsafe "2147483648") - , certIx: wrap (BigNum.fromInt 20) - , txIx: wrap (BigNum.fromInt 120) - } - paddr <- doesNotThrow $ pointerAddress - { network: MainnetId - , paymentCred: keyHashCredential pkh - , stakePointer: pointer - } - addr <- doesNotThrow $ pointerAddressToAddress paddr - paddr2 <- errMaybe "pointerAddressFromAddress failed on valid pointer address" - $ - pointerAddressFromAddress addr - paddr2 `shouldEqual` paddr - pointerAddressPaymentCred paddr `shouldEqual` keyHashCredential pkh - pointerAddressStakePointer paddr `shouldEqual` pointer - -byronAddressFunctionsTest :: TestPlanM (Aff Unit) Unit -byronAddressFunctionsTest = test "ByronAddress tests" $ log - "ByronAddress tests todo" - -suite :: TestPlanM (Aff Unit) Unit -suite = group "Address test suite" $ do - addressFunctionsTest - stakeCredentialTests - baseAddressFunctionsTest - rewardAddressFunctionsTest - enterpriseAddressFunctionsTest - pointerAddressFunctionsTest - byronAddressFunctionsTest diff --git a/test/Serialization/Hash.purs b/test/Serialization/Hash.purs index bd9da66ac4..ddaa92c800 100644 --- a/test/Serialization/Hash.purs +++ b/test/Serialization/Hash.purs @@ -1,28 +1,18 @@ module Test.Ctl.Serialization.Hash (suite) where -import Control.Bind (bind, discard) -import Ctl.Internal.Serialization.Hash - ( ed25519KeyHashFromBech32 - , ed25519KeyHashFromBytes - , ed25519KeyHashToBech32 - , ed25519KeyHashToBech32Unsafe - , ed25519KeyHashToBytes - , scriptHashFromBech32 - , scriptHashFromBytes - , scriptHashToBech32 - , scriptHashToBech32Unsafe - , scriptHashToBytes - ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.Aliases (Bech32String) -import Ctl.Internal.Types.ByteArray (hexToByteArrayUnsafe) -import Data.Eq ((==)) -import Data.Function (($)) +import Prelude + +import Cardano.AsCbor (decodeCbor, encodeCbor) +import Cardano.Types (Bech32String) +import Cardano.Types.Ed25519KeyHash as Ed25519KeyHash +import Cardano.Types.ScriptHash as ScriptHash +import Data.ByteArray (hexToByteArrayUnsafe) import Data.Maybe (Maybe(Just, Nothing), isNothing) -import Data.Newtype (unwrap) -import Data.Unit (Unit) +import Data.Newtype (wrap) import Effect.Aff (Aff) import Mote (test) +import Mote.TestPlanM (TestPlanM) +import Partial.Unsafe (unsafePartial) import Test.Ctl.Utils (assertTrue, errMaybe) pkhBech32 :: Bech32String @@ -35,56 +25,47 @@ invalidBech32 :: Bech32String invalidBech32 = "addr_vkh1zuctrdcq6ctd29242w8g8444z0q38t2lnv3zzf44fqktx044444" suite :: TestPlanM (Aff Unit) Unit -suite = test "Serialization.Hash" do +suite = unsafePartial $ test "Serialization.Hash" do assertTrue "ed25519KeyHashFromBech32 returns Nothing on random string" - (isNothing $ ed25519KeyHashFromBech32 invalidBech32) + (isNothing $ Ed25519KeyHash.fromBech32 invalidBech32) - pkh <- errMaybe "ed25519KeyHashFromBech32 failed" $ ed25519KeyHashFromBech32 - pkhBech32 - let - pkhB32 = ed25519KeyHashToBech32Unsafe "addr_vkh" pkh - mPkhB32 = ed25519KeyHashToBech32 "addr_vkh" pkh - pkhBts = ed25519KeyHashToBytes pkh - pkh2 = ed25519KeyHashFromBytes $ unwrap pkhBts + do + pkh <- errMaybe "ed25519KeyHashFromBech32 failed" $ + Ed25519KeyHash.fromBech32 + pkhBech32 + let + pkhB32 = Ed25519KeyHash.toBech32Unsafe "addr_vkh" pkh + mPkhB32 = Ed25519KeyHash.toBech32 "addr_vkh" pkh + pkhBts = encodeCbor pkh + pkh2 = decodeCbor pkhBts - assertTrue - "Safe ed25519KeyHashToBech32 should produce Just when unsafe version works" - (mPkhB32 == Just pkhB32) + assertTrue + "Safe Ed25519KeyHash.toBech32 should produce Just when unsafe version works" + (mPkhB32 == Just pkhB32) - assertTrue - "Safe ed25519KeyHashToBech32 should return Nothing on invalid prefix" - (ed25519KeyHashToBech32 "" pkh == Nothing) + assertTrue + "Safe Ed25519KeyHash.toBech32 should return Nothing on invalid prefix" + (Ed25519KeyHash.toBech32 "" pkh == Nothing) - assertTrue "ed25519KeyHashFromBytes does not reverts ed25519KeyHashToBytes" - (pkh2 == Just pkh) + assertTrue "ed25519KeyHashFromBytes does not reverts ed25519KeyHashToBytes" + (pkh2 == Just pkh) - assertTrue - "ed25519KeyHashFromBech32 does not reverts ed25519KeyHashToBech32Unsafe" - (pkhB32 == pkhBech32) + assertTrue + "ed25519KeyHashFromBech32 does not reverts Ed25519KeyHash.toBech32Unsafe" + (pkhB32 == pkhBech32) -- - - assertTrue "scriptHashFromBech32 returns Nothing on random string" - (isNothing $ scriptHashFromBech32 invalidBech32) - - scrh <- errMaybe "scriptHashFromBytes failed" $ scriptHashFromBytes - $ hexToByteArrayUnsafe - scriptHashHex - let - scrhB32 = scriptHashToBech32Unsafe "stake_vkh" scrh - mScrhB32 = scriptHashToBech32 "stake_vkh" scrh - scrhBts = scriptHashToBytes scrh - scrhFromBytes = scriptHashFromBytes $ unwrap scrhBts - scrhFromBech = scriptHashFromBech32 scrhB32 - - assertTrue "Safe scriptHashToBech32 should produce Just when unsafe works" - (mScrhB32 == Just scrhB32) - - assertTrue "Safe scriptHashToBech32 should return Nothing on invalid prefix" - (scriptHashToBech32 "" scrh == Nothing) - - assertTrue "scriptHashFromBytes does not reverts scriptHashToBytes" - (scrhFromBytes == Just scrh) - - assertTrue "scriptHashFromBech32 does not reverts scriptHashToBech32Unsafe" - (scrhFromBech == Just scrh) + do + assertTrue "scriptHashFromBech32 returns Nothing on random string" + (isNothing $ ScriptHash.fromBech32 invalidBech32) + + scrh <- errMaybe "scriptHashFromBytes failed" $ decodeCbor + $ wrap + $ hexToByteArrayUnsafe scriptHashHex + let + scrhB32 = ScriptHash.toBech32Unsafe "stake_vkh" scrh + scrhFromBech = ScriptHash.fromBech32 scrhB32 + + assertTrue + "ScriptHash.fromBech32 does not reverts ScriptHash.toBech32Unsafe" + (scrhFromBech == Just scrh) diff --git a/test/Plutip.purs b/test/Testnet.purs similarity index 50% rename from test/Plutip.purs rename to test/Testnet.purs index d80ff74083..ad5fe4720e 100644 --- a/test/Plutip.purs +++ b/test/Testnet.purs @@ -1,74 +1,71 @@ -module Test.Ctl.Plutip +module Test.Ctl.Testnet ( main ) where import Prelude -import Contract.Test.Plutip (PlutipConfig, noWallet, testPlutipContracts) +import Contract.Test (noWallet) +import Contract.Test.Testnet + ( defaultTestnetConfig + , runTestnetTestPlan + , testTestnetContracts + ) import Contract.Test.Utils (exitCode, interruptOnSignal) import Ctl.Internal.Contract.Monad (wrapQueryM) -import Ctl.Internal.Plutip.Server - ( checkPlutipServer - , startPlutipCluster - , startPlutipServer - , stopChildProcessWithPort - , stopPlutipCluster - ) -import Ctl.Internal.Plutip.Types (StopClusterResponse(StopClusterSuccess)) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Test.TestPlanM as Utils import Data.Maybe (Maybe(Just)) import Data.Posix.Signal (Signal(SIGINT)) import Effect (Effect) import Effect.Aff - ( Aff - , Milliseconds(Milliseconds) - , bracket + ( Milliseconds(Milliseconds) , cancelWith , effectCanceler , launchAff ) -import Mote (group, test) +import Mote (group) import Mote.Monad (mapTest) +import Mote.TestPlanM as Utils import Test.Ctl.BalanceTx.ChangeGeneration as ChangeGeneration -import Test.Ctl.Plutip.Common (config) -import Test.Ctl.Plutip.Contract as Contract -import Test.Ctl.Plutip.Contract.Assert as Assert -import Test.Ctl.Plutip.Contract.Mnemonics as Mnemonics -import Test.Ctl.Plutip.Contract.NetworkId as NetworkId -import Test.Ctl.Plutip.Contract.OgmiosMempool as OgmiosMempool -import Test.Ctl.Plutip.ExUnits as ExUnits -import Test.Ctl.Plutip.Logging as Logging -import Test.Ctl.Plutip.UtxoDistribution as UtxoDistribution import Test.Ctl.QueryM.AffInterface as QueryM.AffInterface -import Test.Spec.Assertions (shouldSatisfy) +import Test.Ctl.Testnet.Contract as Contract +import Test.Ctl.Testnet.Contract.Assert as Assert +import Test.Ctl.Testnet.Contract.Mnemonics as Mnemonics +import Test.Ctl.Testnet.Contract.OgmiosMempool as OgmiosMempool +import Test.Ctl.Testnet.ExUnits as ExUnits +import Test.Ctl.Testnet.Gov as Gov +import Test.Ctl.Testnet.Logging as Logging +import Test.Ctl.Testnet.SameWallets as SameWallets +import Test.Ctl.Testnet.UtxoDistribution as UtxoDistribution import Test.Spec.Runner (defaultConfig) --- Run with `npm run plutip-test` +-- Run with `npm run testnet-test` main :: Effect Unit main = interruptOnSignal SIGINT =<< launchAff do + let config = defaultTestnetConfig flip cancelWith (effectCanceler (exitCode 1)) do Utils.interpretWithConfig defaultConfig { timeout = Just $ Milliseconds 70_000.0, exit = true } - $ group "Plutip" do - testPlutipContracts config Mnemonics.suite + $ group "cardano-testnet" do + testTestnetContracts config Mnemonics.suite group "ExUnits - normal limits" do - testPlutipContracts config $ ExUnits.mkFailingSuite 3000 - testPlutipContracts config $ ExUnits.mkSuite 2550 - group "ExUnits - relaxed limits" do - testPlutipContracts configWithMaxExUnits $ ExUnits.mkSuite 3000 - testPlutipContracts config Assert.suite + testTestnetContracts config $ ExUnits.mkFailingSuite 8000 + testTestnetContracts config $ ExUnits.mkSuite 2550 + -- FIXME: group "ExUnits - relaxed limits" do + -- testTestnetContracts configWithMaxExUnits $ ExUnits.mkSuite 3000 + testTestnetContracts config Assert.suite Logging.suite - testStartPlutipCluster - testPlutipContracts config $ do + -- FIXME: testStartPlutipCluster + testTestnetContracts config $ do flip mapTest QueryM.AffInterface.suite (noWallet <<< wrapQueryM) - NetworkId.suite ChangeGeneration.suite Contract.suite + Gov.suite UtxoDistribution.suite - testPlutipContracts config OgmiosMempool.suite + testTestnetContracts config OgmiosMempool.suite + runTestnetTestPlan config SameWallets.suite +-- FIXME: ClusterParameters.runTest +{- configWithMaxExUnits :: PlutipConfig configWithMaxExUnits = config { clusterConfig = config.clusterConfig { raiseExUnitsToMax = true } } @@ -84,3 +81,4 @@ testStartPlutipCluster = group "Server" do stopRes `shouldSatisfy` case _ of StopClusterSuccess -> true _ -> false + -} diff --git a/test/Testnet/Common.purs b/test/Testnet/Common.purs new file mode 100644 index 0000000000..0a5c94d137 --- /dev/null +++ b/test/Testnet/Common.purs @@ -0,0 +1,27 @@ +module Test.Ctl.Testnet.Common + ( privateDrepKey + , privateStakeKey + ) where + +import Prelude + +import Cardano.Wallet.Key (PrivateDrepKey, PrivateStakeKey) +import Contract.Keys (privateKeyFromBytes) +import Data.ByteArray (hexToByteArray) +import Data.Maybe (fromJust) +import Data.Newtype (wrap) +import Partial.Unsafe (unsafePartial) + +privateStakeKey :: PrivateStakeKey +privateStakeKey = wrap $ unsafePartial $ fromJust + $ privateKeyFromBytes =<< map wrap + ( hexToByteArray + "633b1c4c4a075a538d37e062c1ed0706d3f0a94b013708e8f5ab0a0ca1df163d" + ) + +privateDrepKey :: PrivateDrepKey +privateDrepKey = wrap $ unsafePartial $ fromJust + $ privateKeyFromBytes =<< map wrap + ( hexToByteArray + "9151f1251eaf26d1a4de071c94dcd23e566cd9bc970df04a1aa3e5e15ecd79b6" + ) diff --git a/test/Plutip/Contract.purs b/test/Testnet/Contract.purs similarity index 65% rename from test/Plutip/Contract.purs rename to test/Testnet/Contract.purs index 703d1b6ddc..b95a05bce2 100644 --- a/test/Plutip/Contract.purs +++ b/test/Testnet/Contract.purs @@ -1,15 +1,44 @@ -module Test.Ctl.Plutip.Contract +module Test.Ctl.Testnet.Contract ( suite ) where import Prelude +import Cardano.AsCbor (decodeCbor) +import Cardano.Plutus.ApplyArgs (applyArgs) +import Cardano.Serialization.Lib (fromBytes) +import Cardano.Transaction.Builder + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, SpendOutput) + ) +import Cardano.Types + ( Address(EnterpriseAddress) + , Credential(PubKeyHashCredential, ScriptHashCredential) + , GeneralTransactionMetadata + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , TransactionUnspentOutput(TransactionUnspentOutput) + , _input + , _output + ) +import Cardano.Types.AssetName as AssetName +import Cardano.Types.Coin as Coin +import Cardano.Types.Int as Int +import Cardano.Types.Mint as Mint +import Cardano.Types.PlutusData (unit) as PlutusData +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.PrivateKey (toPublicKey) as PrivateKey +import Cardano.Types.PublicKey (hash) as PublicKey +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) +import Cardano.Types.Value (lovelaceValueOf) import Contract.Address ( PaymentPubKeyHash(PaymentPubKeyHash) - , PubKeyHash(PubKeyHash) , StakePubKeyHash , getNetworkId - , scriptHashAddress + , mkAddress ) import Contract.AuxiliaryData (setGeneralTxMetadata) import Contract.BalanceTxConstraints @@ -21,19 +50,19 @@ import Contract.BalanceTxConstraints , mustUseCollateralUtxos ) import Contract.Chain (currentTime, waitUntilSlot) +import Contract.Config + ( KnownWallet(Nami, Gero, Flint, Lode, NuFi) + , walletName + ) import Contract.Hashing (datumHash, nativeScriptHash) +import Contract.Keys (privateKeyFromBytes) import Contract.Log (logInfo') -import Contract.Metadata - ( GeneralTransactionMetadata(GeneralTransactionMetadata) - , TransactionMetadatum(Text) - , TransactionMetadatumLabel(TransactionMetadatumLabel) - ) +import Contract.Metadata as Metadatum import Contract.Monad (Contract, liftContractE, liftContractM, liftedM) import Contract.Numeric.BigNum as BigNum import Contract.PlutusData - ( Datum(Datum) - , PlutusData(Bytes, Integer, List) - , Redeemer(Redeemer) + ( PlutusData(Bytes, Integer, List) + , RedeemerDatum(RedeemerDatum) , getDatumByHash , getDatumsByHashes , getDatumsByHashesWithErrors @@ -42,21 +71,20 @@ import Contract.PlutusData import Contract.Prelude (liftM, mconcat) import Contract.Prim.ByteArray ( byteArrayFromAscii + , hexToByteArray , hexToByteArrayUnsafe , hexToRawBytes ) import Contract.ScriptLookups as Lookups import Contract.Scripts ( ValidatorHash - , applyArgs , getScriptByHash , getScriptsByHashes - , mintingPolicyHash , validatorHash ) import Contract.Test (ContractTest) import Contract.Test.Assert (runChecks) -import Contract.Test.Plutip +import Contract.Test.Testnet ( InitialUTxOs , InitialUTxOsWithStakeKey , withStakeKey @@ -67,7 +95,7 @@ import Contract.Transaction ( BalanceTxError(BalanceInsufficientError, InsufficientCollateralUtxos) , DataHash , NativeScript(ScriptPubkey, ScriptNOfK, ScriptAll) - , OutputDatum(OutputDatumHash, NoOutputDatum, OutputDatum) + , OutputDatum(OutputDatum, OutputDatumHash) , ScriptRef(PlutusScriptRef, NativeScriptRef) , TransactionHash(TransactionHash) , TransactionInput(TransactionInput) @@ -75,10 +103,10 @@ import Contract.Transaction , awaitTxConfirmed , balanceTx , balanceTxE - , balanceTxWithConstraints - , balanceTxWithConstraintsE + , buildTx , createAdditionalUtxos - , getTxMetadata + , getTxAuxiliaryData + , lookupTxHash , signTransaction , submit , submitTxFromConstraints @@ -97,9 +125,13 @@ import Contract.Wallet , getWalletCollateral , getWalletUtxos , isWalletAvailable + , ownDrepPubKey + , ownDrepPubKeyHash , ownPaymentPubKeyHashes + , ownRegisteredPubStakeKeys , ownStakePubKeyHashes - , privateKeyFromBytes + , ownUnregisteredPubStakeKeys + , signData , withKeyWallet ) import Control.Monad.Error.Class (try) @@ -113,11 +145,7 @@ import Ctl.Examples.BalanceTxConstraints as BalanceTxConstraintsExample import Ctl.Examples.Cip30 as Cip30 import Ctl.Examples.ContractTestUtils as ContractTestUtils import Ctl.Examples.ECDSA as ECDSA -import Ctl.Examples.Helpers - ( mkCurrencySymbol - , mkTokenName - , mustPayToPubKeyStakeAddress - ) +import Ctl.Examples.Helpers (mkAssetName, mustPayToPubKeyStakeAddress) import Ctl.Examples.IncludeDatum as IncludeDatum import Ctl.Examples.Lose7Ada as AlwaysFails import Ctl.Examples.ManyAssets as ManyAssets @@ -131,37 +159,17 @@ import Ctl.Examples.OneShotMinting (contract) as OneShotMinting import Ctl.Examples.PaysWithDatum (contract) as PaysWithDatum import Ctl.Examples.PlutusV2.InlineDatum as InlineDatum import Ctl.Examples.PlutusV2.OneShotMinting (contract) as OneShotMintingV2 -import Ctl.Examples.PlutusV2.ReferenceInputs (contract) as ReferenceInputs import Ctl.Examples.PlutusV2.ReferenceInputsAndScripts (contract) as ReferenceInputsAndScripts -import Ctl.Examples.PlutusV2.ReferenceScripts (contract) as ReferenceScripts -import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyV2) +import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) import Ctl.Examples.Schnorr as Schnorr import Ctl.Examples.SendsToken (contract) as SendsToken import Ctl.Examples.TxChaining (contract) as TxChaining -import Ctl.Internal.Plutus.Conversion.Address (toPlutusAddress) -import Ctl.Internal.Plutus.Types.Address (Address, pubKeyHashAddress) -import Ctl.Internal.Plutus.Types.Transaction - ( TransactionOutputWithRefScript(TransactionOutputWithRefScript) - ) -import Ctl.Internal.Plutus.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - , _input - , _output - , lookupTxHash - ) -import Ctl.Internal.Plutus.Types.Value (lovelaceValueOf) -import Ctl.Internal.Scripts (nativeScriptHashEnterpriseAddress) -import Ctl.Internal.Test.TestPlanM (TestPlanM) +import Ctl.Internal.Test.UtxoDistribution (TestWalletSpec) import Ctl.Internal.Types.Interval (getSlotLength) -import Ctl.Internal.Wallet - ( WalletExtension(NamiWallet, GeroWallet, FlintWallet, NuFiWallet) - ) -import Ctl.Internal.Wallet.Cip30Mock - ( WalletMock(MockNami, MockGero, MockFlint, MockNuFi, MockGenericCip30) - , withCip30Mock - ) +import Ctl.Internal.Wallet.Cip30Mock (withCip30Mock) import Data.Array (head, (!!)) +import Data.Array (singleton) as Array import Data.Either (Either(Left, Right), hush, isLeft, isRight) import Data.Foldable (fold, foldM, length) import Data.Lens (view) @@ -176,11 +184,11 @@ import Effect.Class (liftEffect) import Effect.Exception (error, throw) import JS.BigInt as BigInt import Mote (group, skip, test) +import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Safe.Coerce (coerce) import Test.Ctl.Fixtures - ( cip25MetadataFixture1 - , fullyAppliedScriptFixture + ( fullyAppliedScriptFixture , nativeScriptFixture1 , nativeScriptFixture2 , nativeScriptFixture3 @@ -191,21 +199,25 @@ import Test.Ctl.Fixtures , partiallyAppliedScriptFixture , unappliedScriptFixture ) -import Test.Ctl.Plutip.Common (privateStakeKey) -import Test.Ctl.Plutip.Utils (getLockedInputs, submitAndLog) -import Test.Ctl.Plutip.UtxoDistribution (checkUtxoDistribution) -import Test.Spec.Assertions (shouldEqual, shouldNotEqual, shouldSatisfy) +import Test.Ctl.Testnet.Common (privateDrepKey, privateStakeKey) +import Test.Ctl.Testnet.Utils (getLockedInputs, submitAndLog) +import Test.Ctl.Testnet.UtxoDistribution (checkUtxoDistribution) +import Test.Spec.Assertions + ( expectError + , shouldEqual + , shouldNotEqual + , shouldReturn + , shouldSatisfy + ) suite :: TestPlanM ContractTest Unit suite = do group "WaitUntilSlot" do test "wait for slot far in the future" do withWallets unit \_ -> do - -- Plutip increases last known slot by 80 at a time void $ waitUntilSlot $ Slot $ BigNum.fromInt 10 void $ waitUntilSlot $ Slot $ BigNum.fromInt 160 void $ waitUntilSlot $ Slot $ BigNum.fromInt 161 - void $ waitUntilSlot $ Slot $ BigNum.fromInt 241 group "Regressions" do skip $ test "#1441 - Mint many assets at once - fails with TooManyAssetsInOutput" @@ -213,8 +225,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1000_000_000 - , BigInt.fromInt 2000_000_000 + [ BigNum.fromInt 1000_000_000 + , BigNum.fromInt 2000_000_000 ] withWallets distribution \alice -> do withKeyWallet alice ManyAssets.contract @@ -223,8 +235,8 @@ suite = do do let someUtxos = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 5_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 5_000_000 ] withWallets someUtxos \alice -> do @@ -238,13 +250,13 @@ suite = do constraints :: Constraints.TxConstraints constraints = mustPayToPubKeyStakeAddress pkh stakePkh $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 + $ BigNum.fromInt 2_000_000 lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints res <- - ( balanceTxWithConstraintsE ubTx + ( balanceTxE ubTx usedUtxos (mustNotSpendUtxosWithOutRefs $ Map.keys utxos) ) res `shouldSatisfy` isLeft @@ -252,8 +264,8 @@ suite = do test "#1480 - test that does nothing but fails" do let someUtxos = - [ BigInt.fromInt 2_000_000 - , BigInt.fromInt 3_000_000 + [ BigNum.fromInt 2_000_000 + , BigNum.fromInt 3_000_000 ] privateStakeKey1 = @@ -280,8 +292,8 @@ suite = do do let someUtxos = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 5_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 5_000_000 ] withWallets (someUtxos /\ someUtxos) \(alice /\ bob) -> do bobsCollateral <- withKeyWallet bob do @@ -295,10 +307,10 @@ suite = do awaitTxConfirmed txId logInfo' "Try to spend locked values" - let - scriptAddress = scriptHashAddress vhash Nothing + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) + Nothing utxos <- utxosAt scriptAddress - txInput <- + utxo <- liftM ( error ( "The id " @@ -307,21 +319,23 @@ suite = do <> show scriptAddress ) ) - (view _input <$> head (lookupTxHash txId utxos)) + $ head (lookupTxHash txId utxos) let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer + usedUtxos = Map.union utxos $ toUtxoMap [ utxo ] + ubTx <- buildTx + [ SpendOutput + utxo + ( Just + $ PlutusScriptOutput (ScriptValue validator) + RedeemerDatum.unit + $ Just + $ DatumValue + $ PlutusData.unit + ) + ] - ubTx <- mkUnbalancedTx lookups constraints - res <- - ( balanceTxWithConstraintsE ubTx - $ mustUseCollateralUtxos bobsCollateral - ) + res <- balanceTxE ubTx usedUtxos + (mustUseCollateralUtxos bobsCollateral) res `shouldSatisfy` isRight test @@ -329,8 +343,8 @@ suite = do do let someUtxos = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 5_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 5_000_000 ] withWallets someUtxos \alice -> do withKeyWallet alice do @@ -342,10 +356,10 @@ suite = do awaitTxConfirmed txId logInfo' "Try to spend locked values" - let - scriptAddress = scriptHashAddress vhash Nothing + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) + Nothing utxos <- utxosAt scriptAddress - txInput <- + utxo <- liftM ( error ( "The id " @@ -354,21 +368,21 @@ suite = do <> show scriptAddress ) ) - (view _input <$> head (lookupTxHash txId utxos)) + $ head (lookupTxHash txId utxos) let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - - ubTx <- mkUnbalancedTx lookups constraints - res <- - ( balanceTxWithConstraintsE ubTx - $ mustUseCollateralUtxos Map.empty - ) + usedUtxos = Map.union utxos $ toUtxoMap [ utxo ] + ubTx <- buildTx + [ SpendOutput + utxo + ( Just + $ PlutusScriptOutput (ScriptValue validator) + RedeemerDatum.unit + $ Just + $ DatumValue + $ PlutusData.unit + ) + ] + res <- balanceTxE ubTx usedUtxos (mustUseCollateralUtxos Map.empty) res `shouldSatisfy` case _ of Left (InsufficientCollateralUtxos mp) -> Map.isEmpty mp _ -> false @@ -377,20 +391,20 @@ suite = do let distribution :: InitialUTxOs /\ InitialUTxOs distribution = - [ BigInt.fromInt 10_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 10_000_000 + , BigNum.fromInt 20_000_000 ] /\ - [ BigInt.fromInt 2_000_000_000 ] + [ BigNum.fromInt 2_000_000_000 ] withWallets distribution \(alice /\ bob) -> do withKeyWallet alice do getWalletCollateral >>= liftEffect <<< case _ of Nothing -> throw "Unable to get collateral" Just [ TransactionUnspentOutput - { output: TransactionOutputWithRefScript { output } } + { output: output } ] -> do let amount = (unwrap output).amount - unless (amount == lovelaceValueOf (BigInt.fromInt 10_000_000)) + unless (amount == lovelaceValueOf (BigNum.fromInt 10_000_000)) $ throw "Wrong UTxO selected as collateral" Just _ -> do -- not a bug, but unexpected @@ -398,27 +412,30 @@ suite = do withKeyWallet bob do pure unit -- sign, balance, submit, etc. - test "Payment keyhash to payment keyhash transaction (Pkh2Pkh example)" do - let - distribution :: InitialUTxOs - distribution = - [ BigInt.fromInt 10_000_000 - , BigInt.fromInt 20_000_000 - ] - withWallets distribution \alice -> do - checkUtxoDistribution distribution alice - pkh <- liftedM "Failed to get PKH" $ head <$> withKeyWallet alice - ownPaymentPubKeyHashes - stakePkh <- join <<< head <$> withKeyWallet alice ownStakePubKeyHashes - withKeyWallet alice $ pkh2PkhContract pkh stakePkh - + test + "Payment keyhash to payment keyhash transaction (Pkh2Pkh example)" + do + let + distribution :: InitialUTxOs + distribution = + [ BigNum.fromInt 10_000_000 + , BigNum.fromInt 20_000_000 + , BigNum.fromInt 20_000_000 + ] + withWallets distribution \alice -> do + logInfo' "407 hi" + checkUtxoDistribution distribution alice + pkh <- liftedM "Failed to get PKH" $ head <$> withKeyWallet alice + ownPaymentPubKeyHashes + stakePkh <- join <<< head <$> withKeyWallet alice ownStakePubKeyHashes + withKeyWallet alice $ pkh2PkhContract pkh stakePkh test "Base Address to Base Address transaction (Pkh2Pkh example, but with stake keys)" do let aliceUtxos = - [ BigInt.fromInt 20_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 20_000_000 + , BigNum.fromInt 20_000_000 ] distribution = withStakeKey privateStakeKey aliceUtxos @@ -436,12 +453,12 @@ suite = do do let aliceUtxos = - [ BigInt.fromInt 20_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 20_000_000 + , BigNum.fromInt 20_000_000 ] bobUtxos = - [ BigInt.fromInt 20_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 20_000_000 + , BigNum.fromInt 20_000_000 ] distribution :: InitialUTxOs /\ InitialUTxOs @@ -469,12 +486,12 @@ suite = do do let aliceUtxos = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 20_000_000 ] bobUtxos = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 20_000_000 ] distribution = withStakeKey privateStakeKey aliceUtxos @@ -501,7 +518,7 @@ suite = do test "Tx confirmation fails after timeout (awaitTxConfirmedWithTimeout)" do let distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 1_000_000_000 ] + [ BigNum.fromInt 1_000_000_000 ] withWallets distribution \_ -> AwaitTxConfirmedWithTimeout.contract @@ -510,20 +527,20 @@ suite = do distribution :: InitialUTxOs /\ InitialUTxOs /\ InitialUTxOs /\ InitialUTxOs distribution = - [ BigInt.fromInt 20_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 20_000_000 + , BigNum.fromInt 20_000_000 ] /\ - [ BigInt.fromInt 20_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 20_000_000 + , BigNum.fromInt 20_000_000 ] /\ - [ BigInt.fromInt 20_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 20_000_000 + , BigNum.fromInt 20_000_000 ] /\ - [ BigInt.fromInt 20_000_000 - , BigInt.fromInt 20_000_000 + [ BigNum.fromInt 20_000_000 + , BigNum.fromInt 20_000_000 ] withWallets distribution \(alice /\ bob /\ charlie /\ dan) -> do @@ -551,32 +568,28 @@ suite = do constraints :: TxConstraints constraints = Constraints.mustPayToNativeScript nsHash $ Value.lovelaceValueOf - $ BigInt.fromInt 10_000_000 + $ BigNum.fromInt 10_000_000 lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty txId <- submit bsTx awaitTxConfirmed txId pure txId -- Bob attempts to unlock and send Ada to Charlie withKeyWallet bob do -- First, he should find the transaction input where Ada is locked - networkId <- getNetworkId - let - nsAddr = nativeScriptHashEnterpriseAddress networkId nsHash - nsAddrPlutus <- liftContractM "Unable to convert to Plutus address" - $ toPlutusAddress nsAddr - utxos <- utxosAt nsAddrPlutus + nsAddr <- mkAddress (wrap $ ScriptHashCredential nsHash) Nothing + utxos <- utxosAt nsAddr txInput <- liftContractM "Unable to get UTxO" $ view _input <$> lookupTxHash txId utxos !! 0 let constraints :: TxConstraints constraints = Constraints.mustPayToPubKey (coerce alicePaymentPKH) - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) <> Constraints.mustSpendNativeScriptOutput txInput nativeScript @@ -594,8 +607,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = Lookups.unspentOutputs utxos - ubTx <- mkUnbalancedTx lookups constraints - tx <- signTransaction =<< balanceTx ubTx + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + tx <- signTransaction =<< balanceTx ubTx usedUtxos mempty let signWithWallet txToSign wallet = withKeyWallet wallet (signTransaction txToSign) @@ -607,20 +620,20 @@ suite = do distribution :: InitialUTxOs /\ InitialUTxOs /\ InitialUTxOs /\ InitialUTxOs distribution = - [ BigInt.fromInt 50_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 50_000_000 + , BigNum.fromInt 50_000_000 ] /\ - [ BigInt.fromInt 50_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 50_000_000 + , BigNum.fromInt 50_000_000 ] /\ - [ BigInt.fromInt 50_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 50_000_000 + , BigNum.fromInt 50_000_000 ] /\ - [ BigInt.fromInt 50_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 50_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \(alice /\ bob /\ charlie /\ dan) -> do @@ -648,13 +661,13 @@ suite = do constraints :: TxConstraints constraints = Constraints.mustPayToNativeScript nsHash $ Value.lovelaceValueOf - $ BigInt.fromInt 10_000_000 + $ BigNum.fromInt 10_000_000 lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty txId <- submit bsTx awaitTxConfirmed txId pure txId @@ -662,28 +675,24 @@ suite = do -- Bob attempts to unlock and send Ada to Charlie withKeyWallet bob do -- First, he should find the transaction input where Ada is locked - networkId <- getNetworkId - let - nsAddr = nativeScriptHashEnterpriseAddress networkId nsHash - nsAddrPlutus <- liftContractM "Unable to convert to Plutus address" - $ toPlutusAddress nsAddr - utxos <- utxosAt nsAddrPlutus + nsAddr <- mkAddress (wrap $ ScriptHashCredential nsHash) Nothing + utxos <- utxosAt nsAddr txInput <- liftContractM "Unable to get UTxO" $ view _input <$> lookupTxHash txId utxos !! 0 let constraints :: TxConstraints constraints = Constraints.mustPayToPubKey (coerce alicePaymentPKH) - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) <> Constraints.mustSpendNativeScriptOutput txInput nativeScript lookups :: Lookups.ScriptLookups lookups = Lookups.unspentOutputs utxos - ubTx <- mkUnbalancedTx lookups constraints + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints -- Bob signs the tx - tx <- signTransaction =<< balanceTx ubTx + tx <- signTransaction =<< balanceTx ubTx usedUtxos mempty let signWithWallet txToSign wallet = withKeyWallet wallet (signTransaction txToSign) @@ -695,53 +704,53 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do mp <- alwaysMintsPolicy - let cs = Value.scriptCurrencySymbol mp + let cs = PlutusScript.hash mp tn <- liftContractM "Cannot make token name" - $ Value.mkTokenName + $ AssetName.mkAssetName =<< byteArrayFromAscii "TheToken" let constraints :: Constraints.TxConstraints constraints = Constraints.mustMintValue - $ Value.singleton cs tn - $ BigInt.fromInt 100 + $ Mint.singleton cs tn + $ Int.fromInt 100 lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp + lookups = Lookups.plutusMintingPolicy mp - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty submitAndLog bsTx test "mustProduceAtLeast spends native token" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do mp <- alwaysMintsPolicy - _ /\ cs <- mkCurrencySymbol alwaysMintsPolicy - tn <- mkTokenName "TheToken" + let cs = PlutusScript.hash mp + tn <- mkAssetName "TheToken" -- Minting let constraints :: Constraints.TxConstraints constraints = Constraints.mustMintValue - $ Value.singleton cs tn - $ BigInt.fromInt 100 + $ Mint.singleton cs tn + $ Int.fromInt 100 lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp + lookups = Lookups.plutusMintingPolicy mp txHash <- submitTxFromConstraints lookups constraints awaitTxConfirmed txHash @@ -755,7 +764,7 @@ suite = do constraints' :: Constraints.TxConstraints constraints' = Constraints.mustProduceAtLeast $ Value.singleton cs tn - $ BigInt.fromInt 100 + $ BigNum.fromInt 100 lookups' = lookups <> Lookups.ownPaymentPubKeyHash pkh txHash' <- submitTxFromConstraints lookups' constraints' @@ -765,25 +774,25 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do mp <- alwaysMintsPolicy - _ /\ cs <- mkCurrencySymbol alwaysMintsPolicy - tn <- mkTokenName "TheToken" + let cs = PlutusScript.hash mp + tn <- mkAssetName "TheToken" -- Minting let constraints :: Constraints.TxConstraints constraints = Constraints.mustMintValue - $ Value.singleton cs tn - $ BigInt.fromInt 100 + $ Mint.singleton cs tn + $ Int.fromInt 100 lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp + lookups = Lookups.plutusMintingPolicy mp txHash <- submitTxFromConstraints lookups constraints awaitTxConfirmed txHash @@ -797,36 +806,36 @@ suite = do constraints' :: Constraints.TxConstraints constraints' = Constraints.mustProduceAtLeast $ Value.singleton cs tn - $ BigInt.fromInt 101 + $ BigNum.fromInt 101 lookups' = lookups <> Lookups.ownPaymentPubKeyHash pkh - ubTx <- mkUnbalancedTx lookups' constraints' - result <- balanceTxE ubTx + ubTx /\ usedUtxos <- mkUnbalancedTx lookups' constraints' + result <- balanceTxE ubTx usedUtxos mempty result `shouldSatisfy` isLeft test "mustSpendAtLeast succeeds to spend" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do mp <- alwaysMintsPolicy - _ /\ cs <- mkCurrencySymbol alwaysMintsPolicy - tn <- mkTokenName "TheToken" + let cs = PlutusScript.hash mp + tn <- mkAssetName "TheToken" -- Minting let constraints :: Constraints.TxConstraints constraints = Constraints.mustMintValue - $ Value.singleton cs tn - $ BigInt.fromInt 100 + $ Mint.singleton cs tn + $ Int.fromInt 100 lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp + lookups = Lookups.plutusMintingPolicy mp txHash <- submitTxFromConstraints lookups constraints awaitTxConfirmed txHash @@ -840,7 +849,7 @@ suite = do constraints' :: Constraints.TxConstraints constraints' = Constraints.mustSpendAtLeast $ Value.singleton cs tn - $ BigInt.fromInt 100 + $ BigNum.fromInt 100 lookups' = lookups <> Lookups.ownPaymentPubKeyHash pkh txHash' <- submitTxFromConstraints lookups' constraints' @@ -850,25 +859,25 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do mp <- alwaysMintsPolicy - _ /\ cs <- mkCurrencySymbol alwaysMintsPolicy - tn <- mkTokenName "TheToken" + let cs = PlutusScript.hash mp + tn <- mkAssetName "TheToken" -- Minting let constraints :: Constraints.TxConstraints constraints = Constraints.mustMintValue - $ Value.singleton cs tn - $ BigInt.fromInt 100 + $ Mint.singleton cs tn + $ Int.fromInt 100 lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp + lookups = Lookups.plutusMintingPolicy mp txHash <- submitTxFromConstraints lookups constraints awaitTxConfirmed txHash @@ -882,19 +891,19 @@ suite = do constraints' :: Constraints.TxConstraints constraints' = Constraints.mustSpendAtLeast $ Value.singleton cs tn - $ BigInt.fromInt 101 + $ BigNum.fromInt 101 lookups' = lookups <> Lookups.ownPaymentPubKeyHash pkh - ubTx <- mkUnbalancedTx lookups' constraints' - result <- balanceTxE ubTx + ubTx /\ usedUtxos <- mkUnbalancedTx lookups' constraints' + result <- balanceTxE ubTx usedUtxos mempty result `shouldSatisfy` isLeft test "Minting using NativeScript (multisig) as a policy" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice NativeScriptMints.contract @@ -903,7 +912,8 @@ suite = do withWallets unit \_ -> do let mkDatumHash :: String -> DataHash - mkDatumHash = wrap <<< hexToByteArrayUnsafe + mkDatumHash str = unsafePartial $ fromJust $ decodeCbor <<< wrap =<< + hexToByteArray str -- Nothing is expected, because we are in an empty chain. -- This test only checks for ability to connect to the datum-querying -- backend. @@ -924,38 +934,36 @@ suite = do "e8cb7d18e81b0be160c114c563c020dcc7bf148a1994b73912db3ea1318d488b" ] - test "GetDatumsByHashes" do + -- FIXME: script integrity hash mismatch + skip $ test "GetDatumsByHashes" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] - datum1 :: Datum - datum1 = Datum $ Integer $ BigInt.fromInt 1 + datum1 = Integer $ BigInt.fromInt 1 - datum2 :: Datum - datum2 = Datum $ Integer $ BigInt.fromInt 2 + datum2 = Integer $ BigInt.fromInt 2 - datums :: Array Datum + datums :: Array PlutusData datums = [ datum2, datum1 ] let payToTest :: ValidatorHash -> Contract TransactionHash payToTest vhash = do let - constraints = - Constraints.mustPayToScript - vhash - datum1 - Constraints.DatumWitness - (Value.lovelaceValueOf $ BigInt.fromInt 1_000_000) - <> Constraints.mustPayToScript - vhash - datum2 + constraints = mconcat + [ Constraints.mustPayToScript vhash datum1 + Constraints.DatumWitness + (Value.lovelaceValueOf $ BigNum.fromInt 1_000_000) + , Constraints.mustPayToScript vhash datum2 Constraints.DatumWitness - (Value.lovelaceValueOf $ BigInt.fromInt 1_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 1_000_000) + , Constraints.mustIncludeDatum datum1 + , Constraints.mustIncludeDatum datum2 + ] lookups :: Lookups.ScriptLookups lookups = mempty @@ -993,21 +1001,21 @@ suite = do test "GetScriptByHash" do let distribution :: InitialUTxOs - distribution = [ BigInt.fromInt 50_000_000 ] + distribution = [ BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do validator1 <- AlwaysSucceeds.alwaysSucceedsScript validator2 <- alwaysSucceedsScriptV2 let - validatorRef1 = PlutusScriptRef $ unwrap validator1 - validatorRef2 = PlutusScriptRef $ unwrap validator2 + validatorRef1 = PlutusScriptRef validator1 + validatorRef2 = PlutusScriptRef validator2 useScriptAndGetByHash validator vhash = do txId <- AlwaysSucceeds.payToAlwaysSucceeds vhash awaitTxConfirmed txId -- Spending utxo, to make Kupo (used inside) see the script AlwaysSucceeds.spendFromAlwaysSucceeds vhash validator txId - getScriptByHash $ unwrap vhash + getScriptByHash vhash result1 <- useScriptAndGetByHash validator1 (validatorHash validator1) result2 <- useScriptAndGetByHash validator2 (validatorHash validator2) @@ -1018,8 +1026,8 @@ suite = do -- Testing getScriptsByHashes let - scriptHash1 = unwrap (validatorHash validator1) - scriptHash2 = unwrap (validatorHash validator2) + scriptHash1 = validatorHash validator1 + scriptHash2 = validatorHash validator2 results <- getScriptsByHashes [ scriptHash1, scriptHash2 ] results `shouldEqual` Map.fromFoldable [ (scriptHash1 /\ (Right (Just validatorRef1))) @@ -1029,7 +1037,7 @@ suite = do test "Getting transaction metadata" do let distribution :: InitialUTxOs - distribution = [ BigInt.fromInt 50_000_000 ] + distribution = [ BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1039,42 +1047,47 @@ suite = do lookups :: Lookups.ScriptLookups lookups = mempty - givenMetadata = GeneralTransactionMetadata $ Map.fromFoldable - [ TransactionMetadatumLabel (BigInt.fromInt 8) /\ Text "foo" ] - ubTx <- mkUnbalancedTx lookups constraints - ubTx' <- setGeneralTxMetadata ubTx givenMetadata - bsTx <- signTransaction =<< balanceTx ubTx' + givenMetadata :: GeneralTransactionMetadata + givenMetadata = + wrap $ Map.fromFoldable + [ BigNum.fromInt 8 /\ Metadatum.Text "foo" ] + + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + let ubTx' = setGeneralTxMetadata ubTx givenMetadata + bsTx <- signTransaction =<< balanceTx ubTx' usedUtxos mempty txId <- submit bsTx awaitTxConfirmed txId - mMetadata <- getTxMetadata txId - mMetadata `shouldEqual` Right givenMetadata + mMetadata <- map (_.metadata <<< unwrap) <$> getTxAuxiliaryData txId + mMetadata `shouldEqual` Right (Just givenMetadata) test "Minting zero of a token fails" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do - tn1 <- mkTokenName "Token name" - mp1 /\ _ <- mkCurrencySymbol alwaysMintsPolicy - mp2 /\ _ <- mkCurrencySymbol alwaysMintsPolicyV2 + tn1 <- mkAssetName "Token name" + mp1 <- alwaysMintsPolicy + mp2 <- alwaysMintsPolicyScriptV2 let constraints :: Constraints.TxConstraints constraints = mconcat - [ Constraints.mustMintCurrency (mintingPolicyHash mp1) tn1 zero - , Constraints.mustMintCurrency (mintingPolicyHash mp2) tn1 one + [ Constraints.mustMintCurrency (PlutusScript.hash mp1) tn1 + Int.zero + , Constraints.mustMintCurrency (PlutusScript.hash mp2) tn1 + Int.one ] lookups :: Lookups.ScriptLookups lookups = - Lookups.mintingPolicy mp1 <> Lookups.mintingPolicy mp2 + Lookups.plutusMintingPolicy mp1 <> Lookups.plutusMintingPolicy mp2 result <- mkUnbalancedTxE lookups constraints result `shouldSatisfy` isLeft @@ -1082,47 +1095,57 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do - tn1 <- mkTokenName "Token with a long name" - tn2 <- mkTokenName "Token" - mp1 /\ cs1 <- mkCurrencySymbol mintingPolicyRdmrInt1 - mp2 /\ cs2 <- mkCurrencySymbol mintingPolicyRdmrInt2 - mp3 /\ cs3 <- mkCurrencySymbol mintingPolicyRdmrInt3 + tn1 <- mkAssetName "Token with a long name" + tn2 <- mkAssetName "Token" + mp1 <- mintingPolicyRdmrInt1 + mp2 <- mintingPolicyRdmrInt2 + mp3 <- mintingPolicyRdmrInt3 + let + cs1 = PlutusScript.hash mp1 + cs2 = PlutusScript.hash mp2 + cs3 = PlutusScript.hash mp3 let constraints :: Constraints.TxConstraints - constraints = mconcat + constraints = mconcat $ unsafePartial [ Constraints.mustMintValueWithRedeemer - (Redeemer $ Integer (BigInt.fromInt 1)) - (Value.singleton cs1 tn1 one <> Value.singleton cs1 tn2 one) + (RedeemerDatum $ Integer (BigInt.fromInt 1)) + ( Mint.singleton cs1 tn1 Int.one <> Mint.singleton cs1 tn2 + Int.one + ) , Constraints.mustMintValueWithRedeemer - (Redeemer $ Integer (BigInt.fromInt 2)) - (Value.singleton cs2 tn1 one <> Value.singleton cs2 tn2 one) + (RedeemerDatum $ Integer (BigInt.fromInt 2)) + ( Mint.singleton cs2 tn1 Int.one <> Mint.singleton cs2 tn2 + Int.one + ) , Constraints.mustMintValueWithRedeemer - (Redeemer $ Integer (BigInt.fromInt 3)) - (Value.singleton cs3 tn1 one <> Value.singleton cs3 tn2 one) + (RedeemerDatum $ Integer (BigInt.fromInt 3)) + ( Mint.singleton cs3 tn1 Int.one <> Mint.singleton cs3 tn2 + Int.one + ) ] lookups :: Lookups.ScriptLookups lookups = - Lookups.mintingPolicy mp1 - <> Lookups.mintingPolicy mp2 - <> Lookups.mintingPolicy mp3 + Lookups.plutusMintingPolicy mp1 + <> Lookups.plutusMintingPolicy mp2 + <> Lookups.plutusMintingPolicy mp3 - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty submitAndLog bsTx test "Multi-signature transaction" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do checkUtxoDistribution distribution alice @@ -1131,8 +1154,8 @@ suite = do test "Multi-signature transaction with BaseAddresses" do let aliceUtxos = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] distribution = withStakeKey privateStakeKey aliceUtxos withWallets distribution \alice -> do @@ -1143,8 +1166,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 10_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 10_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> withKeyWallet alice $ AdditionalUtxos.contract false @@ -1153,8 +1176,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 10_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 10_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> withKeyWallet alice $ AdditionalUtxos.contract true @@ -1165,8 +1188,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1184,8 +1207,8 @@ suite = do let distribution :: InitialUTxOsWithStakeKey distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1207,8 +1230,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice SendsToken.contract @@ -1216,7 +1239,7 @@ suite = do test "PlutusV1 forces balancer to select non-PlutusV2 inputs" do let distribution :: InitialUTxOs - distribution = [ BigInt.fromInt 5_000_000 ] + distribution = [ BigNum.fromInt 5_000_000 ] withWallets distribution \alice -> do alicePkh <- withKeyWallet alice do @@ -1226,23 +1249,27 @@ suite = do let vhash = validatorHash validator - scriptAddress = scriptHashAddress vhash Nothing + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing + aliceAddress <- mkAddress + (wrap $ PubKeyHashCredential $ unwrap alicePkh) + Nothing let - datum42 = Datum $ Integer $ BigInt.fromInt 42 + datum42 = Integer $ BigInt.fromInt 42 datum42Hash = datumHash datum42 datum42Lookup = Lookups.datum datum42 let transactionId :: TransactionHash - transactionId = TransactionHash $ hexToByteArrayUnsafe - "a6b656487601c390a3bb61958c62369cb5d5a7597a68a9dccedb3dd68a60bfdd" + transactionId = TransactionHash $ unsafePartial $ fromJust $ fromBytes + $ hexToByteArrayUnsafe + "a6b656487601c390a3bb61958c62369cb5d5a7597a68a9dccedb3dd68a60bfdd" mkUtxo :: UInt -> Address -> Value - -> OutputDatum + -> Maybe OutputDatum -> TransactionUnspentOutput mkUtxo index address amount datum = TransactionUnspentOutput @@ -1250,27 +1277,24 @@ suite = do { index , transactionId } - , output: TransactionOutputWithRefScript - { scriptRef: Nothing - , output: TransactionOutput - { address - , amount - , datum - , referenceScript: Nothing - } + , output: TransactionOutput + { address + , amount + , datum + , scriptRef: Nothing } } - aliceUtxo :: OutputDatum -> TransactionUnspentOutput + aliceUtxo :: Maybe OutputDatum -> TransactionUnspentOutput aliceUtxo = mkUtxo zero - (pubKeyHashAddress alicePkh Nothing) - (Value.lovelaceValueOf $ BigInt.fromInt 50_000_000) + aliceAddress + (Value.lovelaceValueOf $ BigNum.fromInt 50_000_000) alwaysSucceedsUtxo :: TransactionUnspentOutput alwaysSucceedsUtxo = mkUtxo one scriptAddress - (Value.lovelaceValueOf $ BigInt.fromInt 2_000_000) - (OutputDatumHash datum42Hash) + (Value.lovelaceValueOf $ BigNum.fromInt 2_000_000) + (Just $ OutputDatumHash datum42Hash) -- Balance a transaction which requires selecting a utxo with a -- certain datum @@ -1282,7 +1306,7 @@ suite = do [ alwaysSucceedsUtxo, aliceUtxo datum ] value :: Value.Value - value = Value.lovelaceValueOf $ BigInt.fromInt 50_000_000 + value = Value.lovelaceValueOf $ BigNum.fromInt 50_000_000 constraints :: TxConstraints constraints = fold @@ -1303,8 +1327,8 @@ suite = do balanceTxConstraints = BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx <- mkUnbalancedTx lookups constraints - balanceTxWithConstraintsE unbalancedTx balanceTxConstraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTxE unbalancedTx usedUtxos balanceTxConstraints let hasInsufficientBalance @@ -1313,16 +1337,16 @@ suite = do Left (BalanceInsufficientError _ _) -> true _ -> false - balanceWithDatum NoOutputDatum >>= flip shouldSatisfy isRight - balanceWithDatum (OutputDatum datum42) >>= flip shouldSatisfy + balanceWithDatum Nothing >>= flip shouldSatisfy isRight + balanceWithDatum (Just $ OutputDatum datum42) >>= flip shouldSatisfy hasInsufficientBalance test "InlineDatum" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1339,8 +1363,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1356,8 +1380,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1373,8 +1397,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1393,8 +1417,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1414,8 +1438,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> withKeyWallet alice PaysWithDatum.contract @@ -1424,8 +1448,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1441,8 +1465,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1455,39 +1479,45 @@ suite = do AlwaysSucceeds.spendFromAlwaysSucceeds vhash validator txId group "CIP-40 Collateral Output" do - test "Always failing script triggers Collateral Return (ADA-only)" do - let - distribution :: InitialUTxOs /\ InitialUTxOs - distribution = - [ BigInt.fromInt 10_000_000 - , BigInt.fromInt 50_000_000 - ] /\ [ BigInt.fromInt 50_000_000 ] - withWallets distribution \(alice /\ seed) -> do - validator <- AlwaysFails.alwaysFailsScript - let vhash = validatorHash validator - txId <- withKeyWallet seed do - logInfo' "Attempt to lock value" - txId <- AlwaysFails.payToAlwaysFails vhash - awaitTxConfirmed txId - pure txId + skip $ test + "Always failing script triggers Collateral Return (ADA-only) UNSKIP AFTER CONWAY" + do + let + distribution :: InitialUTxOs /\ InitialUTxOs + distribution = + [ BigNum.fromInt 10_000_000 + , BigNum.fromInt 50_000_000 + ] /\ [ BigNum.fromInt 50_000_000 ] + withWallets distribution \(alice /\ seed) -> do + validator <- AlwaysFails.alwaysFailsScript + let vhash = validatorHash validator + txId <- withKeyWallet seed do + logInfo' "Attempt to lock value" + txId <- AlwaysFails.payToAlwaysFails vhash + awaitTxConfirmed txId + pure txId - withKeyWallet alice do - awaitTxConfirmed txId - logInfo' "Try to spend locked values" - balanceBefore <- fold <$> getWalletBalance - AlwaysFails.spendFromAlwaysFails vhash validator txId - balance <- fold <$> getWalletBalance - let - collateralLoss = Value.lovelaceValueOf $ BigInt.fromInt $ - -5_000_000 - balance `shouldEqual` (balanceBefore <> collateralLoss) + withKeyWallet alice do + awaitTxConfirmed txId + logInfo' "Try to spend locked values" + balanceBefore <- unsafePartial $ fold <$> getWalletBalance + AlwaysFails.spendFromAlwaysFails vhash validator txId + balance <- unsafePartial $ fold <$> getWalletBalance + let + collateralLoss = Value.lovelaceValueOf $ BigNum.fromInt $ + 5_000_000 + balance `shouldEqual` + ( unsafePartial $ fromJust $ balanceBefore `Value.minus` + collateralLoss + ) - test "AlwaysFails script triggers Native Asset Collateral Return (tokens)" + skip $ test + "AlwaysFails script triggers Native Asset Collateral Return (tokens) UNSKIP AFTER CONWAY" do let distribution :: InitialUTxOs /\ InitialUTxOs distribution = - [] /\ [ BigInt.fromInt 2_100_000_000 ] + [] /\ [ BigNum.fromInt 2_100_000_000 ] withWallets distribution \(alice /\ seed) -> do alicePkh /\ aliceStakePkh <- withKeyWallet alice do pkh <- liftedM "Failed to get PKH" $ head <$> @@ -1496,10 +1526,12 @@ suite = do pure $ pkh /\ stakePkh mp <- alwaysMintsPolicy - let cs = Value.scriptCurrencySymbol mp + let cs = PlutusScript.hash mp tn <- liftContractM "Cannot make token name" - $ byteArrayFromAscii "TheToken" >>= Value.mkTokenName - let asset = Value.singleton cs tn $ BigInt.fromInt 50 + $ byteArrayFromAscii "TheToken" >>= AssetName.mkAssetName + let + asset = Value.singleton cs tn $ BigNum.fromInt 50 + mint = Mint.singleton cs tn $ Int.fromInt 50 validator <- AlwaysFails.alwaysFailsScript let vhash = validatorHash validator @@ -1508,21 +1540,22 @@ suite = do logInfo' "Minting asset to Alice" let constraints :: Constraints.TxConstraints - constraints = Constraints.mustMintValue (asset <> asset) - <> mustPayToPubKeyStakeAddress alicePkh aliceStakePkh - ( asset <> - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) - ) - <> mustPayToPubKeyStakeAddress alicePkh aliceStakePkh - ( asset <> - (Value.lovelaceValueOf $ BigInt.fromInt 50_000_000) - ) + constraints = + Constraints.mustMintValue (unsafePartial $ mint <> mint) + <> mustPayToPubKeyStakeAddress alicePkh aliceStakePkh + ( unsafePartial $ asset <> + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) + ) + <> mustPayToPubKeyStakeAddress alicePkh aliceStakePkh + ( unsafePartial $ asset <> + (Value.lovelaceValueOf $ BigNum.fromInt 50_000_000) + ) lookups :: Lookups.ScriptLookups - lookups = Lookups.mintingPolicy mp + lookups = Lookups.plutusMintingPolicy mp - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty submit bsTx >>= awaitTxConfirmed logInfo' "Attempt to lock value" @@ -1535,56 +1568,24 @@ suite = do logInfo' "Try to spend locked values" AlwaysFails.spendFromAlwaysFails vhash validator txId - group "CIP-33 Reference Scripts" do - test "Use reference scripts for spending" do - let - distribution :: InitialUTxOs - distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 - ] - withWallets distribution \alice -> - withKeyWallet alice ReferenceScripts.contract - - test - "Use reference scripts for spending (with Base Address, testing `mustPayToScriptAddressWithScriptRef`)" + group "CIP-33 Reference Scripts + CIP-31 Reference Inputs" do + test "Use reference inputs and reference scripts at the same time" do let - distribution :: InitialUTxOsWithStakeKey - distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + distribution :: InitialUTxOs + distribution = + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> - withKeyWallet alice ReferenceScripts.contract - - group "CIP-31 Reference Inputs" do - test "Use reference inputs" do - let - distribution :: InitialUTxOs - distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 - ] - withWallets distribution \alice -> - withKeyWallet alice ReferenceInputs.contract - - test "Use reference inputs and reference scripts at the same time" do - let - distribution :: InitialUTxOs - distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 - ] - withWallets distribution \alice -> - withKeyWallet alice ReferenceInputsAndScripts.contract + withKeyWallet alice ReferenceInputsAndScripts.contract test "One-Shot Minting example" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> withKeyWallet alice OneShotMinting.contract @@ -1593,8 +1594,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> withKeyWallet alice OneShotMintingV2.contract @@ -1603,7 +1604,7 @@ suite = do let initialUtxos :: InitialUTxOs initialUtxos = - [ BigInt.fromInt 50_000_000, BigInt.fromInt 50_000_000 ] + [ BigNum.fromInt 50_000_000, BigNum.fromInt 50_000_000 ] distribution :: InitialUTxOs /\ InitialUTxOs distribution = initialUtxos /\ initialUtxos @@ -1613,20 +1614,19 @@ suite = do head <$> withKeyWallet bob ownPaymentPubKeyHashes receiverSkh <- join <<< head <$> withKeyWallet bob ownStakePubKeyHashes - mintingPolicy /\ cs <- mkCurrencySymbol alwaysMintsPolicyV2 - - tn <- mkTokenName "TheToken" + mintingPolicy <- alwaysMintsPolicyScriptV2 + let cs = PlutusScript.hash mintingPolicy + tn <- mkAssetName "TheToken" withKeyWallet alice do let params = { receiverPkh , receiverSkh - , adaToSend: BigInt.fromInt 5_000_000 + , adaToSend: Coin.fromInt 5_000_000 , mintingPolicy - , tokensToMint: cs /\ tn /\ one /\ unit - , datumToAttach: wrap $ Integer $ BigInt.fromInt 42 - , txMetadata: cip25MetadataFixture1 + , tokensToMint: cs /\ tn /\ BigNum.one /\ unit + , datumToAttach: Integer $ BigInt.fromInt 42 } checks <- ContractTestUtils.mkChecks params @@ -1637,7 +1637,7 @@ suite = do let initialUtxos :: InitialUTxOs initialUtxos = - [ BigInt.fromInt 50_000_000, BigInt.fromInt 50_000_000 ] + [ BigNum.fromInt 50_000_000, BigNum.fromInt 50_000_000 ] distribution :: InitialUTxOs /\ InitialUTxOs distribution = initialUtxos /\ initialUtxos @@ -1654,7 +1654,7 @@ suite = do test "Tx chain submits (TxChaining example)" $ let distribution :: InitialUTxOs - distribution = [ BigInt.fromInt 2_500_000 ] + distribution = [ BigNum.fromInt 2_500_000 ] in withWallets distribution \alice -> withKeyWallet alice TxChaining.contract @@ -1666,7 +1666,7 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 150_000_000 ] + [ BigNum.fromInt 150_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1679,44 +1679,44 @@ suite = do Constraints.mustPayToPubKeyWithScriptRef pkh (NativeScriptRef nativeScriptFixture1) - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) <> Constraints.mustPayToPubKeyWithScriptRef pkh (NativeScriptRef nativeScriptFixture2) - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) <> Constraints.mustPayToPubKeyWithScriptRef pkh (NativeScriptRef nativeScriptFixture3) - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) <> Constraints.mustPayToPubKeyWithScriptRef pkh (NativeScriptRef nativeScriptFixture4) - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) <> Constraints.mustPayToPubKeyWithScriptRef pkh (NativeScriptRef nativeScriptFixture5) - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) <> Constraints.mustPayToPubKeyWithScriptRef pkh (NativeScriptRef nativeScriptFixture6) - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) <> Constraints.mustPayToPubKeyWithScriptRef pkh (NativeScriptRef nativeScriptFixture7) - (Value.lovelaceValueOf $ BigInt.fromInt 10_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 10_000_000) lookups0 :: Lookups.ScriptLookups lookups0 = mempty - unbalancedTx0 <- mkUnbalancedTx lookups0 constraints0 + unbalancedTx0 /\ usedUtxos0 <- mkUnbalancedTx lookups0 constraints0 - withBalancedTx unbalancedTx0 \balancedTx0 -> do + withBalancedTx unbalancedTx0 usedUtxos0 mempty \balancedTx0 -> do balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 @@ -1728,7 +1728,7 @@ suite = do constraints1 :: TxConstraints constraints1 = Constraints.mustPayToPubKey pkh - (Value.lovelaceValueOf $ BigInt.fromInt 70_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 70_000_000) lookups1 :: Lookups.ScriptLookups lookups1 = Lookups.unspentOutputs additionalUtxos @@ -1738,8 +1738,9 @@ suite = do balanceTxConstraints = BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx1 <- mkUnbalancedTx lookups1 constraints1 - balancedTx1 <- balanceTxWithConstraints unbalancedTx1 + unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups1 + constraints1 + balancedTx1 <- balanceTx unbalancedTx1 usedUtxos1 balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 @@ -1758,7 +1759,7 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 150_000_000 ] + [ BigNum.fromInt 150_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -1768,35 +1769,29 @@ suite = do wUtxos0 <- liftedM "Failed to get wallet UTXOs" getWalletUtxos logInfo' $ "wUtxos0 " <> show wUtxos0 - mp <- alwaysMintsPolicyV2 - let cs = Value.scriptCurrencySymbol mp + mp <- alwaysMintsPolicyScriptV2 + let cs = PlutusScript.hash mp tn <- liftContractM "Cannot make token name" - $ byteArrayFromAscii "TheToken" >>= Value.mkTokenName + $ byteArrayFromAscii "TheToken" >>= AssetName.mkAssetName validatorV1 <- AlwaysSucceeds.alwaysSucceedsScript validatorV2 <- alwaysSucceedsScriptV2 let - value :: Value.Value + value :: Value value = - (Value.lovelaceValueOf $ BigInt.fromInt 60_000_000) + (Value.lovelaceValueOf $ BigNum.fromInt 60_000_000) - value' :: Value.Value + value' :: Value value' = - value - <> (Value.singleton cs tn $ BigInt.fromInt 50) + unsafePartial $ value + <> (Value.singleton cs tn $ BigNum.fromInt 50) scriptRefV1 :: ScriptRef - scriptRefV1 = PlutusScriptRef (unwrap validatorV1) + scriptRefV1 = PlutusScriptRef validatorV1 scriptRefV2 :: ScriptRef - scriptRefV2 = PlutusScriptRef (unwrap validatorV2) - - datum :: Datum - datum = Datum plutusData - - datum' :: Datum - datum' = Datum plutusData' + scriptRefV2 = PlutusScriptRef validatorV2 plutusData :: PlutusData plutusData = Integer $ BigInt.fromInt 31415927 @@ -1812,31 +1807,31 @@ suite = do constraints0 = Constraints.mustPayToPubKeyWithDatumAndScriptRef pkh - datum' + plutusData' Constraints.DatumWitness scriptRefV1 value <> Constraints.mustPayToPubKeyWithDatumAndScriptRef pkh - datum + plutusData Constraints.DatumInline scriptRefV2 value' <> Constraints.mustMintCurrency - (mintingPolicyHash mp) + (PlutusScript.hash mp) tn - (BigInt.fromInt 50) + (Int.fromInt 50) - let datumLookup = Lookups.datum datum' + let datumLookup = Lookups.datum plutusData' let lookups0 :: Lookups.ScriptLookups - lookups0 = Lookups.mintingPolicy mp <> datumLookup + lookups0 = Lookups.plutusMintingPolicy mp <> datumLookup - unbalancedTx0 <- mkUnbalancedTx lookups0 constraints0 + unbalancedTx0 /\ usedUtxos <- mkUnbalancedTx lookups0 constraints0 - withBalancedTx unbalancedTx0 \balancedTx0 -> do + withBalancedTx unbalancedTx0 usedUtxos mempty \balancedTx0 -> do balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 @@ -1847,9 +1842,9 @@ suite = do let constraints1 :: TxConstraints constraints1 = - Constraints.mustPayToPubKey pkh $ - Value.lovelaceValueOf (BigInt.fromInt 60_000_000) - <> Value.singleton cs tn (BigInt.fromInt 50) + Constraints.mustPayToPubKey pkh $ unsafePartial $ + Value.lovelaceValueOf (BigNum.fromInt 60_000_000) + <> Value.singleton cs tn (BigNum.fromInt 50) lookups1 :: Lookups.ScriptLookups lookups1 = Lookups.unspentOutputs additionalUtxos @@ -1859,8 +1854,9 @@ suite = do balanceTxConstraints = BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx1 <- mkUnbalancedTx lookups1 constraints1 - balancedTx1 <- balanceTxWithConstraints unbalancedTx1 + unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups1 + constraints1 + balancedTx1 <- balanceTx unbalancedTx1 usedUtxos1 balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 @@ -1874,17 +1870,17 @@ suite = do test "returns the same script when called without args" do withWallets unit \_ -> do result <- liftContractE $ applyArgs - (unwrap unappliedScriptFixture) + unappliedScriptFixture mempty - result `shouldEqual` (unwrap unappliedScriptFixture) + result `shouldEqual` unappliedScriptFixture test "returns the correct partially applied Plutus script" do withWallets unit \_ -> do let args = [ Integer (BigInt.fromInt 32) ] result <- liftContractE $ applyArgs - (unwrap unappliedScriptFixture) + unappliedScriptFixture args - result `shouldEqual` (unwrap partiallyAppliedScriptFixture) + result `shouldEqual` partiallyAppliedScriptFixture test "returns the correct fully applied Plutus script" do withWallets unit \_ -> do @@ -1893,59 +1889,71 @@ suite = do (byteArrayFromAscii "test") let args = [ Integer (BigInt.fromInt 32), Bytes bytes ] result <- liftContractE $ applyArgs - (unwrap unappliedScriptFixture) + unappliedScriptFixture args - result `shouldEqual` (unwrap fullyAppliedScriptFixture) + result `shouldEqual` fullyAppliedScriptFixture group "CIP-30 mock interface" do test "Wallet cleanup" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do - withCip30Mock alice MockNami do - (liftEffect $ isWalletAvailable NamiWallet) >>= shouldEqual true - try (liftEffect $ isWalletAvailable NamiWallet) >>= hush >>> shouldEqual + let nami = walletName Nami + withCip30Mock alice nami do + (liftEffect $ isWalletAvailable nami) >>= shouldEqual true + try (liftEffect $ isWalletAvailable nami) >>= hush >>> shouldEqual (Just false) - withCip30Mock alice MockGero do - (liftEffect $ isWalletAvailable GeroWallet) >>= shouldEqual true - try (liftEffect $ isWalletAvailable GeroWallet) >>= hush >>> shouldEqual - (Just false) + let gerowallet = walletName Gero + withCip30Mock alice gerowallet do + (liftEffect $ isWalletAvailable gerowallet) >>= shouldEqual true + try (liftEffect $ isWalletAvailable gerowallet) >>= hush >>> + shouldEqual + (Just false) - withCip30Mock alice MockFlint do - (liftEffect $ isWalletAvailable FlintWallet) >>= shouldEqual true - try (liftEffect $ isWalletAvailable FlintWallet) >>= hush >>> + let flint = walletName Flint + withCip30Mock alice flint do + (liftEffect $ isWalletAvailable flint) >>= shouldEqual true + try (liftEffect $ isWalletAvailable flint) >>= hush >>> shouldEqual (Just false) - withCip30Mock alice MockNuFi do - (liftEffect $ isWalletAvailable NuFiWallet) >>= shouldEqual true - try (liftEffect $ isWalletAvailable NuFiWallet) >>= hush >>> shouldEqual + let nufi = walletName NuFi + withCip30Mock alice nufi do + (liftEffect $ isWalletAvailable nufi) >>= shouldEqual true + try (liftEffect $ isWalletAvailable nufi) >>= hush >>> shouldEqual (Just false) + let lode = walletName Lode + withCip30Mock alice lode do + (liftEffect $ isWalletAvailable lode) >>= shouldEqual true + try (liftEffect $ isWalletAvailable lode) >>= hush >>> + shouldEqual + (Just false) + test "Collateral selection returns UTxO with smaller amount" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do - withCip30Mock alice MockNami do + withCip30Mock alice (walletName Nami) do getWalletCollateral >>= liftEffect <<< case _ of Nothing -> throw "Unable to get collateral" Just [ TransactionUnspentOutput - { output: TransactionOutputWithRefScript { output } } + { output } ] -> do let amount = (unwrap output).amount unless - (amount == lovelaceValueOf (BigInt.fromInt 50_000_000)) + (amount == lovelaceValueOf (BigNum.fromInt 50_000_000)) $ throw "Wrong UTxO selected as collateral" Just _ -> do throw $ "More than one UTxO in collateral. " <> @@ -1955,11 +1963,11 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do - utxos <- withCip30Mock alice MockNami do + utxos <- withCip30Mock alice (walletName Nami) do getWalletUtxos utxos `shouldSatisfy` isJust @@ -1967,11 +1975,11 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do - mockAddress <- withCip30Mock alice MockNami do + mockAddress <- withCip30Mock alice (walletName Nami) do mbAddr <- head <$> getWalletAddresses mbAddr `shouldSatisfy` isJust pure mbAddr @@ -1983,11 +1991,11 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do - withCip30Mock alice MockNami do + withCip30Mock alice (walletName Nami) do pkh <- liftedM "Failed to get PKH" $ head <$> ownPaymentPubKeyHashes stakePkh <- join <<< head <$> ownStakePubKeyHashes @@ -1997,63 +2005,159 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do getWalletBalance >>= shouldEqual - ( Just $ coinToValue $ Coin $ BigInt.fromInt 1_050_000_000 + ( Just $ coinToValue $ Coin $ BigNum.fromInt 1_050_000_000 ) - withCip30Mock alice MockNami do + withCip30Mock alice (walletName Nami) do getWalletBalance >>= shouldEqual - ( Just $ coinToValue $ Coin $ BigInt.fromInt 1_050_000_000 + ( Just $ coinToValue $ Coin $ BigNum.fromInt 1_050_000_000 ) test "getWalletBalance works (2)" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 5_000_000 - , BigInt.fromInt 2_000_000 - , BigInt.fromInt 1_000_000 + [ BigNum.fromInt 5_000_000 + , BigNum.fromInt 2_000_000 + , BigNum.fromInt 1_000_000 ] withWallets distribution \alice -> do - withCip30Mock alice MockNami do + withCip30Mock alice (walletName Nami) do getWalletBalance >>= flip shouldSatisfy - (eq $ Just $ coinToValue $ Coin $ BigInt.fromInt 8_000_000) + (eq $ Just $ coinToValue $ Coin $ BigNum.fromInt 8_000_000) + + test "ownDrepPubKey works" do + let + walletSpec :: TestWalletSpec + walletSpec = wrap + { utxos: + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 + ] + , stakeKey: Just privateStakeKey + , drepKey: Just privateDrepKey + } + withWallets walletSpec \alice -> + withCip30Mock alice (walletName Nami) $ + ownDrepPubKey `shouldReturn` + PrivateKey.toPublicKey (unwrap privateDrepKey) + + test "ownDrepPubKeyHash works" do + let + walletSpec :: TestWalletSpec + walletSpec = wrap + { utxos: + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 + ] + , stakeKey: Just privateStakeKey + , drepKey: Just privateDrepKey + } + withWallets walletSpec \alice -> + withCip30Mock alice (walletName Nami) $ + ownDrepPubKeyHash `shouldReturn` + PublicKey.hash (PrivateKey.toPublicKey $ unwrap privateDrepKey) + + test "ownRegisteredPubStakeKeys works" do + let + walletSpec :: TestWalletSpec + walletSpec = wrap + { utxos: + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 + ] + , stakeKey: Just privateStakeKey + , drepKey: Nothing + } + withWallets walletSpec \alice -> + withCip30Mock alice (walletName Nami) $ + ownRegisteredPubStakeKeys `shouldReturn` mempty + + test "ownUnregisteredPubStakeKeys works" do + let + walletSpec :: TestWalletSpec + walletSpec = wrap + { utxos: + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 + ] + , stakeKey: Just privateStakeKey + , drepKey: Nothing + } + withWallets walletSpec \alice -> + withCip30Mock alice (walletName Nami) $ + ownUnregisteredPubStakeKeys `shouldReturn` + Array.singleton (PrivateKey.toPublicKey $ unwrap privateStakeKey) + + test "signData using DRep key" do + let + walletSpec :: TestWalletSpec + walletSpec = wrap + { utxos: + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 + ] + , stakeKey: Just privateStakeKey + , drepKey: Just privateDrepKey + } + withWallets walletSpec \alice -> + withCip30Mock alice (walletName Nami) do + networkId <- getNetworkId + drepCred <- wrap <<< PubKeyHashCredential <$> ownDrepPubKeyHash + let + drepAddr = EnterpriseAddress + { networkId, paymentCredential: drepCred } + void $ signData drepAddr mempty + + test "signData fails for wrong address" do + let + distribution :: InitialUTxOs + distribution = + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 + ] + withWallets (distribution /\ distribution) \(alice /\ bob) -> do + bobAddr <- + withCip30Mock bob (walletName Nami) do + liftedM "Could not get Bob's address" (head <$> getWalletAddresses) + withCip30Mock alice (walletName Nami) do + expectError $ signData bobAddr mempty test "CIP-30 utilities" do let distribution :: InitialUTxOsWithStakeKey distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do - withCip30Mock alice MockNami do - Cip30.contract - withCip30Mock alice (MockGenericCip30 "nami") do + withCip30Mock alice (walletName Nami) do Cip30.contract + test "ECDSA example" do let distribution = withStakeKey privateStakeKey - [ BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 - , BigInt.fromInt 2_000_000_000 * BigInt.fromInt 100 + [ BigNum.fromInt 2_000_000_000 + , BigNum.fromInt 2_000_000_000 + , BigNum.fromInt 2_000_000_000 + , BigNum.fromInt 2_000_000_000 + , BigNum.fromInt 2_000_000_000 ] withWallets distribution \alice -> do - withCip30Mock alice MockNami $ ECDSA.contract + withCip30Mock alice (walletName Nami) $ ECDSA.contract group "CIP-49 Plutus Crypto Primitives" do test "ECDSA: a script that checks if a signature is correct" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -2062,8 +2166,8 @@ suite = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 50_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -2077,15 +2181,24 @@ signMultipleContract = do constraints :: Constraints.TxConstraints constraints = mustPayToPubKeyStakeAddress pkh stakePkh $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 + $ BigNum.fromInt 2_000_000 lookups :: Lookups.ScriptLookups lookups = mempty - ubTx1 <- mkUnbalancedTx lookups constraints - ubTx2 <- mkUnbalancedTx lookups constraints - - withBalancedTxs [ ubTx1, ubTx2 ] $ \txs -> do + ubTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups constraints + ubTx2 /\ usedUtxos2 <- mkUnbalancedTx lookups constraints + + withBalancedTxs + [ { transaction: ubTx1 + , usedUtxos: usedUtxos1 + , balancerConstraints: mempty + } + , { transaction: ubTx2 + , usedUtxos: usedUtxos2 + , balancerConstraints: mempty + } + ] $ \txs -> do locked <- getLockedInputs logInfo' $ "Locked inputs inside bracket (should be nonempty): " <> show locked @@ -2102,14 +2215,15 @@ pkh2PkhContract -> Maybe StakePubKeyHash -> Contract Unit pkh2PkhContract pkh stakePkh = do - let - constraints :: Constraints.TxConstraints - constraints = mustPayToPubKeyStakeAddress pkh stakePkh - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx - submitAndLog bsTx + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> stakePkh) + transaction <- buildTx + [ Pay $ TransactionOutput + { address + , amount: Value.coinToValue $ wrap $ BigNum.fromInt 2_000_000 + , datum: Nothing + , scriptRef: Nothing + } + ] + submitAndLog =<< signTransaction =<< balanceTx transaction Map.empty mempty diff --git a/test/Plutip/Contract/Assert.purs b/test/Testnet/Contract/Assert.purs similarity index 64% rename from test/Plutip/Contract/Assert.purs rename to test/Testnet/Contract/Assert.purs index 14fb3e5efd..2a1b933ce9 100644 --- a/test/Plutip/Contract/Assert.purs +++ b/test/Testnet/Contract/Assert.purs @@ -1,18 +1,20 @@ -- | Testing assertions interface provided by `Contract.Test.Assert` -module Test.Ctl.Plutip.Contract.Assert (suite) where +module Test.Ctl.Testnet.Contract.Assert (suite) where import Prelude +import Cardano.Types (ExUnits(ExUnits)) +import Cardano.Types.PlutusScript as PlutusScript import Contract.Monad (liftedM) +import Contract.Numeric.BigNum as BigNum import Contract.PlutusData (PlutusData(Integer)) -import Contract.Test (ContractTest) +import Contract.Test (ContractTest, InitialUTxOs, withWallets) import Contract.Test.Assert ( checkExUnitsNotExceed , collectAssertionFailures , printContractAssertionFailures ) import Contract.Test.Mote (TestPlanM) -import Contract.Test.Plutip (InitialUTxOs, withWallets) import Contract.Wallet ( ownPaymentPubKeyHashes , ownStakePubKeyHashes @@ -20,8 +22,8 @@ import Contract.Wallet ) import Control.Monad.Trans.Class (lift) import Ctl.Examples.ContractTestUtils as ContractTestUtils -import Ctl.Examples.Helpers (mkCurrencySymbol, mkTokenName) -import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyV2) +import Ctl.Examples.Helpers (mkAssetName) +import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) import Data.Array (head) import Data.Either (isLeft, isRight) import Data.Newtype (wrap) @@ -30,7 +32,7 @@ import Effect.Class (liftEffect) import Effect.Exception (throw) import JS.BigInt as BigInt import Mote (group, test) -import Test.Ctl.Fixtures (cip25MetadataFixture1) +import Partial.Unsafe (unsafePartial) import Test.Spec.Assertions (shouldEqual, shouldSatisfy) suite :: TestPlanM ContractTest Unit @@ -39,7 +41,7 @@ suite = do let initialUtxos :: InitialUTxOs initialUtxos = - [ BigInt.fromInt 2_000_000_000, BigInt.fromInt 2_000_000_000 ] + [ BigNum.fromInt 2_000_000_000, BigNum.fromInt 2_000_000_000 ] distribution :: InitialUTxOs /\ InitialUTxOs distribution = initialUtxos /\ initialUtxos @@ -51,20 +53,21 @@ suite = do head <$> withKeyWallet bob ownPaymentPubKeyHashes receiverSkh <- join <<< head <$> withKeyWallet bob ownStakePubKeyHashes - mintingPolicy /\ cs <- mkCurrencySymbol alwaysMintsPolicyV2 + mintingPolicy <- alwaysMintsPolicyScriptV2 - tn <- mkTokenName "TheToken" + let cs = PlutusScript.hash mintingPolicy + + tn <- mkAssetName "TheToken" withKeyWallet alice do let params = { receiverPkh , receiverSkh - , adaToSend: BigInt.fromInt 5_000_000 + , adaToSend: wrap $ BigNum.fromInt 5_000_000 , mintingPolicy - , tokensToMint: cs /\ tn /\ one /\ unit - , datumToAttach: wrap $ Integer $ BigInt.fromInt 42 - , txMetadata: cip25MetadataFixture1 + , tokensToMint: cs /\ tn /\ BigNum.one /\ unit + , datumToAttach: Integer $ BigInt.fromInt 42 } checks <- ContractTestUtils.mkChecks params @@ -80,29 +83,33 @@ suite = do head <$> withKeyWallet bob ownPaymentPubKeyHashes receiverSkh <- join <<< head <$> withKeyWallet bob ownStakePubKeyHashes - mintingPolicy /\ cs <- mkCurrencySymbol alwaysMintsPolicyV2 + mintingPolicy <- alwaysMintsPolicyScriptV2 + + let cs = PlutusScript.hash mintingPolicy - tn <- mkTokenName "TheToken" + tn <- mkAssetName "TheToken" withKeyWallet alice do let params = { receiverPkh , receiverSkh - , adaToSend: BigInt.fromInt 5_000_000 + , adaToSend: wrap $ BigNum.fromInt 5_000_000 , mintingPolicy - , tokensToMint: cs /\ tn /\ one /\ unit - , datumToAttach: wrap $ Integer $ BigInt.fromInt 42 - , txMetadata: cip25MetadataFixture1 + , tokensToMint: cs /\ tn /\ BigNum.one /\ unit + , datumToAttach: Integer $ BigInt.fromInt 42 } checks <- ContractTestUtils.mkChecks params - { tokensToMint = cs /\ tn /\ (one + one) /\ unit } + { tokensToMint = cs /\ tn + /\ (unsafePartial $ BigNum.one <> BigNum.one) + /\ unit + } eiResult /\ failures <- collectAssertionFailures checks $ lift do ContractTestUtils.mkContract params eiResult `shouldSatisfy` isRight printContractAssertionFailures failures `shouldEqual` - "In addition to the error above, the following `Contract` assertions have failed:\n\n 1. Unexpected token delta (TokenName (hexToRawBytesUnsafe \"546865546f6b656e\")) at address Sender Expected: 2, Actual: 1" + "In addition to the error above, the following `Contract` assertions have failed:\n\n 1. Unexpected token delta (mkAssetName (hexToByteArrayUnsafe \"546865546f6b656e\")) at address Sender Expected: 2, Actual: 1" test "ExUnits limit reached" do @@ -111,26 +118,28 @@ suite = do head <$> withKeyWallet bob ownPaymentPubKeyHashes receiverSkh <- join <<< head <$> withKeyWallet bob ownStakePubKeyHashes - mintingPolicy /\ cs <- mkCurrencySymbol alwaysMintsPolicyV2 + mintingPolicy <- alwaysMintsPolicyScriptV2 - tn <- mkTokenName "TheToken" + let cs = PlutusScript.hash mintingPolicy + + tn <- mkAssetName "TheToken" withKeyWallet alice do let params = { receiverPkh , receiverSkh - , adaToSend: BigInt.fromInt 5_000_000 + , adaToSend: wrap $ BigNum.fromInt 5_000_000 , mintingPolicy - , tokensToMint: cs /\ tn /\ one /\ unit - , datumToAttach: wrap $ Integer $ BigInt.fromInt 42 - , txMetadata: cip25MetadataFixture1 + , tokensToMint: cs /\ tn /\ BigNum.one /\ unit + , datumToAttach: Integer $ BigInt.fromInt 42 } checks <- ContractTestUtils.mkChecks params <#> ( _ <> [ checkExUnitsNotExceed - { mem: BigInt.fromInt 800, steps: BigInt.fromInt 16110 } + $ ExUnits + { mem: BigNum.fromInt 800, steps: BigNum.fromInt 16110 } ] ) eiResult /\ failures <- collectAssertionFailures checks $ lift do @@ -146,28 +155,32 @@ suite = do head <$> withKeyWallet bob ownPaymentPubKeyHashes receiverSkh <- join <<< head <$> withKeyWallet bob ownStakePubKeyHashes - mintingPolicy /\ cs <- mkCurrencySymbol alwaysMintsPolicyV2 + mintingPolicy <- alwaysMintsPolicyScriptV2 + + let cs = PlutusScript.hash mintingPolicy - tn <- mkTokenName "TheToken" + tn <- mkAssetName "TheToken" withKeyWallet alice do let params = { receiverPkh , receiverSkh - , adaToSend: BigInt.fromInt 5_000_000 + , adaToSend: wrap $ BigNum.fromInt 5_000_000 , mintingPolicy - , tokensToMint: cs /\ tn /\ one /\ unit - , datumToAttach: wrap $ Integer $ BigInt.fromInt 42 - , txMetadata: cip25MetadataFixture1 + , tokensToMint: cs /\ tn /\ BigNum.one /\ unit + , datumToAttach: Integer $ BigInt.fromInt 42 } checks <- ContractTestUtils.mkChecks params - { tokensToMint = cs /\ tn /\ (one + one) /\ unit } <#> + { tokensToMint = cs /\ tn + /\ (unsafePartial $ BigNum.one <> BigNum.one) + /\ unit + } <#> ( _ <> - [ checkExUnitsNotExceed - { mem: BigInt.fromInt 800, steps: BigInt.fromInt 16110 } + [ checkExUnitsNotExceed $ ExUnits + { mem: BigNum.fromInt 800, steps: BigNum.fromInt 16110 } ] ) @@ -176,4 +189,4 @@ suite = do eiResult `shouldSatisfy` isLeft printContractAssertionFailures failures `shouldEqual` - "In addition to the error above, the following `Contract` assertions have failed:\n\n 1. Error while trying to get expected value: Unable to estimate expected loss in wallet\n\n 2. Unexpected token delta (TokenName (hexToRawBytesUnsafe \"546865546f6b656e\")) at address Sender Expected: 2, Actual: 1 \n\n 3. ExUnits limit exceeded: Expected: { mem: 800, steps: 16110 }, Actual: { mem: 800, steps: 161100 } \n\nThe following `Contract` checks have been skipped due to an exception: \n\n 1. Sender's output has a datum\n\n 2. Output has a reference script\n\n 3. Contains CIP-25 metadata" + "In addition to the error above, the following `Contract` assertions have failed:\n\n 1. Error while trying to get expected value: Unable to estimate expected loss in wallet\n\n 2. Unexpected token delta (mkAssetName (hexToByteArrayUnsafe \"546865546f6b656e\")) at address Sender Expected: 2, Actual: 1 \n\n 3. ExUnits limit exceeded: Expected: { mem: 800, steps: 16110 }, Actual: { mem: 800, steps: 161100 } \n\nThe following `Contract` checks have been skipped due to an exception: \n\n 1. Sender's output has a datum\n\n 2. Output has a reference script" diff --git a/test/Plutip/Contract/Mnemonics.purs b/test/Testnet/Contract/Mnemonics.purs similarity index 79% rename from test/Plutip/Contract/Mnemonics.purs rename to test/Testnet/Contract/Mnemonics.purs index c6445c1612..b21d1ac3b6 100644 --- a/test/Plutip/Contract/Mnemonics.purs +++ b/test/Testnet/Contract/Mnemonics.purs @@ -1,11 +1,10 @@ -module Test.Ctl.Plutip.Contract.Mnemonics (suite) where +module Test.Ctl.Testnet.Contract.Mnemonics (suite) where import Prelude import Contract.Address (addressFromBech32) -import Contract.Test (ContractTest) +import Contract.Test (ContractTest, withWallets) import Contract.Test.Mote (TestPlanM) -import Contract.Test.Plutip (withWallets) import Contract.Wallet (getWalletAddresses, withKeyWalletFromMnemonic) import Contract.Wallet.Key (StakeKeyPresence(WithStakeKey)) import Data.Array (head) @@ -28,7 +27,7 @@ suite = do do head <$> getWalletAddresses addrExpected <- addressFromBech32 - "addr1q8day0u0gtx3302u5mmgmw20q67s9mkglte8y8kqk75jge5mvvhnhsjfj5jfpt7dv4tu6wlz7z032cmmp9ljftjmkzfswlmg44" + "addr_test1qrday0u0gtx3302u5mmgmw20q67s9mkglte8y8kqk75jge5mvvhnhsjfj5jfpt7dv4tu6wlz7z032cmmp9ljftjmkzfsdfxge2" addr1 `shouldEqual` pure addrExpected do addr1 <- withKeyWalletFromMnemonic @@ -40,7 +39,7 @@ suite = do do head <$> getWalletAddresses addrExpected <- addressFromBech32 - "addr1q9mmg8l2w7ar4cj89jte699dxuu0u3partkjt7fqdga5a7u6w4gzwu7mms8sn7rd0apcwtyu2xjzflvm7sc5vd3vtvpqnux32a" + "addr_test1qpmmg8l2w7ar4cj89jte699dxuu0u3partkjt7fqdga5a7u6w4gzwu7mms8sn7rd0apcwtyu2xjzflvm7sc5vd3vtvpqs2m3xz" addr1 `shouldEqual` pure addrExpected where diff --git a/test/Plutip/Contract/OgmiosMempool.purs b/test/Testnet/Contract/OgmiosMempool.purs similarity index 87% rename from test/Plutip/Contract/OgmiosMempool.purs rename to test/Testnet/Contract/OgmiosMempool.purs index 269ec587a8..6edd6cb464 100644 --- a/test/Plutip/Contract/OgmiosMempool.purs +++ b/test/Testnet/Contract/OgmiosMempool.purs @@ -1,9 +1,10 @@ -module Test.Ctl.Plutip.Contract.OgmiosMempool +module Test.Ctl.Testnet.Contract.OgmiosMempool ( suite ) where import Prelude +import Cardano.Types.BigNum as BigNum import Contract.Backend.Ogmios.Mempool ( MempoolSizeAndCapacity(MempoolSizeAndCapacity) , acquireMempoolSnapshot @@ -18,7 +19,6 @@ import Contract.Test.Mote (TestPlanM) import Contract.Transaction (awaitTxConfirmed) import Ctl.Examples.PlutusV2.InlineDatum as InlineDatum import Data.Array (length) -import JS.BigInt as BigInt import Mote (group, skip, test) import Test.Spec.Assertions (shouldEqual) @@ -28,8 +28,8 @@ suite = group "Ogmios mempool test" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1000_000_000 - , BigInt.fromInt 2000_000_000 + [ BigNum.fromInt 1000_000_000 + , BigNum.fromInt 2000_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -38,8 +38,8 @@ suite = group "Ogmios mempool test" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1000_000_000 - , BigInt.fromInt 2000_000_000 + [ BigNum.fromInt 1000_000_000 + , BigNum.fromInt 2000_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -57,8 +57,8 @@ suite = group "Ogmios mempool test" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1000_000_000 - , BigInt.fromInt 2000_000_000 + [ BigNum.fromInt 1000_000_000 + , BigNum.fromInt 2000_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -78,8 +78,8 @@ suite = group "Ogmios mempool test" do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 1000_000_000 - , BigInt.fromInt 2000_000_000 + [ BigNum.fromInt 1000_000_000 + , BigNum.fromInt 2000_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do diff --git a/test/Testnet/DistributeFunds.purs b/test/Testnet/DistributeFunds.purs new file mode 100644 index 0000000000..9971d7f104 --- /dev/null +++ b/test/Testnet/DistributeFunds.purs @@ -0,0 +1,274 @@ +module Test.Ctl.Testnet.DistributeFunds where + +import Contract.Prelude hiding (over) + +import Contract.Test.Mote (TestPlanM) +import Ctl.Internal.Testnet.DistributeFunds + ( _completeTxs + , _leftover + , _source + , _total + , _totalUtxos + , _tx + , _utxos + ) +import Ctl.Internal.Testnet.DistributeFunds as Distribute +import Data.Bifunctor (lmap) +import Data.Lens (over, set, view, (%~), (+~), (-~), (.~), (^.)) +import Data.List (List(Cons)) +import Data.List as List +import Mote (group, test) +import Test.Spec.Assertions (shouldEqual) + +suite :: TestPlanM (Aff Unit) Unit +suite = group "Testnet" $ group "Distribute Funds" do + group "assignUtxo" do + let + highThreshold = + { maxCoinPerTx: 999_999 + , maxTargetUtxosPerTx: 999_999 + } + + test "Fails if sources do not have enough funds" do + + let + outcome = + Distribute.assignUtxo + highThreshold + { amount: 120, key: "utxo0" } + $ List.fromFoldable + [ Distribute.initialSourceState + { key: 1, initialFunds: 90 } + , Distribute.initialSourceState + { key: 2, initialFunds: 100 } + ] + lmap (const unit) outcome `shouldEqual` Left unit + test "Starts new Tx when reaches the limit of UTxOs" do + let + thresholds = highThreshold { maxTargetUtxosPerTx = 3 } + + src0 :: Distribute.SourceState Int String Int + src0 = + Distribute.initialSourceState + { key: 0, initialFunds: 90 } + # (_tx <<< _total .~ 370) + # (_tx <<< _totalUtxos .~ 2) + # + ( _tx <<< _utxos .~ List.fromFoldable + [ { key: "tgt0", amount: 300 } + , { key: "tgt42", amount: 70 } + ] + ) + + src1 :: Distribute.SourceState Int String Int + src1 = Distribute.initialSourceState + { key: 1, initialFunds: 30 } + + utxo0 = { amount: 10, key: "utxo0" } + utxo1 = { amount: 6, key: "utxo1" } + acc0 = List.fromFoldable [ src0, src1 ] + outcome = do + acc1 <- Distribute.assignUtxo + thresholds + utxo0 + acc0 + acc2 <- Distribute.assignUtxo + thresholds + utxo1 + acc1 + pure acc2 + + expected :: List (Distribute.SourceState Int String Int) + expected = List.fromFoldable + [ src1 + # (_leftover -~ utxo1.amount) + # + ( set _tx + $ Distribute.emptyTx utxo1.amount + # (_totalUtxos .~ 1) + # (_utxos .~ pure utxo1) + ) + , src0 + # (_leftover -~ utxo0.amount) + # (_tx .~ Distribute.emptyTx zero) + # + ( over _completeTxs + $ src0 + # (view _tx) + # (_total +~ utxo0.amount) + # (_totalUtxos .~ 3) + # (_utxos %~ Cons utxo0) + # Cons + ) + ] + + outcome `shouldEqual` Right expected + test "Tends to spend sources evenly" do + let + utxos0 = List.fromFoldable + [ { key: "01", amount: 2 } + , { key: "02", amount: 18 } + ] + utxos1 = List.fromFoldable + [ { key: "11", amount: 3 } + , { key: "12", amount: 17 } + ] + utxos2 = List.fromFoldable + [ { key: "21", amount: 9 } + , { key: "22", amount: 11 } + ] + utxos3 = List.fromFoldable + [ { key: "31", amount: 15 } + , { key: "32", amount: 5 } + ] + -- total = 80 + utxos = utxos0 <> utxos1 <> utxos2 <> utxos3 + + -- they have exactly enough to fit all the utxos + src0 = Distribute.initialSourceState + { key: 0, initialFunds: 40 } + src1 = Distribute.initialSourceState + { key: 1, initialFunds: 40 } + sources = List.fromFoldable [ src0, src1 ] + + outcome = foldM + ( flip $ Distribute.assignUtxo highThreshold + { maxTargetUtxosPerTx = 2 } + ) + sources + utxos + + -- Both must have 2 txs, 20 UTxO each. All sources funds must be spent. + expected = List.fromFoldable + [ src1 + # (_leftover .~ 0) + -- it would be put in completeTxs on the next iteration + # + ( set _tx + $ Distribute.emptyTx 20 + # (_totalUtxos .~ 2) + # (_utxos .~ List.reverse utxos3) + ) + # + ( set _completeTxs + $ Distribute.emptyTx 20 + # (_totalUtxos .~ 2) + # (_utxos .~ List.reverse utxos1) + # pure + ) + , src0 + # (_leftover .~ 0) + # + ( _completeTxs .~ List.fromFoldable + [ Distribute.emptyTx 20 + # (_totalUtxos .~ 2) + # (_utxos .~ List.reverse utxos2) + , Distribute.emptyTx 20 + # (_totalUtxos .~ 2) + # (_utxos .~ List.reverse utxos0) + ] + ) + ] + outcome `shouldEqual` Right expected + + -- It could be better: seach for a source that have a Tx with lowest total or lowest amount of UTxOs + -- But if it worths it? + test "Makes new Tx if utxo is impossible to fit in existing ones" do + let + src0 = + Distribute.initialSourceState + { key: 0, initialFunds: 900 } + # (_tx <<< _total .~ 120) + src1 = + Distribute.initialSourceState + { key: 1, initialFunds: 800 } + # (_tx <<< _total .~ 105) + utxo = { key: "utxo0", amount: 100 } + outcome = + Distribute.assignUtxo + highThreshold { maxCoinPerTx = 200 } + utxo + $ List.fromFoldable [ src0, src1 ] + expected = List.fromFoldable + [ src0 + , src1 + # (_leftover -~ utxo.amount) + # + ( set _tx + $ Distribute.emptyTx utxo.amount + # (_totalUtxos .~ 1) + # (_utxos .~ pure utxo) + ) + # (_completeTxs .~ pure (src1 ^. _tx)) + ] + outcome `shouldEqual` Right expected + test "Tries to fit UTxO in any constructing tx that can fit it" do + let + src0 = + Distribute.initialSourceState + { key: 0, initialFunds: 900 } + -- not enough to fit the utxo + # (_tx <<< _total .~ 120) + src1 = + Distribute.initialSourceState + { key: 1, initialFunds: 800 } + -- exactly enough to fit the utxo + # (_tx <<< _total .~ 100) + utxo = { key: "utxo0", amount: 100 } + outcome = + Distribute.assignUtxo + highThreshold { maxCoinPerTx = 200 } + utxo + $ List.fromFoldable [ src0, src1 ] + expected = List.fromFoldable + [ src0 + , src1 + # (_leftover -~ utxo.amount) + # (_tx <<< _total +~ utxo.amount) + # (_tx <<< _totalUtxos +~ 1) + # (_tx <<< _utxos .~ pure utxo) + ] + outcome `shouldEqual` Right expected + test "Tries to fit UTxO in any source tx that has enough funds" do + let + -- not enough + src0 = Distribute.initialSourceState + { key: 0, initialFunds: 200 } + src1 = Distribute.initialSourceState + { key: 1, initialFunds: 100 } + -- enough + src2 = Distribute.initialSourceState + { key: 2, initialFunds: 300 } + utxo = { key: "utxo0", amount: 250 } + outcome = map (List.sortBy $ comparing (view _source)) + $ Distribute.assignUtxo highThreshold utxo + $ List.fromFoldable [ src0, src1, src2 ] + expected = List.sortBy (comparing $ view _source) $ List.fromFoldable + [ src0 + , src1 + , src2 + # (_leftover -~ utxo.amount) + # + ( set _tx + $ Distribute.emptyTx utxo.amount + # (_totalUtxos .~ 1) + # (_utxos .~ pure utxo) + ) + ] + outcome `shouldEqual` Right expected + test "Fails if UTxO amount is higher than threshold" do + let + -- not enough + src0 = Distribute.initialSourceState + { key: 0, initialFunds: 300 } + src1 = Distribute.initialSourceState + { key: 1, initialFunds: 900 } + utxo = { key: "utxo0", amount: 250 } + outcome = + Distribute.assignUtxo + highThreshold { maxCoinPerTx = 200 } + utxo + $ List.fromFoldable [ src0, src1 ] + lmap (const unit) outcome `shouldEqual` Left unit + pure unit + diff --git a/test/Testnet/DistributeFundsV2.purs b/test/Testnet/DistributeFundsV2.purs new file mode 100644 index 0000000000..6105937e5b --- /dev/null +++ b/test/Testnet/DistributeFundsV2.purs @@ -0,0 +1,205 @@ +module Test.Ctl.Testnet.DistributeFundsV2 + ( suite + ) where + +import Prelude + +import Contract.Test.Mote (TestPlanM) +import Ctl.Internal.Testnet.DistributeFundsV2 + ( AssignUtxoResult + ( AssignUtxo_Unassigned + , AssignUtxo_Deferred + , AssignUtxo_AssignedToSource + ) + , DistrFundsError(DistrFunds_AssignUtxoError) + , DistrFundsParams + , SourceState + , assignUtxoToSource + , initSourceState + , makeDistributionPlan + , runDistrFundsRound + ) +import Data.Array (reverse) +import Data.Either (Either(Left, Right)) +import Data.List (fromFoldable) as List +import Data.Maybe (Maybe(Just, Nothing)) +import Data.Newtype (modify, wrap) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect.Aff (Aff) +import Mote (group, test) +import Test.Spec.Assertions (shouldEqual) + +suite :: TestPlanM (Aff Unit) Unit +suite = + group "DistributeFundsV2" do + group "assignUtxoToSource" do + test "Leaves utxo unassigned if it cannot be covered by source" + let + src0 = initSourceState "src0" 1000 + utxo = "target0" /\ 2000 + in + assignUtxoToSource defaultParams src0 utxo `shouldEqual` + AssignUtxo_Unassigned + + test "Takes tx fee into account" + let + params = defaultParams { feePerTx = 10 } + src0 = initSourceState "src0" 1000 + utxo = "target0" /\ 1000 + in + assignUtxoToSource params src0 utxo `shouldEqual` + AssignUtxo_Unassigned + + test "Marks utxo as deferred if maxUtxosPerTx is exceeded" + let + params = defaultParams { maxUtxosPerTx = 0 } + src0 = initSourceState "src0" 1000 + utxo = "target0" /\ 1000 + in + assignUtxoToSource params src0 utxo `shouldEqual` + AssignUtxo_Deferred + + test "Correctly assigns utxos to source" + let + params = defaultParams { feePerTx = 100 } + src0 = initSourceState "src0" 2000 + utxo0 = "target0" /\ 1000 + utxo1 = "target1" /\ 500 + assignUtxo = flip (assignUtxoToSource params) + outcome = + (getSource <<< assignUtxo utxo1) + =<< getSource (assignUtxo utxo0 src0) + in + outcome `shouldEqual` Just + ( src0 + { leftover = 500 + , currentTx = modify + ( _ + { numUtxos = 2 + , utxos = List.fromFoldable + [ utxoToRec utxo1, utxoToRec utxo0 ] + } + ) + src0.currentTx + } + ) + + group "runDistrFundsRound" do + test "Fails if utxo cannot be covered by any source" + let + sources = List.fromFoldable + [ initSourceState "src0" 1000 + , initSourceState "src1" 2000 + , initSourceState "src2" 3000 + ] + utxos = List.fromFoldable + [ "target0" /\ 1000 + , "target1" /\ 3500 + ] + in + runDistrFundsRound defaultParams sources utxos `shouldEqual` + Left DistrFunds_AssignUtxoError + + test "Deferrs utxos that cannot be assigned in the current round" + let + params = defaultParams { maxUtxosPerTx = 1 } + src0 = initSourceState "src0" 2000 + src1 = initSourceState "src1" 1000 + sources = List.fromFoldable [ src0, src1 ] + utxo0 = "target0" /\ 1600 + utxo1 = "target1" /\ 800 + utxo2 = "target2" /\ 400 + utxos = List.fromFoldable [ utxo0, utxo1, utxo2 ] + in + runDistrFundsRound params sources utxos `shouldEqual` + Right + { sources: List.fromFoldable + [ src0 + { leftover = 400 + , currentTx = modify + ( _ + { numUtxos = 1 + , utxos = List.fromFoldable [ utxoToRec utxo0 ] + } + ) + src0.currentTx + } + , src1 + { leftover = 200 + , currentTx = modify + ( _ + { numUtxos = 1 + , utxos = List.fromFoldable [ utxoToRec utxo1 ] + } + ) + src1.currentTx + } + ] + , deferredTargets: List.fromFoldable [ utxo2 ] + } + + group "makeDistributionPlan" do + test "Prepares simple funds distribution plan (2 rounds)" + let + params = defaultParams { maxUtxosPerTx = 2, maxRounds = 5 } + + utxos0 = [ "01" /\ 2, "02" /\ 18 ] + utxos1 = [ "11" /\ 3, "12" /\ 17 ] + utxos2 = [ "21" /\ 9, "22" /\ 11 ] + utxos3 = [ "31" /\ 15, "32" /\ 5 ] + + -- total = 80 + utxos = utxos0 <> utxos1 <> utxos2 <> utxos3 + + -- sources have exactly enough funds to fit all the utxos + src0 = "src0" /\ 40 + src1 = "src1" /\ 40 + sources = [ src0, src1 ] + in + makeDistributionPlan params sources utxos `shouldEqual` + Right + [ [ wrap + { srcWallet: "src0" + , numUtxos: 2 + , utxos: List.fromFoldable $ utxoToRec <$> reverse utxos1 + } + , wrap + { srcWallet: "src1" + , numUtxos: 2 + , utxos: List.fromFoldable $ utxoToRec <$> reverse utxos0 + } + ] + , [ wrap + { srcWallet: "src0" + , numUtxos: 2 + , utxos: List.fromFoldable $ utxoToRec <$> utxos2 + } + , wrap + { srcWallet: "src1" + , numUtxos: 2 + , utxos: List.fromFoldable $ utxoToRec <$> utxos3 + } + ] + ] + +utxoToRec + :: forall wallet amount + . wallet /\ amount + -> { wallet :: wallet, amount :: amount } +utxoToRec (wallet /\ amount) = { wallet, amount } + +getSource + :: forall wallet amount + . AssignUtxoResult wallet amount + -> Maybe (SourceState wallet amount) +getSource = case _ of + AssignUtxo_AssignedToSource src -> Just src + _ -> Nothing + +defaultParams :: forall wallet. DistrFundsParams wallet Int +defaultParams = + { maxRounds: top + , maxUtxosPerTx: top + , getUtxoMinAdaForWallet: const zero + , feePerTx: zero + } diff --git a/test/Plutip/ExUnits.purs b/test/Testnet/ExUnits.purs similarity index 87% rename from test/Plutip/ExUnits.purs rename to test/Testnet/ExUnits.purs index b05bc93736..a3bb793685 100644 --- a/test/Plutip/ExUnits.purs +++ b/test/Testnet/ExUnits.purs @@ -1,20 +1,21 @@ -module Test.Ctl.Plutip.ExUnits +module Test.Ctl.Testnet.ExUnits ( mkSuite , mkFailingSuite ) where import Prelude +import Cardano.Types.BigNum as BigNum import Contract.Log (logInfo') import Contract.Scripts (validatorHash) import Contract.Test (ContractTest, InitialUTxOs, withKeyWallet, withWallets) import Contract.Transaction (awaitTxConfirmed) import Ctl.Examples.ExUnits as ExUnits -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Data.Either (isLeft) import Effect.Aff (try) import JS.BigInt as BigInt import Mote (test) +import Mote.TestPlanM (TestPlanM) import Test.Spec.Assertions (shouldSatisfy) mkSuite :: Int -> TestPlanM ContractTest Unit @@ -24,8 +25,8 @@ mkSuite n = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 500_000_000 - , BigInt.fromInt 500_000_000 + [ BigNum.fromInt 500_000_000 + , BigNum.fromInt 500_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do @@ -44,8 +45,8 @@ mkFailingSuite n = do let distribution :: InitialUTxOs distribution = - [ BigInt.fromInt 500_000_000 - , BigInt.fromInt 500_000_000 + [ BigNum.fromInt 500_000_000 + , BigNum.fromInt 500_000_000 ] withWallets distribution \alice -> do withKeyWallet alice do diff --git a/test/Testnet/Gov.purs b/test/Testnet/Gov.purs new file mode 100644 index 0000000000..46b4aa9791 --- /dev/null +++ b/test/Testnet/Gov.purs @@ -0,0 +1,53 @@ +module Test.Ctl.Testnet.Gov + ( suite + ) where + +import Prelude + +import Cardano.Types.BigNum (fromInt) as BigNum +import Contract.Test (ContractTest) +import Contract.Test.Mote (TestPlanM) +import Contract.Test.Testnet (withKeyWallet, withWallets) +import Ctl.Examples.Gov.DelegateVoteAbstain (contract) as Gov.DelegateVoteAbstain +import Ctl.Examples.Gov.ManageDrep (contract) as Gov.ManageDrep +import Ctl.Examples.Gov.ManageDrepScript (contract) as Gov.ManageDrepScript +import Ctl.Examples.Gov.SubmitVote (contract) as Gov.SubmitVote +import Ctl.Examples.Gov.SubmitVoteScript (contract) as Gov.SubmitVoteScript +import Ctl.Internal.Test.UtxoDistribution (TestWalletSpec) +import Data.Maybe (Maybe(Just)) +import Data.Newtype (wrap) +import Mote (group, test) +import Test.Ctl.Testnet.Common (privateDrepKey, privateStakeKey) + +walletSpec :: TestWalletSpec +walletSpec = wrap + { utxos: + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 50_000_000 + ] + , stakeKey: Just privateStakeKey + , drepKey: Just privateDrepKey + } + +suite :: TestPlanM ContractTest Unit +suite = do + group "Governance" do + test "Gov.DelegateVoteAbstain" do + withWallets walletSpec \alice -> + withKeyWallet alice Gov.DelegateVoteAbstain.contract + + test "Gov.ManageDrep example" do + withWallets walletSpec \alice -> + withKeyWallet alice Gov.ManageDrep.contract + + test "Gov.ManageDrepScript example" do + withWallets walletSpec \alice -> + withKeyWallet alice Gov.ManageDrepScript.contract + + test "Gov.SubmitVote example" do + withWallets walletSpec \alice -> + withKeyWallet alice Gov.SubmitVote.contract + + test "Gov.SubmitVoteScript example" do + withWallets walletSpec \alice -> + withKeyWallet alice Gov.SubmitVoteScript.contract diff --git a/test/Plutip/Logging.purs b/test/Testnet/Logging.purs similarity index 81% rename from test/Plutip/Logging.purs rename to test/Testnet/Logging.purs index 653ef0a911..fd43ab5619 100644 --- a/test/Plutip/Logging.purs +++ b/test/Testnet/Logging.purs @@ -1,12 +1,11 @@ -module Test.Ctl.Plutip.Logging +module Test.Ctl.Testnet.Logging ( suite ) where import Prelude import Contract.Log (logWarn') -import Contract.Test.Plutip (runPlutipContract) -import Ctl.Internal.Test.TestPlanM (TestPlanM) +import Contract.Test.Testnet (defaultTestnetConfig, runTestnetContract) import Data.Log.Level (LogLevel(Error)) import Data.Maybe (Maybe(Just)) import Effect.Aff (Aff, try) @@ -14,7 +13,7 @@ import Effect.Class (liftEffect) import Effect.Exception (throw) import Effect.Ref as Ref import Mote (group, test) -import Test.Ctl.Plutip.Common (config) +import Mote.TestPlanM (TestPlanM) import Test.Spec.Assertions (shouldEqual) suite :: TestPlanM (Aff Unit) Unit @@ -24,12 +23,12 @@ suite = do hasLogged <- liftEffect $ Ref.new false let config' = - config + defaultTestnetConfig { customLogger = Just \_ _ -> liftEffect $ Ref.write true hasLogged , suppressLogs = false } - runPlutipContract config' unit \_ -> do + runTestnetContract config' unit \_ -> do logWarn' "" hasLoggedResult <- liftEffect $ Ref.read hasLogged hasLoggedResult `shouldEqual` true @@ -37,12 +36,12 @@ suite = do hasLogged <- liftEffect $ Ref.new false let config' = - config + defaultTestnetConfig { customLogger = Just \_ _ -> liftEffect $ Ref.write true hasLogged , suppressLogs = true } - runPlutipContract config' unit \_ -> do + runTestnetContract config' unit \_ -> do logWarn' "" hasLoggedResult <- liftEffect $ Ref.read hasLogged hasLoggedResult `shouldEqual` false @@ -50,12 +49,12 @@ suite = do hasLogged <- liftEffect $ Ref.new false let config' = - config + defaultTestnetConfig { customLogger = Just \_ _ -> liftEffect $ Ref.write true hasLogged , suppressLogs = true } - void $ try $ runPlutipContract config' unit \_ -> do + void $ try $ runTestnetContract config' unit \_ -> do logWarn' "" liftEffect $ throw "Exception" hasLoggedResult <- liftEffect $ Ref.read hasLogged @@ -64,14 +63,14 @@ suite = do hasLogged <- liftEffect $ Ref.new false let config' = - config + defaultTestnetConfig { customLogger = Just writeLog , suppressLogs = false , logLevel = Error } writeLog lgl m = liftEffect $ when (m.level >= lgl) $ do Ref.write true hasLogged - runPlutipContract config' unit \_ -> do + runTestnetContract config' unit \_ -> do logWarn' "" hasLoggedResult <- liftEffect $ Ref.read hasLogged hasLoggedResult `shouldEqual` false diff --git a/test/Testnet/SameWallets.purs b/test/Testnet/SameWallets.purs new file mode 100644 index 0000000000..d538044050 --- /dev/null +++ b/test/Testnet/SameWallets.purs @@ -0,0 +1,92 @@ +module Test.Ctl.Testnet.SameWallets + ( suite + ) where + +import Contract.Prelude + +import Cardano.Types.BigNum as BigNum +import Cardano.Types.Int as Int +import Cardano.Types.Mint as Mint +import Cardano.Types.PlutusScript as PlutusScript +import Contract.Address (PaymentPubKeyHash) +import Contract.Monad (Contract, liftedM) +import Contract.ScriptLookups as Lookups +import Contract.Test.Testnet + ( ContractTestPlan + , sameWallets + , withKeyWallet + ) +import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) +import Contract.TxConstraints as Constraints +import Contract.Value (TokenName, Value) +import Contract.Value as Value +import Contract.Wallet (ownPaymentPubKeyHashes) +import Ctl.Examples.AlwaysMints (alwaysMintsPolicy) +import Ctl.Examples.Helpers (mkAssetName) as Helpers +import Ctl.Internal.Test.UtxoDistribution (InitialUTxOs) +import Data.Array as Array +import Mote (group, test) + +suite :: ContractTestPlan +suite = + let + distribution :: InitialUTxOs /\ InitialUTxOs + distribution = + -- Alice + [ BigNum.fromInt 1_000_000_000 ] /\ + -- Bob + [ BigNum.fromInt 1_000_000_000 ] + + tokenNameAscii :: String + tokenNameAscii = "CTLNFT" + in + sameWallets distribution do + group "SameWallets" do + test "Alice mints some tokens" \(alice /\ _) -> do + tn <- Helpers.mkAssetName tokenNameAscii + withKeyWallet alice $ void $ alwaysMint tn + test "Alice sends a token to Bob" \(alice /\ bob) -> do + bobPKH <- withKeyWallet bob do + liftedM "Failed to get Bob's PKH" + $ Array.head + <$> ownPaymentPubKeyHashes + withKeyWallet alice do + mp <- alwaysMintsPolicy + let cs = PlutusScript.hash mp + tn <- Helpers.mkAssetName tokenNameAscii + pkh2pkh bobPKH $ Value.singleton cs tn BigNum.one + +alwaysMint :: TokenName -> Contract Unit +alwaysMint tn = do + mp <- alwaysMintsPolicy + let + cs = PlutusScript.hash mp + + constraints :: Constraints.TxConstraints + constraints = Constraints.mustMintValue + $ Mint.singleton cs tn + $ Int.fromInt 100 + + lookups :: Lookups.ScriptLookups + lookups = Lookups.plutusMintingPolicy mp + + submitTxFromConstraints lookups constraints + >>= awaitTxConfirmed + +pkh2pkh :: PaymentPubKeyHash -> Value -> Contract Unit +pkh2pkh recipient val = do + + pkh <- + liftedM "Failed to get own PKH" + $ Array.head + <$> ownPaymentPubKeyHashes + + let + constraints :: Constraints.TxConstraints + constraints = Constraints.mustPayToPubKey recipient val + + lookups :: Lookups.ScriptLookups + lookups = Lookups.ownPaymentPubKeyHash pkh + + submitTxFromConstraints lookups constraints + >>= awaitTxConfirmed diff --git a/test/Testnet/Staking.purs b/test/Testnet/Staking.purs new file mode 100644 index 0000000000..0b160f9752 --- /dev/null +++ b/test/Testnet/Staking.purs @@ -0,0 +1,702 @@ +module Test.Ctl.Testnet.Staking + ( main + , suite + ) where + +import Prelude + +import Cardano.AsCbor (decodeCbor) +import Cardano.Plutus.ApplyArgs (applyArgs) +import Cardano.Transaction.Builder + ( CredentialWitness(NativeScriptCredential, PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(WithdrawRewards, IssueCertificate, Pay) + ) +import Cardano.Types + ( Certificate + ( StakeDelegation + , StakeRegistration + , StakeDeregistration + , PoolRetirement + , PoolRegistration + ) + , Credential(ScriptHashCredential, PubKeyHashCredential) + , OutputDatum(OutputDatum) + , PlutusData(Integer) + , PoolParams(PoolParams) + , TransactionOutput(TransactionOutput) + , UnitInterval(UnitInterval) + , _body + , _certs + ) +import Cardano.Types.BigInt as BigInt +import Cardano.Types.NativeScript as NativeScript +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Types.PublicKey as PublicKey +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Cardano.Wallet.Key (PrivateStakeKey) +import Contract.Address (getNetworkId, mkAddress) +import Contract.Backend.Ogmios (getPoolParameters) +import Contract.Log (logInfo') +import Contract.Monad (Contract, liftedM) +import Contract.Numeric.BigNum (fromInt, toBigInt) as BigNum +import Contract.Prelude (liftM) +import Contract.Prim.ByteArray (hexToByteArray) +import Contract.Scripts (NativeScript(ScriptPubkey, ScriptAny)) +import Contract.Staking + ( getPoolIds + , getPubKeyHashDelegationsAndRewards + , getStakeCredentialDelegationsAndRewards + , getValidatorHashDelegationsAndRewards + ) +import Contract.Test.Mote (TestPlanM, interpretWithConfig) +import Contract.Test.Testnet (defaultTestnetConfig, runTestnetContract) +import Contract.Test.Utils (exitCode, interruptOnSignal) +import Contract.Time (getCurrentEpoch) +import Contract.Transaction + ( Epoch(Epoch) + , PoolPubKeyHash(PoolPubKeyHash) + , balanceTx + , buildTx + , signTransaction + ) +import Contract.Value (lovelaceValueOf) +import Contract.Wallet + ( ownPaymentPubKeyHashes + , ownStakePubKeyHashes + , withKeyWallet + ) +import Contract.Wallet.Key (getPrivateStakeKey) +import Control.Bind (bindFlipped) +import Ctl.Examples.AlwaysSucceeds (alwaysSucceedsScript) +import Ctl.Examples.Helpers (submitAndLog) +import Ctl.Examples.IncludeDatum (only42Script) +import Ctl.Internal.Test.UtxoDistribution + ( InitialUTxOs + , InitialUTxOsWithStakeKey(InitialUTxOsWithStakeKey) + ) +import Data.Array (head) +import Data.Array as Array +import Data.Either (hush) +import Data.Foldable (for_) +import Data.Lens ((.~)) +import Data.Map as Map +import Data.Maybe (Maybe(Just, Nothing)) +import Data.Newtype (unwrap, wrap) +import Data.Posix.Signal (Signal(SIGINT)) +import Data.Time.Duration (Seconds(Seconds)) +import Data.Tuple.Nested ((/\)) +import Data.UInt as UInt +import Effect (Effect) +import Effect.Aff + ( Aff + , Milliseconds(Milliseconds) + , cancelWith + , delay + , effectCanceler + , launchAff + ) +import Effect.Aff.Class (liftAff) +import Effect.Exception (error) +import Mote (group, skip, test) +import Test.Ctl.Testnet.Common (privateStakeKey) +import Test.Spec.Assertions (shouldEqual, shouldSatisfy) +import Test.Spec.Runner (defaultConfig) + +main :: Effect Unit +main = interruptOnSignal SIGINT =<< launchAff do + flip cancelWith (effectCanceler (exitCode 1)) do + interpretWithConfig + defaultConfig { timeout = Just $ Milliseconds 90_000.0, exit = true } + suite + +suite :: TestPlanM (Aff Unit) Unit +suite = do + let + -- A routine function that selects a pool from the list of available pools + selectPoolId :: Contract PoolPubKeyHash + selectPoolId = do + pools <- getPoolIds + logInfo' "Pool IDs:" + logInfo' $ show pools + for_ pools \poolId -> do + logInfo' "Pool parameters" + logInfo' <<< show =<< getPoolParameters poolId + liftM (error "unable to get any pools") $ head pools + group "Staking" do + group "Stake keys: register & deregister" do + test "PubKey" do + let + distribution = withStakeKey privateStakeKeyForDist + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] + runTestnetContract config distribution $ flip withKeyWallet do + aliceStakePkh <- liftedM "Failed to get Stake PKH" + (join <<< head <$> ownStakePubKeyHashes) + + -- Register + do + let + transaction = Transaction.empty + # _body <<< _certs .~ + [ StakeRegistration $ wrap $ PubKeyHashCredential $ unwrap + aliceStakePkh + ] + + balanceTx transaction Map.empty mempty >>= signTransaction >>= + submitAndLog + + -- Deregister stake key + do + tx <- buildTx + [ IssueCertificate + ( StakeDeregistration $ wrap $ PubKeyHashCredential $ unwrap + aliceStakePkh + ) + Nothing + ] + + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + test "PlutusScript" do + let + distribution = withStakeKey privateStakeKeyForDist + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] + runTestnetContract config distribution $ flip withKeyWallet do + validator1 <- alwaysSucceedsScript + validator2 <- do + only42 <- only42Script + liftM (error "failed to apply args") do + applyArgs only42 [ Integer $ BigInt.fromInt 42 ] # hush + let + validatorHash1 = PlutusScript.hash validator1 + validatorHash2 = PlutusScript.hash validator2 + + -- Register + do + let + tx = + Transaction.empty + # _body <<< _certs .~ + [ StakeRegistration $ wrap $ ScriptHashCredential + validatorHash1 + , StakeRegistration $ wrap $ ScriptHashCredential + validatorHash2 + ] + + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + -- Deregister stake key + do + let + plan = + [ IssueCertificate + ( StakeDeregistration $ wrap $ ScriptHashCredential $ + PlutusScript.hash validator1 + ) + $ Just + $ PlutusScriptCredential (ScriptValue validator1) + RedeemerDatum.unit + , IssueCertificate + ( StakeDeregistration $ wrap $ ScriptHashCredential $ + PlutusScript.hash validator2 + ) + $ Just + $ PlutusScriptCredential (ScriptValue validator2) + RedeemerDatum.unit + ] + + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + test "NativeScript" do + let + distribution = withStakeKey privateStakeKeyForDist + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] + runTestnetContract config distribution $ flip withKeyWallet do + alicePkh <- liftedM "Failed to get PKH" + (head <$> ownPaymentPubKeyHashes) + let + nativeScript = ScriptAny + [ ScriptPubkey $ unwrap alicePkh ] + stakeValidatorHash = NativeScript.hash nativeScript + + -- Register + do + let + tx = + Transaction.empty + # _body <<< _certs .~ + [ StakeRegistration $ wrap $ ScriptHashCredential + stakeValidatorHash + ] + + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + -- Deregister stake key + do + let + credential = wrap $ ScriptHashCredential $ NativeScript.hash + nativeScript + plan = + [ IssueCertificate (StakeDeregistration credential) + $ Just + $ NativeScriptCredential + $ ScriptValue nativeScript + ] + + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + test "Pool registration & retirement" do + let + distribution = withStakeKey privateStakeKeyForDist + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] + runTestnetContract config distribution \alice -> withKeyWallet alice do + aliceStakePkh <- liftedM "Failed to get Stake PKH" + (join <<< head <$> ownStakePubKeyHashes) + + -- Register stake key + do + let + credential = wrap $ PubKeyHashCredential $ unwrap aliceStakePkh + + plan = + [ IssueCertificate (StakeRegistration credential) Nothing ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + kwMStakeKey <- liftAff $ getPrivateStakeKey alice + privateStakeKey <- liftM (error "Failed to get private stake key") + kwMStakeKey + networkId <- getNetworkId + let + poolOperator = PoolPubKeyHash $ PublicKey.hash $ + PrivateKey.toPublicKey (unwrap privateStakeKey) + + -- Register pool + do + vrfKeyHash <- liftM (error "Unable to decode VRFKeyHash") do + hexToByteArray + "fbf6d41985670b9041c5bf362b5262cf34add5d265975de176d613ca05f37096" + >>= wrap >>> decodeCbor + let + rewardAccount = + { networkId + , stakeCredential: wrap $ PubKeyHashCredential $ unwrap + aliceStakePkh + } + + poolParams = PoolParams + { operator: poolOperator + , vrfKeyhash: vrfKeyHash -- needed to prove that the pool won the lottery + , pledge: BigNum.fromInt 1 + , cost: BigNum.fromInt 1 + , margin: UnitInterval + { numerator: BigNum.fromInt 1 + , denominator: BigNum.fromInt 1 + } + , rewardAccount + , poolOwners: + [ PublicKey.hash $ + PrivateKey.toPublicKey + (unwrap privateStakeKey) + ] + , relays: [] + , poolMetadata: Nothing + } + + tx = + Transaction.empty # _body <<< _certs .~ + [ PoolRegistration poolParams ] + + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + -- List pools: the pool must appear in the list + do + pools <- getPoolIds + pools `shouldSatisfy` Array.elem poolOperator + + currentEpoch <- getCurrentEpoch + let + -- NOTE: this is a source of flaky-ness + -- (there's no guarantee that the tx will pass before the specified epoch). + -- You will get something like this error if it's not the case: + -- Error: `submit` call failed. Error from Ogmios: [{"wrongRetirementEpoch":{"currentEpoch":114,"firstUnreachableEpoch":1000114,"requestedEpoch":95}}] + retirementEpoch :: Epoch + retirementEpoch = Epoch (unwrap currentEpoch + UInt.fromInt 5) + + -- Retire pool + do + let + tx = + Transaction.empty # _body <<< _certs .~ + [ PoolRetirement + { poolKeyHash: poolOperator, epoch: retirementEpoch } + ] + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + let + waitEpoch :: Epoch -> Contract Epoch + waitEpoch epoch = do + epochNow <- getCurrentEpoch + if unwrap epochNow >= unwrap epoch then pure epochNow + else do + liftAff $ delay $ Milliseconds 1000.0 + waitEpoch epoch + + void $ waitEpoch retirementEpoch + + -- List pools: the pool must not appear in the list + do + pools <- getPoolIds + pools `shouldSatisfy` Array.notElem poolOperator + + skip $ test + "Plutus Stake script: delegate to existing pool & withdraw rewards" + do + let + distribution = withStakeKey privateStakeKeyForDist + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] + runTestnetContract config distribution \alice -> + withKeyWallet alice do + validator <- alwaysSucceedsScript + let + validatorHash = PlutusScript.hash validator + + -- Lock funds on the stake script + do + address <- mkAddress (wrap $ ScriptHashCredential validatorHash) + (Just $ wrap $ ScriptHashCredential $ validatorHash) + let + plan = + [ Pay $ TransactionOutput + { address + , datum: Just $ OutputDatum PlutusData.unit + , amount: lovelaceValueOf + $ BigNum.fromInt 1_000_000_000 + , scriptRef: Nothing + } + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= + submitAndLog + + -- Register stake script + do + let + credential = wrap $ ScriptHashCredential validatorHash + tx <- buildTx + [ IssueCertificate (StakeRegistration credential) + $ Just + $ PlutusScriptCredential + (ScriptValue validator) + RedeemerDatum.unit + ] + balanceTx tx Map.empty mempty >>= signTransaction >>= + submitAndLog + + -- Select a pool + poolId <- selectPoolId + + -- Delegate + do + let + credential = wrap $ ScriptHashCredential $ PlutusScript.hash + validator + plan = + [ IssueCertificate (StakeDeregistration credential) + $ Just + $ PlutusScriptCredential + (ScriptValue validator) + RedeemerDatum.unit + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= + submitAndLog + + -- Wait until rewards + let + -- No need for limit on number of retries, because we have a + -- timeout for tests. + waitUntilRewards = do + mbDelegationsAndRewards <- + getValidatorHashDelegationsAndRewards validatorHash + case mbDelegationsAndRewards of + Just dels@{ rewards } + | BigNum.toBigInt <<< unwrap <$> rewards > Just zero -> + pure dels + _ -> do + liftAff $ delay $ Milliseconds 5000.0 + waitUntilRewards + + { rewards: rewardsBefore, delegate } <- waitUntilRewards + delegate `shouldEqual` Just poolId + + -- Withdraw + do + let + credential = wrap $ ScriptHashCredential $ PlutusScript.hash + validator + + rewardsAmount <- liftedM "Unable to get rewards" $ + getStakeCredentialDelegationsAndRewards credential <#> + bindFlipped _.rewards + let + plan = + [ WithdrawRewards credential rewardsAmount + $ Just + ( PlutusScriptCredential (ScriptValue validator) + RedeemerDatum.unit + ) + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= + submitAndLog + + -- Check rewards. + -- Not going to deregister here, because the rewards are added too + -- soon, and we can't deregister the stake key if there are rewards + -- left. + -- This will not happen in real life scenarios, because epoch are + -- (usually) significantly longer. + do + { rewards: rewardsAfter } <- liftedM "Unable to get rewards" $ + getValidatorHashDelegationsAndRewards validatorHash + rewardsAfter `shouldSatisfy` \after -> after < rewardsBefore + + skip $ test + "Native Stake script: delegate to existing pool & withdraw rewards" + do + let + distribution = + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] /\ + withStakeKey privateStakeKeyForDist + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] + runTestnetContract config distribution \(alice /\ bob) -> do + bobStakePkh <- withKeyWallet bob do + liftedM "Failed to get Stake PKH" + (join <<< head <$> ownStakePubKeyHashes) + let + nativeScript = ScriptAny + [ ScriptPubkey $ unwrap bobStakePkh ] + scriptHash = NativeScript.hash nativeScript + credential = wrap $ ScriptHashCredential $ NativeScript.hash + nativeScript + + -- Alice + withKeyWallet alice do + -- She locks funds on the stake script (no need for her to validate + -- the script in order to do that) + do + address <- mkAddress (wrap $ ScriptHashCredential scriptHash) + (Just $ wrap $ ScriptHashCredential scriptHash) + let + plan = + [ Pay $ TransactionOutput + { address + , datum: Just $ OutputDatum PlutusData.unit + , amount: lovelaceValueOf + $ BigNum.fromInt 1_000_000_000 + , scriptRef: Nothing + } + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= + submitAndLog + + -- Alice registers stake script (again, no need to validate it) + do + tx <- buildTx + [ IssueCertificate (StakeRegistration credential) + $ Just + $ NativeScriptCredential + $ ScriptValue nativeScript + ] + balanceTx tx Map.empty mempty >>= signTransaction >>= + submitAndLog + + -- Bob performs operations with the stake script that require his + -- (and only his) signature. + withKeyWallet bob do + + -- Select first pool + poolId <- selectPoolId + + -- Delegate + do + tx <- buildTx + [ IssueCertificate + ( StakeDelegation + ( wrap $ ScriptHashCredential $ NativeScript.hash + nativeScript + ) + poolId + ) + $ Just + $ NativeScriptCredential + $ ScriptValue nativeScript + ] + balanceTx tx Map.empty mempty >>= signTransaction >>= + submitAndLog + + -- Wait until rewards + let + -- No need for limit on number of retries, because we have a + -- timeout for tests. + waitUntilRewards = do + mbDelegationsAndRewards <- + getValidatorHashDelegationsAndRewards scriptHash + case mbDelegationsAndRewards of + Just dels@{ rewards } + | BigNum.toBigInt <<< unwrap <$> rewards > Just zero -> + pure dels + _ -> do + liftAff $ delay $ Milliseconds 5000.0 + waitUntilRewards + + { rewards: rewardsBefore, delegate } <- waitUntilRewards + delegate `shouldEqual` Just poolId + + -- Withdraw + do + rewardsAmount <- liftedM "Unable to get rewards" $ + getStakeCredentialDelegationsAndRewards credential <#> + bindFlipped _.rewards + let + plan = + [ WithdrawRewards credential rewardsAmount + $ Just (NativeScriptCredential (ScriptValue nativeScript)) + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= + submitAndLog + + -- Check rewards. + -- Not going to deregister here, because the rewards are added too + -- soon, and we can't deregister the stake key if there are rewards + -- left. + -- This will not happen in real life scenarios, because epoch are + -- (usually) significantly longer. + do + { rewards: rewardsAfter } <- liftedM "Unable to get rewards" $ + getValidatorHashDelegationsAndRewards scriptHash + rewardsAfter `shouldSatisfy` \after -> after < rewardsBefore + + skip $ test "PubKey: delegate to existing pool & withdraw rewards" do + let + distribution = withStakeKey privateStakeKeyForDist + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 + ] + runTestnetContract config distribution \alice -> + withKeyWallet alice do + aliceStakePkh <- liftedM "Failed to get Stake PKH" + (join <<< head <$> ownStakePubKeyHashes) + + -- Register stake key + do + let + tx = Transaction.empty + # _body <<< _certs .~ + [ StakeRegistration $ wrap $ PubKeyHashCredential $ unwrap $ + aliceStakePkh + ] + + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + -- Select a pool ID + poolId <- selectPoolId + + -- Delegate + do + tx <- buildTx + [ IssueCertificate + ( StakeDelegation + (wrap $ PubKeyHashCredential $ unwrap aliceStakePkh) + poolId + ) + Nothing + ] + + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + -- Wait until rewards + let + -- No need for limit on number of retries, because we have a + -- timeout for tests. + waitUntilRewards = do + mbDelegationsAndRewards <- + getPubKeyHashDelegationsAndRewards $ unwrap aliceStakePkh + case mbDelegationsAndRewards of + Just dels@{ rewards } + | BigNum.toBigInt <<< unwrap <$> rewards > Just zero -> + pure dels + _ -> do + liftAff $ delay $ Milliseconds 5000.0 + waitUntilRewards + + { rewards: rewardsBefore, delegate: _ } <- waitUntilRewards + + -- TODO: why does the query layer return Nothing even though + -- the rewards are received? Potential Ogmios bug, need to investigate + -- delegate `shouldEqual` Just poolId + + -- Withdraw + do + let + credential = wrap $ PubKeyHashCredential $ unwrap aliceStakePkh + + rewardsAmount <- liftedM "Unable to get rewards" $ + getStakeCredentialDelegationsAndRewards credential <#> + bindFlipped _.rewards + let + plan = + [ WithdrawRewards credential rewardsAmount Nothing ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog + + -- Check rewards. + -- Not going to deregister here, because the rewards are added too + -- soon, and we can't deregister the stake key if there are rewards + -- left. + -- This will not happen in real life scenarios, because epoch are + -- (usually) significantly longer. + do + { rewards: rewardsAfter } <- + liftedM "Unable to get rewards" + $ getPubKeyHashDelegationsAndRewards + $ unwrap aliceStakePkh + rewardsAfter `shouldSatisfy` \after -> after < rewardsBefore + where + config = + defaultTestnetConfig + { clusterConfig = + defaultTestnetConfig.clusterConfig + { slotLength = Seconds 0.05 + , epochSize = Just $ UInt.fromInt 80 + } + -- , suppressLogs = false + } + +withStakeKey :: PrivateStakeKey -> InitialUTxOs -> InitialUTxOsWithStakeKey +withStakeKey = InitialUTxOsWithStakeKey + +privateStakeKeyForDist :: PrivateStakeKey +privateStakeKeyForDist = privateStakeKey diff --git a/test/Plutip/Utils.purs b/test/Testnet/Utils.purs similarity index 80% rename from test/Plutip/Utils.purs rename to test/Testnet/Utils.purs index a02909571d..f9be6991d6 100644 --- a/test/Plutip/Utils.purs +++ b/test/Testnet/Utils.purs @@ -1,4 +1,4 @@ -module Test.Ctl.Plutip.Utils +module Test.Ctl.Testnet.Utils ( submitAndLog , getLockedInputs ) where @@ -7,11 +7,7 @@ import Prelude import Contract.Log (logInfo') import Contract.Monad (Contract) -import Contract.Transaction - ( BalancedSignedTransaction - , awaitTxConfirmed - , submit - ) +import Contract.Transaction (Transaction, awaitTxConfirmed, submit) import Control.Monad.Reader (asks) import Ctl.Internal.Types.UsedTxOuts (TxOutRefCache) import Data.Newtype (unwrap) @@ -21,7 +17,7 @@ import Effect.Ref as Ref -- TODO: Get everything we can about a tx and confirm them -- eg. outputs, metadata, datums, scripts submitAndLog - :: BalancedSignedTransaction -> Contract Unit + :: Transaction -> Contract Unit submitAndLog bsTx = do txId <- submit bsTx logInfo' $ "Tx ID: " <> show txId diff --git a/test/Plutip/UtxoDistribution.purs b/test/Testnet/UtxoDistribution.purs similarity index 75% rename from test/Plutip/UtxoDistribution.purs rename to test/Testnet/UtxoDistribution.purs index fcc796eb1d..a18a91b6dd 100644 --- a/test/Plutip/UtxoDistribution.purs +++ b/test/Testnet/UtxoDistribution.purs @@ -1,10 +1,10 @@ -module Test.Ctl.Plutip.UtxoDistribution +module Test.Ctl.Testnet.UtxoDistribution ( ArbitraryUtxoDistr , assertContract , assertCorrectDistribution , assertNoUtxosAtAddress , assertNoUtxosAtEnterpriseAddress - , assertUtxosAtPlutipWalletAddress + , assertUtxosAtTestnetWalletAddress , checkUtxoDistribution , genInitialUtxo , ppArbitraryUtxoDistr @@ -14,24 +14,26 @@ module Test.Ctl.Plutip.UtxoDistribution import Prelude -import Contract.Address - ( Address - , getNetworkId - , payPubKeyHashEnterpriseAddress +import Cardano.Types + ( BigNum + , Credential(PubKeyHashCredential) + , TransactionInput + , TransactionOutput + , UtxoMap ) +import Cardano.Types.Address (Address(EnterpriseAddress)) +import Cardano.Types.BigNum as BigNum +import Contract.Address (Address, getNetworkId) import Contract.Monad (Contract, liftedM) -import Contract.Test.Plutip +import Contract.Test.Testnet ( class UtxoDistribution , InitialUTxOs , InitialUTxOsWithStakeKey(InitialUTxOsWithStakeKey) - , runPlutipContract + , defaultTestnetConfig + , runTestnetContract , withStakeKey ) -import Contract.Transaction - ( TransactionInput - , TransactionOutputWithRefScript(TransactionOutputWithRefScript) - ) -import Contract.Utxos (UtxoMap, utxosAt) +import Contract.Utxos (utxosAt) import Contract.Value (Value, lovelaceValueOf) import Contract.Wallet ( KeyWallet @@ -41,33 +43,32 @@ import Contract.Wallet , withKeyWallet ) import Control.Lazy (fix) -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Ctl.Internal.Test.UtxoDistribution (encodeDistribution, keyWallets) import Data.Array (foldl, head, replicate, zip) import Data.Array.NonEmpty (fromNonEmpty) as NEArray import Data.Foldable (intercalate) import Data.FoldableWithIndex (foldlWithIndex) import Data.Map (empty, insert, isEmpty) as Map -import Data.Maybe (isJust) -import Data.Newtype (unwrap) +import Data.Maybe (fromJust, isJust) +import Data.Newtype (unwrap, wrap) import Data.NonEmpty ((:|)) import Data.Traversable (for_) import Data.Tuple.Nested (type (/\), (/\)) import Effect.Aff (Aff) import Effect.Class (liftEffect) import Effect.Exception (throw) -import JS.BigInt (BigInt) -import JS.BigInt (fromInt, toString) as BigInt import Mote (group, test) -import Test.Ctl.Plutip.Common (config, privateStakeKey) -import Test.QuickCheck (class Arbitrary, arbitrary) +import Mote.TestPlanM (TestPlanM) +import Partial.Unsafe (unsafePartial) +import Test.Ctl.Testnet.Common (privateStakeKey) +import Test.QuickCheck (class Arbitrary, arbitrary, mkSeed) import Test.QuickCheck.Gen ( Gen , arrayOf , chooseInt , frequency - , randomSample' , resize + , sample , sized ) import Type.Prelude (Proxy(Proxy)) @@ -79,8 +80,9 @@ suite = group "UtxoDistribution" do do let distribution :: Array InitialUTxOs - distribution = replicate 2 [ BigInt.fromInt 1_000_000_000 ] - runPlutipContract config distribution $ checkUtxoDistribution distribution + distribution = replicate 2 [ BigNum.fromInt 1_000_000_000 ] + runTestnetContract defaultTestnetConfig distribution $ + checkUtxoDistribution distribution test "stake key transfers with distribution: stake + [[1000000000,1000000000]]" @@ -88,22 +90,25 @@ suite = group "UtxoDistribution" do let distribution :: Array InitialUTxOsWithStakeKey distribution = withStakeKey privateStakeKey <$> replicate 2 - [ BigInt.fromInt 1_000_000_000 ] - runPlutipContract config distribution $ checkUtxoDistribution distribution + [ BigNum.fromInt 1_000_000_000 ] + runTestnetContract defaultTestnetConfig distribution $ + checkUtxoDistribution distribution test "stake key transfers with distribution: ([[1000000000,1000000000]], stake + [[1000000000,1000000000]])" do let distribution1 :: Array InitialUTxOs - distribution1 = replicate 2 [ BigInt.fromInt 1_000_000_000 ] + distribution1 = replicate 2 [ BigNum.fromInt 1_000_000_000 ] distribution = distribution1 /\ (withStakeKey privateStakeKey <$> distribution1) - runPlutipContract config distribution $ checkUtxoDistribution distribution + runTestnetContract defaultTestnetConfig distribution $ + checkUtxoDistribution distribution - distrs <- liftEffect $ randomSample' 5 arbitrary - for_ distrs $ \distr -> + -- set seed to 5 and size to 10 to fail + let distrs = sample (mkSeed 2) 5 arbitrary + for_ distrs $ \distr -> do test ( "stake key transfers with random distribution: " <> ppArbitraryUtxoDistr distr @@ -111,7 +116,7 @@ suite = group "UtxoDistribution" do $ withArbUtxoDistr distr - \randDistr -> runPlutipContract config randDistr $ + \randDistr -> runTestnetContract defaultTestnetConfig randDistr $ checkUtxoDistribution randDistr checkUtxoDistribution @@ -124,7 +129,7 @@ checkUtxoDistribution distr wallets = do let walletsArray = keyWallets (Proxy :: Proxy distr) wallets walletUtxos = encodeDistribution distr - for_ walletsArray assertUtxosAtPlutipWalletAddress + for_ walletsArray assertUtxosAtTestnetWalletAddress assertCorrectDistribution $ zip walletsArray walletUtxos -- TODO: minimum value of 1 ada is hardcoded, tests become flaky below @@ -133,8 +138,10 @@ checkUtxoDistribution distr wallets = do -- https://github.com/Plutonomicon/cardano-transaction-lib/issues/857 -- is resolved genInitialUtxo :: Gen InitialUTxOs -genInitialUtxo = map (BigInt.fromInt >>> (_ * BigInt.fromInt 1_000_000)) - <$> arrayOf (chooseInt 1 1000) +genInitialUtxo = unsafePartial $ + map + (BigNum.fromInt >>> (_ `BigNum.mul` BigNum.fromInt 1_000_000) >>> fromJust) + <$> arrayOf (chooseInt 1 1000) instance Arbitrary ArbitraryUtxoDistr where arbitrary = @@ -164,7 +171,7 @@ data ArbitraryUtxoDistr | UDTuple ArbitraryUtxoDistr ArbitraryUtxoDistr ppInitialUtxos :: InitialUTxOs -> String -ppInitialUtxos x = "[" <> intercalate ", " (map BigInt.toString x) <> "]" +ppInitialUtxos x = "[" <> intercalate ", " (map BigNum.toString x) <> "]" ppArbitraryUtxoDistr :: ArbitraryUtxoDistr -> String ppArbitraryUtxoDistr = case _ of @@ -191,25 +198,29 @@ withArbUtxoDistr d f = case d of assertContract :: String -> Boolean -> Contract Unit assertContract msg cond = if cond then pure unit else liftEffect $ throw msg --- | For a plutip test wallet, assert that any utxos held by the +-- | For a testnet wallet, assert that any utxos held by the -- | wallet are at the expected address. If the wallet has a stake -- | key, this function assumes the expected address is the base -- | address, otherwise it assumes the expected address is the -- | enterprise address. -assertUtxosAtPlutipWalletAddress +assertUtxosAtTestnetWalletAddress :: KeyWallet -> Contract Unit -assertUtxosAtPlutipWalletAddress wallet = withKeyWallet wallet do +assertUtxosAtTestnetWalletAddress wallet = withKeyWallet wallet do maybeStake <- join <<< head <$> ownStakePubKeyHashes when (isJust maybeStake) $ assertNoUtxosAtEnterpriseAddress wallet assertNoUtxosAtEnterpriseAddress :: KeyWallet -> Contract Unit assertNoUtxosAtEnterpriseAddress wallet = withKeyWallet wallet $ - assertNoUtxosAtAddress =<< liftedM "Could not get wallet address" - ( payPubKeyHashEnterpriseAddress - <$> getNetworkId - <*> liftedM "Could not get payment pubkeyhash" - (head <$> ownPaymentPubKeyHashes) + assertNoUtxosAtAddress =<< + ( EnterpriseAddress <$> + ( { networkId: _, paymentCredential: _ } + <$> getNetworkId + <*> liftedM "Could not get payment pubkeyhash" + ( map (wrap <<< PubKeyHashCredential <<< unwrap) <<< head <$> + ownPaymentPubKeyHashes + ) + ) ) assertNoUtxosAtAddress :: Address -> Contract Unit @@ -245,7 +256,7 @@ assertCorrectDistribution wallets = for_ wallets \(wallet /\ expectedAmounts) -> -- Remove a single utxo containing the expected ada amount, -- returning the updated utxo map and false if it could not be -- found - findAndRemoveExpected :: Boolean /\ UtxoMap -> BigInt -> Boolean /\ UtxoMap + findAndRemoveExpected :: Boolean /\ UtxoMap -> BigNum -> Boolean /\ UtxoMap findAndRemoveExpected o@(false /\ _) _ = o findAndRemoveExpected (_ /\ utxos) expected = foldlWithIndex @@ -259,12 +270,12 @@ assertCorrectDistribution wallets = for_ wallets \(wallet /\ expectedAmounts) -> :: Value -> TransactionInput -> Boolean /\ UtxoMap - -> TransactionOutputWithRefScript + -> TransactionOutput -> Boolean /\ UtxoMap removeUtxoMatchingValue expected i (found /\ m) - o@(TransactionOutputWithRefScript { output }) + output | not found && expected == (unwrap output).amount = true /\ m - | otherwise = found /\ Map.insert i o m + | otherwise = found /\ Map.insert i output m diff --git a/test/Transaction.purs b/test/Transaction.purs deleted file mode 100644 index 6a144d9b64..0000000000 --- a/test/Transaction.purs +++ /dev/null @@ -1,177 +0,0 @@ -module Test.Ctl.Transaction (suite) where - -import Prelude - -import Ctl.Internal.Cardano.Types.Transaction - ( Redeemer(Redeemer) - , ScriptDataHash(ScriptDataHash) - , Transaction(Transaction) - , TransactionWitnessSet(TransactionWitnessSet) - , TxBody(TxBody) - , Vkey(Vkey) - , Vkeywitness(Vkeywitness) - , mkEd25519Signature - , mkPublicKey - ) -import Ctl.Internal.Deserialization.WitnessSet as Deserialization.WitnessSet -import Ctl.Internal.Serialization.WitnessSet as Serialization.WitnessSet -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Transaction - ( attachDatum - , attachPlutusScript - , attachRedeemer - , setScriptDataHash - ) -import Ctl.Internal.Types.ByteArray (byteArrayToHex, hexToByteArrayUnsafe) -import Ctl.Internal.Types.Datum (Datum(Datum)) -import Ctl.Internal.Types.PlutusData (PlutusData(Integer)) -import Ctl.Internal.Types.RedeemerTag (RedeemerTag(Spend)) -import Ctl.Internal.Types.Scripts - ( Language(PlutusV1, PlutusV2) - , PlutusScript(PlutusScript) - ) -import Data.Maybe (Maybe(Just, Nothing), fromJust) -import Data.Newtype (over, unwrap) -import Data.Tuple.Nested ((/\)) -import Effect (Effect) -import Effect.Aff (Aff) -import Effect.Class (liftEffect) -import Effect.Exception (throw) -import JS.BigInt as BigInt -import Mote (group, test) -import Partial.Unsafe (unsafePartial) -import Test.Ctl.Fixtures.CostModels (costModelsFixture1) -import Test.Spec.Assertions (shouldEqual) - -suite :: TestPlanM (Aff Unit) Unit -suite = group "attach datums to tx" $ do - test "datum should be correctly attached" testAttachDatum - test "redeemer should be correctly attached" testAttachRedeemer - test "scripts should be correctly attached (PlutusV1)" $ testAttachScript - PlutusV1 - test "scripts should be correctly attached (PlutusV2)" $ testAttachScript - PlutusV2 - test "scripts data hash should be correctly set" testSetScriptDataHash - test "existing witnesses should be preserved" testPreserveWitness - -testAttachDatum :: Aff Unit -testAttachDatum = liftEffect $ - attachDatum datum tx >>= case _ of - Transaction { witnessSet: TransactionWitnessSet ws } -> - case ws.plutusData of - Just [ pd ] -> do - pd `shouldEqual` unwrap datum - Just _ -> throw "Incorrect number of datums attached" - Nothing -> throw "Datum wasn't attached" - where - tx :: Transaction - tx = mempty - - datum :: Datum - datum = Datum $ Integer $ BigInt.fromInt 1 - -testAttachRedeemer :: Aff Unit -testAttachRedeemer = liftEffect $ do - redeemer <- mkRedeemer datum - attachRedeemer redeemer tx >>= case _ of - Transaction { witnessSet: TransactionWitnessSet ws } -> do - case ws.redeemers of - Just [ r ] -> r `shouldEqual` redeemer - Just _ -> throw "Incorrect number of redeemers attached" - Nothing -> throw "Redeemer wasn't attached" - where - tx :: Transaction - tx = mempty - - datum :: PlutusData - datum = Integer $ BigInt.fromInt 1 - -testAttachScript :: Language -> Aff Unit -testAttachScript language = liftEffect $ - attachPlutusScript script tx >>= case _ of - Transaction { witnessSet: TransactionWitnessSet ws } -> - case ws.plutusScripts of - Just [ ps ] -> ps `shouldEqual` script - Just _ -> throw "Incorrect number of scripts attached" - Nothing -> throw "Script wasn't attached" - where - tx :: Transaction - tx = mempty - - script :: PlutusScript - script = PlutusScript $ hexToByteArrayUnsafe "4e4d01000033222220051200120011" - /\ language - -testSetScriptDataHash :: Aff Unit -testSetScriptDataHash = liftEffect $ do - redeemer <- mkRedeemer datum2 - Transaction { body: TxBody body } <- - setScriptDataHash costModelsFixture1 [ redeemer ] [ datum1 ] tx - case body.scriptDataHash of - Nothing -> throw "Script data hash wasn't set" - Just (ScriptDataHash sdh) -> - -- TODO - -- Verify the hash with some external tool - byteArrayToHex sdh - `shouldEqual` - "dde4d4f89151fdbcea51fa4e9edcac89d69febe036a4976b643c713c19b0cad1" - where - tx :: Transaction - tx = mempty - - datum1 :: Datum - datum1 = Datum $ Integer $ BigInt.fromInt 1 - - datum2 :: PlutusData - datum2 = Integer $ BigInt.fromInt 2 - -testPreserveWitness :: Aff Unit -testPreserveWitness = liftEffect $ do - Transaction { witnessSet: TransactionWitnessSet { plutusData, vkeys } } <- - attachDatum datum tx - case plutusData /\ vkeys of - Just [ pd ] /\ Just vs@[ _ ] -> do - pd `shouldEqual` unwrap datum - vk' <- Deserialization.WitnessSet.convertVkeyWitnesses <$> - Serialization.WitnessSet.convertVkeywitnesses vs - - vk' `shouldEqual` [ vk ] - Just _ /\ Just _ -> throw "Incorrect number of witnesses" - Nothing /\ _ -> throw "Datum wasn't attached" - _ /\ Nothing -> throw "Vkey witness wasn't preserved" - where - tx :: Transaction - tx = over Transaction _ { witnessSet = initialWitnessSet } - $ mempty - - datum :: Datum - datum = Datum $ Integer $ BigInt.fromInt 1 - - initialWitnessSet :: TransactionWitnessSet - initialWitnessSet = over TransactionWitnessSet _ { vkeys = Just [ vk ] } - $ mempty - - vk :: Vkeywitness - vk = Vkeywitness - ( Vkey - ( unsafePartial $ fromJust <<< mkPublicKey $ - "ed25519_pk1p9sf9wz3t46u9ghht44203gerxt82kzqaqw74fqrmwjmdy8sjxmqknzq8j" - ) - /\ - ( unsafePartial $ fromJust <<< mkEd25519Signature $ - "ed25519_sig1clmhgxx9e9t24wzgkmcsr44uq98j935evsjnrj8nn7ge08qrz0mgdx\ - \v5qtz8dyghs47q3lxwk4akq3u2ty8v4egeqvtl02ll0nfcqqq6faxl6" - ) - ) - -mkRedeemer :: PlutusData -> Effect Redeemer -mkRedeemer pd = do - pure $ Redeemer - { tag: Spend - , index: BigInt.fromInt 0 - , data: pd - , exUnits: - { mem: BigInt.fromInt 7000000 - , steps: BigInt.fromInt 300000000 - } - } diff --git a/test/Types/Interval.purs b/test/Types/Interval.purs index 3ec7e5b9c7..478be40f0e 100644 --- a/test/Types/Interval.purs +++ b/test/Types/Interval.purs @@ -7,12 +7,11 @@ module Test.Ctl.Types.Interval import Prelude import Aeson (class DecodeAeson, decodeJsonString, printJsonDecodeError) +import Cardano.Types (Slot(Slot)) +import Cardano.Types.BigNum (fromInt) as BigNum import Control.Monad.Error.Class (liftEither) import Control.Monad.Except (throwError) import Ctl.Internal.QueryM.Ogmios (OgmiosEraSummaries, OgmiosSystemStart) -import Ctl.Internal.Serialization.Address (Slot(Slot)) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.BigNum (fromInt) as BigNum import Ctl.Internal.Types.EraSummaries (EraSummaries) import Ctl.Internal.Types.Interval ( Interval @@ -41,6 +40,7 @@ import Effect (Effect) import Effect.Exception (error) import JS.BigInt (fromInt, fromString) as BigInt import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Node.Encoding (Encoding(UTF8)) import Node.FS.Sync (readTextFile) import Node.Path (concat) as Path @@ -52,7 +52,7 @@ import Test.Spec.Assertions (shouldEqual) suite :: TestPlanM (EraSummaries -> SystemStart -> Effect Unit) Unit suite = do group "Interval" do - group "EraSumaries related" do + group "EraSummaries related" do test "Inverse posixTimeToSlot >>> slotToPosixTime " testPosixTimeToSlot test "Inverse slotToPosixTime >>> posixTimeToSlot " testSlotToPosixTime test "PosixTimeToSlot errors" testPosixTimeToSlotError @@ -87,14 +87,14 @@ eraSummariesFixture :: Effect EraSummaries eraSummariesFixture = do { result } :: { result :: OgmiosEraSummaries } <- loadOgmiosFixture "queryLedgerState-eraSummaries" - "d8b19110b9580cddfa3895eea34c2139" + "8073a8f378e969384ec52010ec6c290c" pure $ unwrap result systemStartFixture :: Effect SystemStart systemStartFixture = do { result } :: { result :: OgmiosSystemStart } <- loadOgmiosFixture "queryNetwork-startTime" - "02fa6f9e7ed04ebfe3294c7648be54d5" + "5185237542c7c8a6810aeb0fe74b3b40" pure $ unwrap result testPosixTimeToSlot :: EraSummaries -> SystemStart -> Effect Unit diff --git a/test/Types/Ipv6.purs b/test/Types/Ipv6.purs index 69eb97e19d..dbf8404b47 100644 --- a/test/Types/Ipv6.purs +++ b/test/Types/Ipv6.purs @@ -4,12 +4,13 @@ module Test.Ctl.Types.Ipv6 import Prelude -import Contract.Prim.ByteArray (hexToByteArray) -import Ctl.Internal.Cardano.Types.Transaction (Ipv6(Ipv6)) +import Cardano.AsCbor (decodeCbor) import Ctl.Internal.QueryM.Ogmios (parseIpv6String) -import Ctl.Internal.Test.TestPlanM (TestPlanM) +import Data.ByteArray (hexToByteArrayUnsafe) +import Data.Newtype (wrap) import Effect.Aff (Aff) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.Spec.Assertions (shouldEqual) suite :: TestPlanM (Aff Unit) Unit @@ -26,4 +27,5 @@ suite = do testIpv6 :: String -> String -> TestPlanM (Aff Unit) Unit testIpv6 str expected = test str do - parseIpv6String str `shouldEqual` (Ipv6 <$> hexToByteArray expected) + parseIpv6String str `shouldEqual` + (decodeCbor (wrap $ hexToByteArrayUnsafe expected)) diff --git a/test/Types/TokenName.purs b/test/Types/TokenName.purs index 8ce938451c..cc8dfcc45d 100644 --- a/test/Types/TokenName.purs +++ b/test/Types/TokenName.purs @@ -2,13 +2,13 @@ module Test.Ctl.Types.TokenName (suite) where import Prelude -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.ByteArray (hexToByteArrayUnsafe) -import Ctl.Internal.Types.TokenName (mkTokenName) +import Cardano.Types.AssetName (mkAssetName) +import Data.ByteArray (hexToByteArrayUnsafe) import Data.Maybe (isJust) import Data.Traversable (for_) import Effect.Aff (Aff) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.Ctl.Utils (toFromAesonTest) import Test.Spec.Assertions (shouldSatisfy) @@ -25,10 +25,10 @@ suite = do mayTkName `shouldSatisfy` isJust toFromAesonTest "Should roundtrip successfully" mayTkName toFromAesonTest "\\NUL\\NUL\\NUL Should roundtrip successfully" - (mkTokenNameFromHex "\x0\x0\x0") + (mkAssetNameFromHex "\x0\x0\x0") where - mkTokenNameFromHex = mkTokenName <<< hexToByteArrayUnsafe - tkNamesWithInvalidUtf8 = mkTokenNameFromHex <$> + mkAssetNameFromHex = mkAssetName <<< hexToByteArrayUnsafe + tkNamesWithInvalidUtf8 = mkAssetNameFromHex <$> [ "388178ead6628e2ff3faae2148ec906eb686b3661549c8581cd427433ffd9cf3" -- NOTE: Adopted from https://www.php.net/manual/en/reference.pcre.pattern.modifiers.php#54805 , "c328" diff --git a/test/Types/Transaction.purs b/test/Types/Transaction.purs index 1df2ff00e4..7aec88e05b 100644 --- a/test/Types/Transaction.purs +++ b/test/Types/Transaction.purs @@ -12,16 +12,15 @@ import Aeson ) import Contract.Transaction ( TransactionInput - , TransactionOutputWithRefScript ) import Control.Monad.Error.Class (liftEither) -import Ctl.Internal.Test.TestPlanM (TestPlanM) import Data.Bifunctor (lmap) import Effect (Effect) import Effect.Aff (Aff) import Effect.Class (liftEffect) import Effect.Exception (error) import Mote (group) +import Mote.TestPlanM (TestPlanM) import Node.Encoding (Encoding(UTF8)) import Node.FS.Sync (readTextFile) import Node.Path (concat) as Path @@ -42,10 +41,6 @@ loadAesonFixture filename = do transactionInputFixture :: Effect TransactionInput transactionInputFixture = loadAesonFixture "TransactionInput" -transactionOutputWithRefScriptFixture :: Effect TransactionOutputWithRefScript -transactionOutputWithRefScriptFixture = loadAesonFixture - "TransactionOutputWithRefScript" - toFromAesonTest' :: forall a . Eq a @@ -63,5 +58,3 @@ suite :: TestPlanM (Aff Unit) Unit suite = do group "Transaction-related Aeson representation tests" do toFromAesonTest' "TransactionInput" transactionInputFixture - toFromAesonTest' "TransactionOutputWithRefScript" - transactionOutputWithRefScriptFixture diff --git a/test/Unit.purs b/test/Unit.purs index a1b7daf913..4250ac8a53 100644 --- a/test/Unit.purs +++ b/test/Unit.purs @@ -14,35 +14,28 @@ import Mote.Monad (mapTest) import Test.Ctl.ApplyArgs as ApplyArgs import Test.Ctl.Blockfrost.Aeson.Suite as Blockfrost.Aeson import Test.Ctl.Blockfrost.ProtocolParameters as Blockfrost.ProtocolParameters -import Test.Ctl.ByteArray as ByteArray import Test.Ctl.CoinSelection as CoinSelection +import Test.Ctl.CslGc as CslGc import Test.Ctl.Data as Data import Test.Ctl.Data.Interval as Ctl.Data.Interval -import Test.Ctl.Deserialization as Deserialization import Test.Ctl.E2E.Route as E2E.Route import Test.Ctl.Hashing as Hashing -import Test.Ctl.Internal.Plutus.Conversion.Address as Plutus.Conversion.Address -import Test.Ctl.Internal.Plutus.Conversion.Value as Plutus.Conversion.Value import Test.Ctl.Internal.Plutus.Time as Plutus.Time -import Test.Ctl.Metadata.Cip25 as Cip25 -import Test.Ctl.MustSpendTotal as MustSpendTotal import Test.Ctl.NativeScript as NativeScript -import Test.Ctl.Ogmios.Address as Ogmios.Address import Test.Ctl.Ogmios.Aeson as Ogmios.Aeson import Test.Ctl.Ogmios.EvaluateTx as Ogmios.EvaluateTx import Test.Ctl.Partition as Partition import Test.Ctl.ProtocolParams as ProtocolParams import Test.Ctl.Serialization as Serialization -import Test.Ctl.Serialization.Address as Serialization.Address import Test.Ctl.Serialization.Hash as Serialization.Hash -import Test.Ctl.Transaction as Transaction +import Test.Ctl.Testnet.DistributeFunds as Testnet.DistributeFunds +import Test.Ctl.Testnet.DistributeFundsV2 as Testnet.DistributeFundsV2 import Test.Ctl.Types.Interval as Types.Interval import Test.Ctl.Types.Ipv6 as Ipv6 import Test.Ctl.Types.TokenName as Types.TokenName import Test.Ctl.Types.Transaction as Types.Transaction import Test.Ctl.UsedTxOuts as UsedTxOuts import Test.Ctl.Wallet.Bip32 as Bip32 -import Test.Ctl.Wallet.Cip30.SignData as Cip30SignData import Test.Spec.Runner (defaultConfig) -- Run with `spago test --main Test.Ctl.Unit` @@ -55,26 +48,20 @@ main = interruptOnSignal SIGINT =<< launchAff do testPlan :: TestPlanM (Aff Unit) Unit testPlan = do + Testnet.DistributeFunds.suite + Testnet.DistributeFundsV2.suite ApplyArgs.suite Ipv6.suite NativeScript.suite Bip32.suite - ByteArray.suite - Cip25.suite - Cip30SignData.suite + CslGc.suite Data.suite - Deserialization.suite Hashing.suite Partition.suite - Plutus.Conversion.Address.suite - Plutus.Conversion.Value.suite Plutus.Time.suite Serialization.suite - Serialization.Address.suite Serialization.Hash.suite - Transaction.suite UsedTxOuts.suite - Ogmios.Address.suite Ogmios.Aeson.suite Ogmios.EvaluateTx.suite ProtocolParams.suite @@ -87,5 +74,4 @@ testPlan = do f <$> Types.Interval.eraSummariesFixture <*> Types.Interval.systemStartFixture E2E.Route.suite - MustSpendTotal.suite CoinSelection.suite diff --git a/test/UsedTxOuts.purs b/test/UsedTxOuts.purs index 8d1d8c1d97..667278b6c3 100644 --- a/test/UsedTxOuts.purs +++ b/test/UsedTxOuts.purs @@ -2,10 +2,9 @@ module Test.Ctl.UsedTxOuts (suite) where import Prelude +import Cardano.Types (Transaction) +import Cardano.Types.TransactionHash (TransactionHash) import Control.Monad.Reader (runReaderT) -import Ctl.Internal.Cardano.Types.Transaction (Transaction) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.Transaction (TransactionHash) import Ctl.Internal.Types.UsedTxOuts ( isTxOutRefUsed , lockTransactionInputs @@ -17,17 +16,13 @@ import Data.Array (any, singleton, uncons) import Data.Foldable (all) import Data.Maybe (fromJust) import Data.Newtype (unwrap) -import Data.Set (fromFoldable) as Set import Data.Traversable (traverse) import Data.UInt (UInt) import Effect.Aff (Aff) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) -import Test.Ctl.Fixtures - ( mkSampleTx - , mkTxInput - , txFixture1 - ) +import Test.Ctl.Fixtures (mkSampleTx, mkTxInput, txFixture1) import Test.Spec.Assertions (shouldReturn) buildSampleTransaction @@ -89,7 +84,7 @@ buildSampleTransaction = } ] in - { tx: mkSampleTx txFixture1 (_ { inputs = Set.fromFoldable usedTxOutRefs }) + { tx: mkSampleTx txFixture1 (_ { inputs = usedTxOutRefs }) , usedTxOutRefs: unwrap <$> usedTxOutRefs , unusedTxOutRefs: unwrap <$> unusedTxOutRefs } diff --git a/test/Utils.purs b/test/Utils.purs index fe50406303..d262017eb9 100644 --- a/test/Utils.purs +++ b/test/Utils.purs @@ -10,6 +10,7 @@ module Test.Ctl.Utils , readAeson , toFromAesonTest , toFromAesonTestWith + , fromBytesEffect ) where import Prelude @@ -23,19 +24,23 @@ import Aeson , encodeAeson , parseJsonStringToAeson ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) +import Cardano.Serialization.Lib (class IsBytes, fromBytes) +import Cardano.Serialization.Lib.Internal (class IsCsl) +import Data.ByteArray (ByteArray) import Data.DateTime.Instant (unInstant) import Data.Either (Either(Right), either) import Data.Maybe (Maybe(Just, Nothing), maybe) import Data.Newtype (unwrap, wrap) import Data.Time.Duration (class Duration, Milliseconds, Seconds) import Data.Time.Duration (fromDuration, toDuration) as Duration +import Effect (Effect) import Effect.Aff (Aff, error) import Effect.Class (class MonadEffect, liftEffect) import Effect.Console (log) import Effect.Exception (throw, throwException) import Effect.Now (now) import Mote (test) +import Mote.TestPlanM (TestPlanM) import Node.Encoding (Encoding(UTF8)) import Node.FS.Sync (readTextFile) import Node.Path (FilePath) @@ -163,3 +168,10 @@ aesonRoundTrip = aesonRoundTripWith identity readAeson :: forall (m :: Type -> Type). MonadEffect m => FilePath -> m Aeson readAeson = errEither <<< parseJsonStringToAeson <=< liftEffect <<< readTextFile UTF8 + +fromBytesEffect + :: forall (a :: Type). IsCsl a => IsBytes a => ByteArray -> Effect a +fromBytesEffect bytes = + case fromBytes bytes of + Nothing -> throw "from_bytes() call failed" + Just a -> pure a diff --git a/test/Utils/DrainWallets.purs b/test/Utils/DrainWallets.purs index 6e61639c4c..c762cc7cad 100644 --- a/test/Utils/DrainWallets.purs +++ b/test/Utils/DrainWallets.purs @@ -40,6 +40,7 @@ import Data.Maybe (Maybe(Nothing)) import Data.Newtype (unwrap, wrap) import Data.String (joinWith) import Data.Traversable (for) +import Data.Tuple.Nested ((/\)) import Data.UInt as UInt import Effect (Effect) import Effect.Aff (Aff, launchAff_) @@ -79,7 +80,7 @@ run privateKey walletsDir = runContract config do ( privateStakeKeyFromFile $ Path.concat [ walletsDir, walletFolder, "stake_signing_key" ] ) - pure $ privateKeysToKeyWallet payment mbStake + pure $ privateKeysToKeyWallet payment mbStake Nothing let merge r = @@ -120,9 +121,9 @@ run privateKey walletsDir = runContract config do <> foldMap (_.pkh >>> mustBeSignedBy) usedWallets lookups = unspentOutputs utxos - unbalancedTx <- mkUnbalancedTx lookups constraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx + balancedTx <- balanceTx unbalancedTx usedUtxos mempty balancedSignedTx <- Array.foldM (\tx wallet -> withKeyWallet wallet $ signTransaction tx) (wrap $ unwrap balancedTx) @@ -135,6 +136,7 @@ run privateKey walletsDir = runContract config do { walletSpec = pure $ UseKeys (PrivatePaymentKeyFile privateKey) Nothing + Nothing , backendParams = mkCtlBackendParams { ogmiosConfig: defaultOgmiosWsConfig , kupoConfig: diff --git a/src/Internal/Hashing.js b/test/Utils/Hashing.js similarity index 76% rename from src/Internal/Hashing.js rename to test/Utils/Hashing.js index 0b647d6da4..24d90e1815 100644 --- a/src/Internal/Hashing.js +++ b/test/Utils/Hashing.js @@ -1,17 +1,7 @@ -/* global BROWSER_RUNTIME */ - import Blake2 from "blakejs"; - import SHA256 from "jssha/sha256"; import SHA3 from "jssha/sha3"; -let lib; -if (typeof BROWSER_RUNTIME != "undefined" && BROWSER_RUNTIME) { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-browser"); -} else { - lib = await import("@mlabs-haskell/cardano-serialization-lib-gc-nodejs"); -} - export function blake2b224Hash(bytesToHash) { return Blake2.blake2b(bytesToHash, null, 28); } @@ -28,14 +18,6 @@ export function blake2b256HashHex(bytesToHash) { return Blake2.blake2bHex(bytesToHash, null, 32); } -export function hashPlutusData(plutusData) { - return lib.hash_plutus_data(plutusData); -} - -export function hashPlutusScript(script) { - return script.hash(); -} - const SHA256_HASH_VARIANT = "SHA-256"; const SHA3_256_HASH_VARIANT = "SHA3-256"; diff --git a/test/Utils/Hashing.purs b/test/Utils/Hashing.purs new file mode 100644 index 0000000000..56886efe44 --- /dev/null +++ b/test/Utils/Hashing.purs @@ -0,0 +1,75 @@ +module Test.Ctl.Internal.Hashing + ( blake2b224Hash + , blake2b224HashHex + , blake2b256Hash + , blake2b256HashHex + , plutusDataHash + , md5HashHex + , plutusScriptHash + , scriptRefHash + , sha256Hash + , sha256HashHex + , sha3_256Hash + , sha3_256HashHex + ) where + +import Prelude + +import Cardano.Serialization.Lib + ( hashPlutusData + , nativeScript_hash + , plutusScript_hash + ) +import Cardano.Types.DataHash (DataHash) +import Cardano.Types.NativeScript (NativeScript) +import Cardano.Types.NativeScript as NativeScript +import Cardano.Types.PlutusData (PlutusData) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.PlutusScript (PlutusScript) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.ScriptHash (ScriptHash) +import Cardano.Types.ScriptRef + ( ScriptRef(NativeScriptRef, PlutusScriptRef) + ) +import Data.ByteArray (ByteArray) +import Data.Newtype (wrap) +import Effect (Effect) +import Node.Buffer (fromString, toString) as Buffer +import Node.Crypto.Hash (createHash, digest, update) as Hash +import Node.Encoding (Encoding(Hex, UTF8)) + +foreign import blake2b224Hash :: ByteArray -> ByteArray + +foreign import blake2b224HashHex :: ByteArray -> String + +foreign import blake2b256Hash :: ByteArray -> ByteArray + +foreign import blake2b256HashHex :: ByteArray -> String + +foreign import sha256Hash :: ByteArray -> ByteArray + +foreign import sha256HashHex :: ByteArray -> String + +foreign import sha3_256Hash :: ByteArray -> ByteArray + +foreign import sha3_256HashHex :: ByteArray -> String + +md5HashHex :: String -> Effect String +md5HashHex contents = do + buf <- Buffer.fromString contents UTF8 + digest <- Hash.createHash "md5" >>= Hash.update buf >>= Hash.digest + Buffer.toString Hex digest + +plutusDataHash :: PlutusData -> DataHash +plutusDataHash = + wrap <<< hashPlutusData <<< PlutusData.toCsl + +plutusScriptHash :: PlutusScript -> ScriptHash +plutusScriptHash = wrap <<< plutusScript_hash <<< PlutusScript.toCsl + +nativeScriptHash :: NativeScript -> ScriptHash +nativeScriptHash = wrap <<< nativeScript_hash <<< NativeScript.toCsl + +scriptRefHash :: ScriptRef -> ScriptHash +scriptRefHash (PlutusScriptRef plutusScript) = plutusScriptHash plutusScript +scriptRefHash (NativeScriptRef nativeScript) = nativeScriptHash nativeScript diff --git a/test/Wallet/Bip32.purs b/test/Wallet/Bip32.purs index 22e5e1ac19..074f841254 100644 --- a/test/Wallet/Bip32.purs +++ b/test/Wallet/Bip32.purs @@ -4,20 +4,18 @@ module Test.Ctl.Wallet.Bip32 import Contract.Prelude +import Cardano.Types.Address as Address +import Cardano.Types.NetworkId (NetworkId(MainnetId)) +import Cardano.Wallet.Key (KeyWallet) import Contract.Wallet.Key ( StakeKeyPresence(WithStakeKey) , mkKeyWalletFromMnemonic ) -import Ctl.Internal.Serialization.Address - ( NetworkId(MainnetId) - , addressFromBech32 - ) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Wallet.Key (KeyWallet(KeyWallet)) import Data.Lens (_Left, preview) import Data.UInt as UInt import Effect.Aff (Aff) import Mote (group, test) +import Mote.TestPlanM (TestPlanM) import Test.Spec.Assertions (shouldEqual) suite :: TestPlanM (Aff Unit) Unit @@ -33,15 +31,19 @@ suite = do <> ")" ) do - addressFromBech32 addressStr `shouldEqual` - hush - ( mkKeyWalletFromMnemonic phrase1 + addr <- liftAff $ do + case + ( hush $ mkKeyWalletFromMnemonic phrase1 { accountIndex: UInt.fromInt accountIndex , addressIndex: UInt.fromInt addressIndex } - WithStakeKey <#> - \(KeyWallet wallet) -> wallet.address MainnetId + WithStakeKey ) + of + Nothing -> pure Nothing + Just (wlt :: KeyWallet) -> do + Just <$> (unwrap wlt).address MainnetId + Address.fromBech32 addressStr `shouldEqual` addr group "Invalid mnemonics" do test "handles errors for invalid phrases" do blush (mkKeyWalletFromMnemonic invalidPhrase zero WithStakeKey) diff --git a/test/Wallet/Cip30/SignData.purs b/test/Wallet/Cip30/SignData.purs deleted file mode 100644 index c9c9e09396..0000000000 --- a/test/Wallet/Cip30/SignData.purs +++ /dev/null @@ -1,230 +0,0 @@ -module Test.Ctl.Wallet.Cip30.SignData - ( suite - , COSEKey - , COSESign1 - , checkCip30SignDataResponse - ) where - -import Prelude - -import Ctl.Internal.Deserialization.FromBytes (fromBytes) -import Ctl.Internal.Deserialization.Keys (privateKeyFromBytes) -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Ctl.Internal.Serialization.Address - ( Address - , NetworkId(MainnetId) - , intToNetworkId - ) -import Ctl.Internal.Serialization.Keys - ( bytesFromPublicKey - , publicKeyFromPrivateKey - ) -import Ctl.Internal.Serialization.ToBytes (toBytes) -import Ctl.Internal.Serialization.Types (PrivateKey, PublicKey) -import Ctl.Internal.Test.TestPlanM (TestPlanM) -import Ctl.Internal.Types.ByteArray (byteArrayFromIntArrayUnsafe) -import Ctl.Internal.Types.CborBytes (CborBytes) -import Ctl.Internal.Types.RawBytes (RawBytes) -import Ctl.Internal.Wallet.Cip30 (DataSignature) -import Ctl.Internal.Wallet.Cip30.SignData (signData) -import Ctl.Internal.Wallet.Key - ( PrivatePaymentKey - , PrivateStakeKey - , privateKeysToAddress - ) -import Data.Maybe (Maybe(Just), fromJust, fromMaybe) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Traversable (traverse_) -import Effect (Effect) -import Effect.Aff (Aff) -import Effect.Class (liftEffect) -import Mote (group, test) -import Partial.Unsafe (unsafePartial) -import Test.Ctl.Utils (assertTrue, errMaybe) -import Test.QuickCheck.Arbitrary (class Arbitrary, arbitrary) -import Test.QuickCheck.Gen (Gen, chooseInt, randomSample, vectorOf) - -suite :: TestPlanM (Aff Unit) Unit -suite = - group "signData (CIP-30)" do - test "generates a valid signature and key for a given payload" do - traverse_ testCip30SignData =<< liftEffect (randomSample arbitrary) - --------------------------------------------------------------------------------- --- Tests --------------------------------------------------------------------------------- - -type TestInput = - { privateKey :: ArbitraryPrivatePaymentKey - , privateStakeKey :: Maybe ArbitraryPrivateStakeKey - , payload :: RawBytes - , networkId :: ArbitraryNetworkId - } - -type DeserializedDataSignature = - { coseKey :: COSEKey - , coseSign1 :: COSESign1 - } - -testCip30SignData :: TestInput -> Aff Unit -testCip30SignData { privateKey, privateStakeKey, payload, networkId } = do - let - address = privateKeysToAddress (unwrap privateKey) - (unwrap <$> privateStakeKey) - (unwrap networkId) - - dataSignature <- liftEffect $ signData privatePaymentKey address payload - { coseKey } <- checkCip30SignDataResponse address dataSignature - - assertTrue "COSE_Key's x (-2) header must be set to public key bytes" - (getCoseKeyHeaderX coseKey == Just (bytesFromPublicKey publicPaymentKey)) - where - privatePaymentKey :: PrivateKey - privatePaymentKey = unwrap $ unwrap $ privateKey - - publicPaymentKey :: PublicKey - publicPaymentKey = publicKeyFromPrivateKey privatePaymentKey - -checkCip30SignDataResponse - :: Address -> DataSignature -> Aff DeserializedDataSignature -checkCip30SignDataResponse address { key, signature } = do - coseSign1 <- liftEffect $ fromBytesCoseSign1 signature - coseKey <- liftEffect $ fromBytesCoseKey key - - checkCoseSign1ProtectedHeaders coseSign1 - checkCoseKeyHeaders coseKey - checkKidHeaders coseSign1 coseKey - liftEffect $ checkVerification coseSign1 coseKey - pure { coseKey, coseSign1 } - where - checkCoseSign1ProtectedHeaders :: COSESign1 -> Aff Unit - checkCoseSign1ProtectedHeaders coseSign1 = do - assertTrue "COSE_Sign1's alg (1) header must be set to EdDSA (-8)" - (getCoseSign1ProtectedHeaderAlg coseSign1 == Just (-8)) - - assertTrue "COSE_Sign1's \"address\" header must be set to address bytes" - ( getCoseSign1ProtectedHeaderAddress coseSign1 - == Just (toBytes address) - ) - - checkCoseKeyHeaders :: COSEKey -> Aff Unit - checkCoseKeyHeaders coseKey = do - assertTrue "COSE_Key's kty (1) header must be set to OKP (1)" - (getCoseKeyHeaderKty coseKey == Just 1) - - assertTrue "COSE_Key's alg (3) header must be set to EdDSA (-8)" - (getCoseKeyHeaderAlg coseKey == Just (-8)) - - assertTrue "COSE_Key's crv (-1) header must be set to Ed25519 (6)" - (getCoseKeyHeaderCrv coseKey == Just (6)) - - checkKidHeaders :: COSESign1 -> COSEKey -> Aff Unit - checkKidHeaders coseSign1 coseKey = - assertTrue - "COSE_Sign1's kid (4) and COSE_Key's kid (2) headers, if present, must \ - \be set to the same value" - (getCoseSign1ProtectedHeaderKid coseSign1 == getCoseKeyHeaderKid coseKey) - - checkVerification :: COSESign1 -> COSEKey -> Effect Unit - checkVerification coseSign1 coseKey = do - publicKey <- - errMaybe "COSE_Key's x (-2) header must be set to public key bytes" - $ getCoseKeyHeaderX coseKey >>= fromBytes <<< wrap <<< unwrap - sigStructBytes <- getSignedData coseSign1 - assertTrue "Signature verification failed" - =<< verifySignature coseSign1 publicKey sigStructBytes - --------------------------------------------------------------------------------- --- Arbitrary --------------------------------------------------------------------------------- - -newtype ArbitraryPrivatePaymentKey = - ArbitraryPrivatePaymentKey PrivatePaymentKey - -derive instance Newtype ArbitraryPrivatePaymentKey _ - -instance Arbitrary ArbitraryPrivatePaymentKey where - arbitrary = - wrap <<< wrap <<< unwrap <$> (arbitrary :: Gen ArbitraryPrivateKey) - -newtype ArbitraryPrivateStakeKey = ArbitraryPrivateStakeKey PrivateStakeKey - -derive instance Newtype ArbitraryPrivateStakeKey _ - -instance Arbitrary ArbitraryPrivateStakeKey where - arbitrary = - wrap <<< wrap <<< unwrap <$> (arbitrary :: Gen ArbitraryPrivateKey) - -newtype ArbitraryPrivateKey = ArbitraryPrivateKey PrivateKey - -derive instance Newtype ArbitraryPrivateKey _ - -instance Arbitrary ArbitraryPrivateKey where - arbitrary = - wrap <<< unsafePartial fromJust <<< privateKeyFromBytes <$> privateKeyBytes - where - privateKeyBytes :: Gen RawBytes - privateKeyBytes = - wrap <<< byteArrayFromIntArrayUnsafe <$> vectorOf 32 (chooseInt 0 255) - -newtype ArbitraryNetworkId = ArbitraryNetworkId NetworkId - -derive instance Newtype ArbitraryNetworkId _ - -instance Arbitrary ArbitraryNetworkId where - arbitrary = - wrap <<< fromMaybe MainnetId <<< intToNetworkId <$> chooseInt 0 1 - --------------------------------------------------------------------------------- --- FFI --------------------------------------------------------------------------------- - -foreign import data COSESign1 :: Type -foreign import _getCoseSign1ProtectedHeaderAlg - :: MaybeFfiHelper -> COSESign1 -> Maybe Int - -foreign import _getCoseSign1ProtectedHeaderAddress - :: MaybeFfiHelper -> COSESign1 -> Maybe CborBytes - -foreign import _getCoseSign1ProtectedHeaderKid - :: MaybeFfiHelper -> COSESign1 -> Maybe RawBytes - -foreign import data COSEKey :: Type -foreign import _getCoseKeyHeaderKty :: MaybeFfiHelper -> COSEKey -> Maybe Int -foreign import _getCoseKeyHeaderAlg :: MaybeFfiHelper -> COSEKey -> Maybe Int -foreign import _getCoseKeyHeaderCrv :: MaybeFfiHelper -> COSEKey -> Maybe Int -foreign import _getCoseKeyHeaderX :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes -foreign import _getCoseKeyHeaderKid - :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes - -foreign import fromBytesCoseSign1 :: CborBytes -> Effect COSESign1 -foreign import fromBytesCoseKey :: CborBytes -> Effect COSEKey - -foreign import getSignedData :: COSESign1 -> Effect CborBytes -foreign import verifySignature - :: COSESign1 -> PublicKey -> CborBytes -> Effect Boolean - -getCoseSign1ProtectedHeaderAlg :: COSESign1 -> Maybe Int -getCoseSign1ProtectedHeaderAlg = _getCoseSign1ProtectedHeaderAlg maybeFfiHelper - -getCoseSign1ProtectedHeaderAddress :: COSESign1 -> Maybe CborBytes -getCoseSign1ProtectedHeaderAddress = - _getCoseSign1ProtectedHeaderAddress maybeFfiHelper - -getCoseSign1ProtectedHeaderKid :: COSESign1 -> Maybe RawBytes -getCoseSign1ProtectedHeaderKid = _getCoseSign1ProtectedHeaderKid maybeFfiHelper - -getCoseKeyHeaderKty :: COSEKey -> Maybe Int -getCoseKeyHeaderKty = _getCoseKeyHeaderKty maybeFfiHelper - -getCoseKeyHeaderAlg :: COSEKey -> Maybe Int -getCoseKeyHeaderAlg = _getCoseKeyHeaderAlg maybeFfiHelper - -getCoseKeyHeaderCrv :: COSEKey -> Maybe Int -getCoseKeyHeaderCrv = _getCoseKeyHeaderCrv maybeFfiHelper - -getCoseKeyHeaderX :: COSEKey -> Maybe RawBytes -getCoseKeyHeaderX = _getCoseKeyHeaderX maybeFfiHelper - -getCoseKeyHeaderKid :: COSEKey -> Maybe RawBytes -getCoseKeyHeaderKid = _getCoseKeyHeaderKid maybeFfiHelper diff --git a/test/e2e.env b/test/e2e.env index 7b8163794c..8b0cc2d87f 100755 --- a/test/e2e.env +++ b/test/e2e.env @@ -87,7 +87,8 @@ export E2E_SETTINGS_ARCHIVE_URL="https://github.com/mlabs-haskell/ctl-e2e-assets export E2E_TEST_TIMEOUT=200 export E2E_BROWSER=chromium -export E2E_NO_HEADLESS=false +export E2E_NO_HEADLESS=true +export E2E_PASS_BROWSER_LOGS=false export E2E_EXTRA_BROWSER_ARGS="--disable-web-security" # Bypass CORS for Kupo # Port numbers used by services when testing with Plutip diff --git a/webpack.config.cjs b/webpack.config.cjs index 31f7f3ba7c..e3a4280e2a 100644 --- a/webpack.config.cjs +++ b/webpack.config.cjs @@ -14,6 +14,7 @@ module.exports = env => { layers: false, lazyCompilation: false, outputModule: true, + // `syncWebAssembly` must be set to `true` because CTL internal code expects it. syncWebAssembly: true, topLevelAwait: true }, @@ -58,9 +59,6 @@ module.exports = env => { }, plugins: [ - new webpack.DefinePlugin({ - BROWSER_RUNTIME: isBrowser - }), new webpack.LoaderOptionsPlugin({ debug: true }),