From a999546ededa6729bb6b23b7df0441e966f26623 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Wed, 14 Aug 2024 11:16:08 +0800 Subject: [PATCH 01/20] add contract forked frmo jpg store --- .gitignore | 137 +----- contract.hl | 218 ++++++++++ package-lock.json | 1028 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 21 + tests/fixtures.ts | 0 tests/txTests.ts | 19 + 6 files changed, 1294 insertions(+), 129 deletions(-) create mode 100644 contract.hl create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 tests/fixtures.ts create mode 100644 tests/txTests.ts diff --git a/.gitignore b/.gitignore index c6bba59..91fbb17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,130 +1,9 @@ -# Logs -logs +node_modules +*testingCode.helios +/contract +test.js +*.flat *.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -.pnpm-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Snowpack dependency directory (https://snowpack.dev/) -web_modules/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional stylelint cache -.stylelintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variable files -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# Next.js build output -.next -out - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# vuepress v2.x temp and cache directory -.temp -.cache - -# Docusaurus cache and generated files -.docusaurus - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -# yarn v2 -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* +*.uplc +*.txt +*.env \ No newline at end of file diff --git a/contract.hl b/contract.hl new file mode 100644 index 0000000..06ec46f --- /dev/null +++ b/contract.hl @@ -0,0 +1,218 @@ +spending marketplace + +// ---------- Datum ---------- + +// A listing requires a datum that has +// the owner's payment key and a list of payouts. +// We do not need to specify the marketplace payout +// in `payouts` even though it will be in +// one of the outputs. + +struct Payout { + address: Address + amount_lovelace: Int +} + +struct Datum { + // Does not contain the marketplace payout. + // This is usually royalty and seller payouts. + payouts: []Payout + /// Flexible to allow discounts + /// The key that listed the NFT + owner: PubKeyHash +} + +// ---------- Redeemer ---------- + +/// A user can either buy a token +/// or cancel/update the listing. +enum Redeemer { + /// `payout_outputs_offset` tells us where + /// the outputs containing the payouts start. + Buy { + payout_outputs_offset: Int + } + /// Cancel or update a listing. + WithdrawOrUpdate +} + +// ---------- Parameters ---------- +const AUTHORIZERS: []PubKeyHash = []PubKeyHash{PubKeyHash::new(#)} +const MARKETPLACE_ADDRESS: Address = Address::from_hex("0x") + +// ---------- Functions ---------- + +func find_payout_outputs(outputs: []TxOutput, payout_outputs_offset: Int) -> []TxOutput { + if (payout_outputs_offset == 0) { + outputs + } else { + find_payout_outputs(outputs.tail, payout_outputs_offset - 1) + } +} + + +func check_payouts_aux(outputs: []TxOutput, payouts: []Payout) -> Int { + first_output: TxOutput = outputs.head; + rest_outputs: []TxOutput = outputs.tail; + + assert(first_output.datum == OutputDatum::None, "Rest outputs' datum must be None"); + + payout: Payout = payouts.head; + rest_payouts: []Payout = payouts.tail; + + Payout { payout_address, amount_lovelace } = payout; + + // The `Output` address must match + // the address specified in the corresponding + // payout from the datum. + assert(payout_address == first_output.address, "Output address must be matched with payout"); + // Amount of lovelace in payout datum + // must be greather than 0 + assert(amount_lovelace > 0, "Payout amount must be greatner than 0"); + + // The output value must be equal to or greather than + // payout lovelace amount specified in the + // corresponding payout from the datum. + expected_output_value = Value::new(AssetClass::ADA, amount_lovelace); + assert(first_output.value.contains(expected_output_value), "Amount Lovelace from payout must be paid to output"); + + // prevent token spamming + assert(first_output.value.get_assets() == Value::ZERO, "Must pay with only lovelace"); + + rest_payouts_amount: Int = ( + if (rest_payouts.is_empty()) { + // the base case + // if rest is empty we are done + 0 + } else { + check_payouts_aux(rest_outputs, rest_payouts) + } + ); + + amount_lovelace + rest_payouts_amount +} + +/// Check that payouts and payout outputs +/// are correct. Payouts are stored in the datum +/// when assets are listed. On buy a transaction +/// with matching payout outputs needs to be constructed. +/// We also require that outputs are in the same order as the +/// payouts in the datum. Returns the sum of the payout amounts. +func check_payouts(outputs: []TxOutput, payouts: []Payout, datum_tag: OutputDatum) -> Int { + first_output: TxOutput = outputs.head; + rest_outputs: []TxOutput = outputs.tail; + + assert(first_output.datum == datum_tag, "First output's datum must be matched datum tag"); + + payout: Payout = payouts.head; + rest_payouts: []Payout = payouts.tail; + Payout { payout_address, amount_lovelace } = payout; + + // The `Output` address must match + // the address specified in the corresponding + // payout from the datum. + assert(payout_address == first_output.address, "First output address must be matched with payout"); + + // Amount of lovelace in payout datum + // must be greather than 0 + assert(amount_lovelace > 0, "Payout amount must be greatner than 0"); + + // The output value must be equal to or greather than + // payout lovelace amount specified in the + // corresponding payout from the datum. + expected_output_value = Value::new(AssetClass::ADA, amount_lovelace); + assert(first_output.value.contains(expected_output_value), "Amount lovelace from payout must be paid to output"); + + // prevent token spamming + assert(first_output.value.get_assets() == Value::ZERO, "Must pay with only lovelace"); + + rest_payouts_amount: Int = ( + if (rest_payouts.is_empty()) { + // the base case + // if rest is empty we are done + 0 + } else { + check_payouts_aux(rest_outputs, rest_payouts) + } + ); + + amount_lovelace + rest_payouts_amount +} + +/// This function is used only if a discount +/// is not allowed (tx not signed by jpg). The main difference +/// from `check_payouts` is that we make sure the +/// output address matches a hardcoded marketplace address +/// along with confirming that the output value equals +/// the marketplace_fee. In this case there is no `Payout` +/// to compare to. +func check_marketplace_payout(output: TxOutput, marketplace_fee: Int, datum_tag: OutputDatum) -> Bool { + assert(output.datum == datum_tag, "Marketplace fee output's datum must be match datum tag"); + + // Match constant marketplace address + assert(output.address == MARKETPLACE_ADDRESS, "Marketplace address must be correct"); + + // Output value quantity must equal the marketplace fee + // this prevents people from not paying a fee by submitting + // transactions not constructed by Jpg. + expected_output_value = Value::new(AssetClass::ADA, marketplace_fee); + assert(output.value.contains(expected_output_value), "Marketplace fee must be paid"); + + // prevent token spamming + assert(output.value.get_assets() == Value::ZERO, "Must pay with only lovelace"); + + true +} + +// ---------- Main Function ---------- + +func main(datum: Datum, redeemer: Redeemer, ctx: ScriptContext) -> Bool { + /// Validate that the signer is the owner or that payouts + /// are present as outputs and that the tag is correct. + tx: Tx = ctx.tx; + spending_output_ref: TxOutputId = ctx.get_spending_purpose_output_id(); + redeemer.switch { + Buy { payout_outputs_offset } => { + // to prevent double satisfaction + datum_tag: OutputDatum::Inline = OutputDatum::new_inline(spending_output_ref.serialize().blake2b()); + + Datum { payouts, _ } = datum; + // Find the `outputs` that correspond to `payouts`. + payout_outputs: []TxOutput = find_payout_outputs(tx.outputs, payout_outputs_offset); + + // We can ignore the fee check + // if any of the authorizers have signed the tx. + can_have_discount: Bool = AUTHORIZERS.any((authorizer: PubKeyHash) -> Bool { + tx.is_signed_by(authorizer) + }); + + // If `can_have_discount` is `True` then we can + // assume that jpg properly calculated the fee off chain. + if (can_have_discount) { + check_payouts(payout_outputs, payouts, datum_tag) > 0 + } else { + // When there is a marketplace fee we can assume + // it is the first of the `payout_outputs`. + marketplace_output: TxOutput = payout_outputs.head; + rest_outputs: []TxOutput = payout_outputs.tail; + + payouts_sum: Int = check_payouts(rest_outputs, payouts, OutputDatum::None); + + // This approximates the marketplace fee given only the payouts to a very high degree. + // For a payouts in excess of 100k ada the error is less than 40000 lovelace. + marketplace_fee: Int = payouts_sum * 50 / 49 / 50; + + // Make sure that the marketplace output + // is correct. + check_marketplace_payout(marketplace_output,marketplace_fee, datum_tag) + } + }, + WithdrawOrUpdate => { + // There's not much to do here. An asset + // owner can cancel or update their listing + // at any time. + // is signed by owner + tx.is_signed_by(datum.owner) + } + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..702eb15 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1028 @@ +{ + "name": "handles-marketplace-contracts", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "handles-marketplace-contracts", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@koralabs/helios": "^0.16.8-2", + "@koralabs/kora-labs-common": "^4.3.7", + "@koralabs/kora-labs-contract-testing": "^0.0.9", + "@types/node": "^22.1.0", + "bs58": "^6.0.0", + "dotenv": "^16.4.5", + "tsx": "^4.17.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", + "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", + "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", + "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", + "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", + "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", + "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", + "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", + "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", + "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", + "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", + "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", + "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", + "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", + "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", + "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", + "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", + "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", + "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", + "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", + "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", + "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", + "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", + "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@koralabs/helios": { + "version": "0.16.8-2", + "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-2.tgz", + "integrity": "sha512-qAKs3PgZye+vjWM9bZVgqVVJgA3CruVeDoFn6xAoH3us7seofSei3N1364bKTsYHTz+hEtMRcYU4GEtceaJs1A==", + "dev": true + }, + "node_modules/@koralabs/kora-labs-common": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@koralabs/kora-labs-common/-/kora-labs-common-4.3.7.tgz", + "integrity": "sha512-nXp9+o9DMffn92sSGoDT6UToP3uCpJuwcoofK01U+RKtqytJ79i/9WJrlCkeeI5prj74vNYOpbRE2fidYQQUOQ==", + "dev": true, + "dependencies": { + "bech32": "^2.0.0", + "boolean": "^3.2.0", + "cbor": "^9.0.2", + "pluralize": "^8.0.0" + } + }, + "node_modules/@koralabs/kora-labs-contract-testing": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@koralabs/kora-labs-contract-testing/-/kora-labs-contract-testing-0.0.9.tgz", + "integrity": "sha512-v6ie4hRoUE7vGCihI5Z61JCZiHadJci80zq0Wnplth3Fj7YC4Uyo2i2ne/nZ9yn4iRoSSe2wQQIKQ9mc1DZQlw==", + "dev": true, + "dependencies": { + "@koralabs/helios": "0.16.8-2", + "@koralabs/kora-labs-common": "^4.0.7", + "@stricahq/bip32ed25519": "^1.0.4", + "bip39": "^3.1.0" + } + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@stricahq/bip32ed25519": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@stricahq/bip32ed25519/-/bip32ed25519-1.1.0.tgz", + "integrity": "sha512-G3OEjxaqvTCzEGppmI9arMrKzl44poVXWTVlQgLILI39EtG/mDWQguN+wJ9m+9TOIxPBlz/10TLKrV+WVH91uw==", + "dev": true, + "dependencies": { + "blakejs": "^1.1.1", + "bn.js": "^5.2.0", + "buffer": "^6.0.3", + "chai": "^4.3.4", + "elliptic": "6.5.4", + "hash.js": "^1.1.7", + "pbkdf2": "^3.1.2" + } + }, + "node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/base-x": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.0.tgz", + "integrity": "sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", + "dev": true + }, + "node_modules/bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "dev": true, + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, + "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==", + "dev": true + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true + }, + "node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "dev": true, + "dependencies": { + "base-x": "^5.0.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/tsx": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.17.0.tgz", + "integrity": "sha512-eN4mnDA5UMKDt4YZixo9tBioibaMBpoxBkD+rIPAjVmYERSG0/dWEY1CEFuV89CgASlKL499q8AhmkMnnjtOJg==", + "dev": true, + "dependencies": { + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2d3a4d6 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "handles-marketplace-contracts", + "version": "1.0.0", + "description": "Smart Contract of Ada Handles Marketplace", + "type": "module", + "scripts": { + "test": "tsx -r dotenv/config tests/txTests.ts" + }, + "keywords": [], + "author": "Kora Labs ", + "license": "ISC", + "devDependencies": { + "@koralabs/helios": "^0.16.8-2", + "@koralabs/kora-labs-common": "^4.3.7", + "@koralabs/kora-labs-contract-testing": "^0.0.9", + "@types/node": "^22.1.0", + "bs58": "^6.0.0", + "dotenv": "^16.4.5", + "tsx": "^4.17.0" + } +} diff --git a/tests/fixtures.ts b/tests/fixtures.ts new file mode 100644 index 0000000..e69de29 diff --git a/tests/txTests.ts b/tests/txTests.ts new file mode 100644 index 0000000..14c60db --- /dev/null +++ b/tests/txTests.ts @@ -0,0 +1,19 @@ +import fs from 'fs/promises'; +import * as helios from '@koralabs/helios'; +import { + ContractTester, + getAddressAtDerivation, +} from '@koralabs/kora-labs-contract-testing'; + +const runTests = async (file: string) => { + const walletAddress = await getAddressAtDerivation(0); + const tester = new ContractTester(walletAddress, false); + await tester.init(); + + let contractFile = (await fs.readFile(file)).toString(); + const program = helios.Program.new(contractFile); //new instance +}; + +(async () => { + await runTests('./contract.hl'); +})(); From e872c9042bd670912448cdffa21ea0a378152f72 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Tue, 20 Aug 2024 23:22:09 +0800 Subject: [PATCH 02/20] add tests init --- tests/fixtures.ts => .eslintignore | 0 .eslintrc.json | 62 + .github/workflow/CI.yml | 82 + .prettierignore | 0 .prettierrc.json | 8 + package-lock.json | 3982 +++++++++++++++-- package.json | 15 + .../contract/marketplace.helios | 6 +- src/tests/constants.ts | 63 + src/tests/fixtures.ts | 64 + src/tests/tx.test.ts | 54 + src/tests/types.ts | 8 + src/tests/utils.ts | 39 + tests/txTests.ts | 19 - tsconfig.json | 20 + 15 files changed, 4049 insertions(+), 373 deletions(-) rename tests/fixtures.ts => .eslintignore (100%) create mode 100644 .eslintrc.json create mode 100644 .github/workflow/CI.yml create mode 100644 .prettierignore create mode 100644 .prettierrc.json rename contract.hl => src/contract/marketplace.helios (96%) create mode 100644 src/tests/constants.ts create mode 100644 src/tests/fixtures.ts create mode 100644 src/tests/tx.test.ts create mode 100644 src/tests/types.ts create mode 100644 src/tests/utils.ts delete mode 100644 tests/txTests.ts create mode 100644 tsconfig.json diff --git a/tests/fixtures.ts b/.eslintignore similarity index 100% rename from tests/fixtures.ts rename to .eslintignore diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..c4f3805 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,62 @@ +{ + "parser": "@typescript-eslint/parser", + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:import/errors", + "plugin:import/warnings", + "plugin:import/typescript", + "prettier" + ], + "plugins": ["import", "@typescript-eslint", "simple-import-sort"], + "rules": { + "padding-line-between-statements": [ + "error", + { "blankLine": "always", "prev": "*", "next": "block" }, + { "blankLine": "always", "prev": "block", "next": "*" }, + { "blankLine": "always", "prev": "*", "next": "block-like" }, + { "blankLine": "always", "prev": "block-like", "next": "*" } + ], + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + "caughtErrorsIgnorePattern": "^_" + } + ], + "@typescript-eslint/naming-convention": [ + "error", + { + "selector": ["parameter", "variable"], + "leadingUnderscore": "forbid", + "format": null + }, + { + "selector": "parameter", + "leadingUnderscore": "require", + "format": null, + "modifiers": ["unused"] + } + ], + "no-constant-condition": "off", + "import/no-unresolved": "off", + "simple-import-sort/imports": [ + "error", + { + "groups": [ + // Internal packages. + ["^@(/.*|$)"], + // Side effect imports. + ["^\\u0000"], + // Parent imports. Put `..` last. + ["^\\.\\.(?!/?$)", "^\\.\\./?$"], + // Other relative imports. Put same-folder imports and `.` last. + ["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"], + // Style imports. + ["^.+\\.?(css)$"] + ] + } + ] + } +} diff --git a/.github/workflow/CI.yml b/.github/workflow/CI.yml new file mode 100644 index 0000000..7784994 --- /dev/null +++ b/.github/workflow/CI.yml @@ -0,0 +1,82 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.18 + check-latest: true + + - name: Update npm + run: npm install -g npm@latest + + - name: Install dependencies + run: npm ci --include dev + + - name: Run tests + run: npm run test + + lint: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.18 + check-latest: true + + - name: Update npm + run: npm install -g npm@latest + + - name: Install dependencies + run: npm install --include dev + + - name: Lint + run: npm run lint + + build: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.18 + check-latest: true + + - name: Update npm + run: npm install -g npm@latest + + - name: Install dependencies + run: npm install --include dev + + - name: Install Aiken + run: | + curl -sSfL https://install.aiken-lang.org | bash + ~/.aiken/bin/aikup + sudo ln -s ~/.aiken/bin/aiken /usr/local/bin/aiken + + - name: Validate code + run: npm run build diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..e69de29 diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..71cc855 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "singleQuote": false, + "trailingComma": "es5", + "semi": true, + "useTabs": false +} diff --git a/package-lock.json b/package-lock.json index 702eb15..51716dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,16 +8,40 @@ "name": "handles-marketplace-contracts", "version": "1.0.0", "license": "ISC", + "dependencies": { + "decimal.js": "^10.4.3" + }, "devDependencies": { "@koralabs/helios": "^0.16.8-2", "@koralabs/kora-labs-common": "^4.3.7", "@koralabs/kora-labs-contract-testing": "^0.0.9", "@types/node": "^22.1.0", + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", "bs58": "^6.0.0", + "concurrently": "^8.2.0", "dotenv": "^16.4.5", + "eslint": "^8.51.0", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-simple-import-sort": "^12.1.1", + "prettier": "^2.8.8", "tsx": "^4.17.0" } }, + "node_modules/@babel/runtime": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", @@ -402,6 +426,141 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, "node_modules/@koralabs/helios": { "version": "0.16.8-2", "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-2.tgz", @@ -444,6 +603,41 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@stricahq/bip32ed25519": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@stricahq/bip32ed25519/-/bip32ed25519-1.1.0.tgz", @@ -459,6 +653,18 @@ "pbkdf2": "^3.1.2" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, "node_modules/@types/node": { "version": "22.1.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", @@ -468,350 +674,438 @@ "undici-types": "~6.13.0" } }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/base-x": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.0.tgz", - "integrity": "sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ==", + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true } - ] - }, - "node_modules/bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", - "dev": true + } }, - "node_modules/bip39": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", - "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "dependencies": { - "@noble/hashes": "^1.2.0" + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "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==", - "dev": true - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "dev": true - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true - }, - "node_modules/bs58": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", - "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "base-x": "^5.0.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/cbor": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", - "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, - "dependencies": { - "nofilter": "^3.1.0" - }, "engines": { - "node": ">=16" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/chai": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", - "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=4" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { - "get-func-name": "^2.0.2" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" }, "engines": { - "node": "*" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/create-hash": { + "node_modules/@ungap/structured-clone": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { - "type-detect": "^4.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { - "url": "https://dotenvx.com" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=8" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-tsconfig": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", - "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base-x": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.0.tgz", + "integrity": "sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ { @@ -828,162 +1122,2881 @@ } ] }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", "dev": true }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "node_modules/bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "dev": true, + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, + "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==", + "dev": true + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true + }, + "node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "dev": true, + "dependencies": { + "base-x": "^5.0.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/concurrently": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz", + "integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==", + "dev": true, + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/for-each": { + "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" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/spawn-command": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "dependencies": { - "get-func-name": "^2.0.1" + "safe-buffer": "~5.2.0" } }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true - }, - "node_modules/nofilter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", - "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=12.19" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=0.12" + "node": ">=8" } }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/resolve-pkg-maps": { + "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "bin": { + "tree-kill": "cli.js" + } }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "engines": { + "node": ">=16" }, - "bin": { - "sha.js": "bin.js" + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { - "safe-buffer": "~5.2.0" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, "node_modules/tsx": { "version": "4.17.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.17.0.tgz", @@ -1003,6 +4016,18 @@ "fsevents": "~2.3.3" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", @@ -1012,17 +4037,270 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/undici-types": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", "dev": true }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 2d3a4d6..175f64c 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,9 @@ "description": "Smart Contract of Ada Handles Marketplace", "type": "module", "scripts": { + "build": "rm -rf ./dist && npx tsc **/*.ts", + "prettier": "npx prettier -w '**/*.{js,ts,json,.*}'", + "lint": "concurrently \"npx prettier --check '**/*.{js,ts,json,.*}'\" \"npx eslint . --max-warnings=0\"", "test": "tsx -r dotenv/config tests/txTests.ts" }, "keywords": [], @@ -14,8 +17,20 @@ "@koralabs/kora-labs-common": "^4.3.7", "@koralabs/kora-labs-contract-testing": "^0.0.9", "@types/node": "^22.1.0", + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", "bs58": "^6.0.0", + "concurrently": "^8.2.0", "dotenv": "^16.4.5", + "eslint": "^8.51.0", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-simple-import-sort": "^12.1.1", + "prettier": "^2.8.8", "tsx": "^4.17.0" + }, + "dependencies": { + "decimal.js": "^10.4.3" } } diff --git a/contract.hl b/src/contract/marketplace.helios similarity index 96% rename from contract.hl rename to src/contract/marketplace.helios index 06ec46f..8c65a7e 100644 --- a/contract.hl +++ b/src/contract/marketplace.helios @@ -38,7 +38,9 @@ enum Redeemer { // ---------- Parameters ---------- const AUTHORIZERS: []PubKeyHash = []PubKeyHash{PubKeyHash::new(#)} -const MARKETPLACE_ADDRESS: Address = Address::from_hex("0x") +const MARKETPLACE_ADDRESS: Address = Address::from_hex( + "000e1bdf3e12a8d4e915f40c721e30bfab50675f0b44b38e7bb7f677859717909c5741d9a8524cde5ef03c4dd491fe795d1fdf11fd67d68a5e" +) // ---------- Functions ---------- @@ -204,7 +206,7 @@ func main(datum: Datum, redeemer: Redeemer, ctx: ScriptContext) -> Bool { // Make sure that the marketplace output // is correct. - check_marketplace_payout(marketplace_output,marketplace_fee, datum_tag) + check_marketplace_payout(marketplace_output, marketplace_fee, datum_tag) } }, WithdrawOrUpdate => { diff --git a/src/tests/constants.ts b/src/tests/constants.ts new file mode 100644 index 0000000..0f0c854 --- /dev/null +++ b/src/tests/constants.ts @@ -0,0 +1,63 @@ +import * as helios from "@koralabs/helios"; + +const HANDLE_POLICY_ID = + "f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a"; +const AUTHORIZERS_PUB_KEY_HAHSES = [ + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789000001" + ), + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789000002" + ), + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789000003" + ), +]; +const OWNER_PUB_KEY_HASH = helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789111111" +); + +const MARKETPLACE_ADDRESS = helios.Address.fromHash( + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789222222" + ) +); + +const PAYOUT_ADDRESSES = [ + helios.Address.fromHash( + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789555551" + ) + ), + helios.Address.fromHash( + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789555552" + ) + ), + helios.Address.fromHash( + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789555553" + ) + ), + helios.Address.fromHash( + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789555554" + ) + ), + helios.Address.fromHash( + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789555555" + ) + ), +]; + +const minLovelace = 2_000_000n; + +export { + HANDLE_POLICY_ID, + AUTHORIZERS_PUB_KEY_HAHSES, + OWNER_PUB_KEY_HASH, + MARKETPLACE_ADDRESS, + PAYOUT_ADDRESSES, + minLovelace, +}; diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts new file mode 100644 index 0000000..cdd26e3 --- /dev/null +++ b/src/tests/fixtures.ts @@ -0,0 +1,64 @@ +import { HANDLE_POLICY_ID, minLovelace, OWNER_PUB_KEY_HASH } from "./constants"; +import { Payout } from "./types"; +import { buildDatum } from "./utils"; + +import * as helios from "@koralabs/helios"; +import { AssetNameLabel } from "@koralabs/kora-labs-common"; +import { + Fixture, + getAddressAtDerivation, + getNewFakeUtxoId, +} from "@koralabs/kora-labs-contract-testing"; + +/// setup +helios.config.set({ IS_TESTNET: false, AUTO_SET_VALIDITY_RANGE: true }); + +class BuyFixture extends Fixture { + handleName = "golddydev"; + payouts: Payout[] = []; + owner: helios.PubKeyHash = OWNER_PUB_KEY_HASH; + authorizers: helios.PubKeyHash[] = []; + datumTag: helios.Datum = new helios.Datum(); + payoutOutputs: Payout[] = []; + + async initialize() { + const datum = await buildDatum(this.payouts, this.owner); + this.inputs = [ + new helios.TxInput( /// Handle NFT to Buy + new helios.TxOutputId(getNewFakeUtxoId()), + new helios.TxOutput( + await getAddressAtDerivation(0), + new helios.Value(minLovelace, [ + [ + HANDLE_POLICY_ID, + [ + [ + `${AssetNameLabel.LBL_222}${Buffer.from( + this.handleName + ).toString("hex")}`, + 1, + ], + ], + ], + ]), + datum + ) + ), + ]; + + this.outputs = this.payoutOutputs.map( + (payout, index) => + new helios.TxOutput( /// marketplace address + payout.address, + new helios.Value(payout.amountLovelace), + index == 0 ? this.datumTag : undefined + ) + ); + + /// authorizers + this.signatories = [...this.authorizers]; + return this; + } +} + +export { BuyFixture }; diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts new file mode 100644 index 0000000..2a119bd --- /dev/null +++ b/src/tests/tx.test.ts @@ -0,0 +1,54 @@ +import { MARKETPLACE_ADDRESS, PAYOUT_ADDRESSES } from "./constants"; +import { BuyFixture } from "./fixtures"; +import { adaToLovelace, buildDatumTag } from "./utils"; + +import * as helios from "@koralabs/helios"; +import { + ContractTester, + getAddressAtDerivation, + getNewFakeUtxoId, + Test, +} from "@koralabs/kora-labs-contract-testing"; +import fs from "fs/promises"; + +const runTests = async (file: string) => { + const walletAddress = await getAddressAtDerivation(0); + const tester = new ContractTester(walletAddress, false); + await tester.init(); + + const contractFile = (await fs.readFile(file)).toString(); + const program = helios.Program.new(contractFile); //new instance + + /// --------------- BUY --------------- + + /// ---------- Should Approve - Buy without Authorizer ---------- + await tester.test( + "Buy", + "Can Buy NFT without authorizer", + new Test(program, async (hash) => { + const fixture = new BuyFixture(hash); + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + fixture.datumTag = buildDatumTag( + new helios.TxOutputId(getNewFakeUtxoId()) + ); + fixture.payoutOutputs = [ + { + address: MARKETPLACE_ADDRESS, + amountLovelace: adaToLovelace(Math.ceil((100 + 150 + 80) / 49)), + }, + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + return await fixture.initialize(); + }) + ); +}; + +(async () => { + await runTests("../contract/marketplace.helios"); +})(); diff --git a/src/tests/types.ts b/src/tests/types.ts new file mode 100644 index 0000000..609be7d --- /dev/null +++ b/src/tests/types.ts @@ -0,0 +1,8 @@ +import * as helios from "@koralabs/helios"; + +interface Payout { + address: helios.Address; + amountLovelace: bigint; +} + +export { Payout }; diff --git a/src/tests/utils.ts b/src/tests/utils.ts new file mode 100644 index 0000000..5cedb57 --- /dev/null +++ b/src/tests/utils.ts @@ -0,0 +1,39 @@ +import { Payout } from "./types"; + +import * as helios from "@koralabs/helios"; +import { convertJsontoCbor } from "@koralabs/kora-labs-contract-testing"; +import Decimal from "decimal.js"; + +const adaToLovelace = (ada: number): bigint => + BigInt(new Decimal(ada).mul(Math.pow(10, 6)).floor().toString()); + +const buildDatumTag = (outputRef: helios.TxOutputId): helios.Datum => { + return helios.Datum.inline( + helios.UplcData.fromCbor( + helios.Crypto.blake2b(helios.textToBytes(outputRef.toCborHex())) + ) + ); +}; + +const buildDatum = async ( + payouts: Payout[], + owner: helios.PubKeyHash +): Promise => { + const constrPayout = (payout: Payout) => ({ + constructor_0: [ + `0x${helios.bytesToHex(payout.address.bytes)}`, + payout.amountLovelace, + ], + }); + + const datum = { + constructor_0: [ + payouts.map(constrPayout), + `0x${helios.bytesToHex(owner.bytes)}`, + ], + }; + const datumCbor = await convertJsontoCbor(datum); + return helios.Datum.inline(helios.UplcData.fromCbor(datumCbor)); +}; + +export { adaToLovelace, buildDatumTag, buildDatum }; diff --git a/tests/txTests.ts b/tests/txTests.ts deleted file mode 100644 index 14c60db..0000000 --- a/tests/txTests.ts +++ /dev/null @@ -1,19 +0,0 @@ -import fs from 'fs/promises'; -import * as helios from '@koralabs/helios'; -import { - ContractTester, - getAddressAtDerivation, -} from '@koralabs/kora-labs-contract-testing'; - -const runTests = async (file: string) => { - const walletAddress = await getAddressAtDerivation(0); - const tester = new ContractTester(walletAddress, false); - await tester.init(); - - let contractFile = (await fs.readFile(file)).toString(); - const program = helios.Program.new(contractFile); //new instance -}; - -(async () => { - await runTests('./contract.hl'); -})(); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..121e543 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "baseUrl": "./src", + "rootDir": "./src", + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "Node", + "lib": ["ES2022"], + "allowSyntheticDefaultImports": true, + "strict": true, + "allowJs": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "dist", + "declaration": true + }, + "include": ["src/**/*", "src/tests/**/*"], + "exclude": ["node_modules"] +} From 7fa5cd1468bf13f664e82a366320c7d3edfab62a Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 22 Aug 2024 01:56:34 +0800 Subject: [PATCH 03/20] add initial test --- .github/workflow/CI.yml | 29 ------------------------ package-lock.json | 20 ++++++++--------- package.json | 9 ++++---- src/contract/marketplace.helios | 21 +++++++++-------- src/tests/constants.ts | 4 ++-- src/tests/fixtures.ts | 25 +++++++++++++++++++-- src/tests/tx.test.ts | 7 +++--- src/tests/types.ts | 2 +- src/tests/utils.ts | 40 ++++++++++++++++++--------------- tsconfig.json | 1 - 10 files changed, 78 insertions(+), 80 deletions(-) diff --git a/.github/workflow/CI.yml b/.github/workflow/CI.yml index 7784994..38ff444 100644 --- a/.github/workflow/CI.yml +++ b/.github/workflow/CI.yml @@ -51,32 +51,3 @@ jobs: - name: Lint run: npm run lint - - build: - runs-on: ubuntu-latest - timeout-minutes: 10 - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: 18.18 - check-latest: true - - - name: Update npm - run: npm install -g npm@latest - - - name: Install dependencies - run: npm install --include dev - - - name: Install Aiken - run: | - curl -sSfL https://install.aiken-lang.org | bash - ~/.aiken/bin/aikup - sudo ln -s ~/.aiken/bin/aiken /usr/local/bin/aiken - - - name: Validate code - run: npm run build diff --git a/package-lock.json b/package-lock.json index 51716dc..acfb791 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,9 @@ "decimal.js": "^10.4.3" }, "devDependencies": { - "@koralabs/helios": "^0.16.8-2", - "@koralabs/kora-labs-common": "^4.3.7", - "@koralabs/kora-labs-contract-testing": "^0.0.9", + "@koralabs/helios": "0.16.8-1", + "@koralabs/kora-labs-common": "^4.0.7", + "@koralabs/kora-labs-contract-testing": "0.0.7", "@types/node": "^22.1.0", "@typescript-eslint/eslint-plugin": "^6.7.5", "@typescript-eslint/parser": "^6.7.5", @@ -562,9 +562,9 @@ "dev": true }, "node_modules/@koralabs/helios": { - "version": "0.16.8-2", - "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-2.tgz", - "integrity": "sha512-qAKs3PgZye+vjWM9bZVgqVVJgA3CruVeDoFn6xAoH3us7seofSei3N1364bKTsYHTz+hEtMRcYU4GEtceaJs1A==", + "version": "0.16.8-1", + "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-1.tgz", + "integrity": "sha512-/pbL4lUP7CBELSxfMuZUhJ5rZ5B3T+kwaQ4joI9y+SDMFyfqySARcgv5+uTT1nnTd/gCgM3QzMUZBOL8BMM3AA==", "dev": true }, "node_modules/@koralabs/kora-labs-common": { @@ -580,12 +580,12 @@ } }, "node_modules/@koralabs/kora-labs-contract-testing": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@koralabs/kora-labs-contract-testing/-/kora-labs-contract-testing-0.0.9.tgz", - "integrity": "sha512-v6ie4hRoUE7vGCihI5Z61JCZiHadJci80zq0Wnplth3Fj7YC4Uyo2i2ne/nZ9yn4iRoSSe2wQQIKQ9mc1DZQlw==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@koralabs/kora-labs-contract-testing/-/kora-labs-contract-testing-0.0.7.tgz", + "integrity": "sha512-YFldQeMWXE/qeUNg3df6MOvBYaRkurCQICmox7v7YnB7Pfe/PIotiAo2gCuSpOWiS1s/JkOk5D9axE9z0kZrsQ==", "dev": true, "dependencies": { - "@koralabs/helios": "0.16.8-2", + "@koralabs/helios": "0.16.8-1", "@koralabs/kora-labs-common": "^4.0.7", "@stricahq/bip32ed25519": "^1.0.4", "bip39": "^3.1.0" diff --git a/package.json b/package.json index 175f64c..f19a11f 100644 --- a/package.json +++ b/package.json @@ -4,18 +4,17 @@ "description": "Smart Contract of Ada Handles Marketplace", "type": "module", "scripts": { - "build": "rm -rf ./dist && npx tsc **/*.ts", "prettier": "npx prettier -w '**/*.{js,ts,json,.*}'", "lint": "concurrently \"npx prettier --check '**/*.{js,ts,json,.*}'\" \"npx eslint . --max-warnings=0\"", - "test": "tsx -r dotenv/config tests/txTests.ts" + "test": "tsx -r dotenv/config src/tests/tx.test.ts" }, "keywords": [], "author": "Kora Labs ", "license": "ISC", "devDependencies": { - "@koralabs/helios": "^0.16.8-2", - "@koralabs/kora-labs-common": "^4.3.7", - "@koralabs/kora-labs-contract-testing": "^0.0.9", + "@koralabs/helios": "0.16.8-1", + "@koralabs/kora-labs-common": "^4.0.7", + "@koralabs/kora-labs-contract-testing": "0.0.7", "@types/node": "^22.1.0", "@typescript-eslint/eslint-plugin": "^6.7.5", "@typescript-eslint/parser": "^6.7.5", diff --git a/src/contract/marketplace.helios b/src/contract/marketplace.helios index 8c65a7e..300c491 100644 --- a/src/contract/marketplace.helios +++ b/src/contract/marketplace.helios @@ -37,9 +37,12 @@ enum Redeemer { } // ---------- Parameters ---------- -const AUTHORIZERS: []PubKeyHash = []PubKeyHash{PubKeyHash::new(#)} -const MARKETPLACE_ADDRESS: Address = Address::from_hex( - "000e1bdf3e12a8d4e915f40c721e30bfab50675f0b44b38e7bb7f677859717909c5741d9a8524cde5ef03c4dd491fe795d1fdf11fd67d68a5e" +const AUTHORIZERS: []PubKeyHash = []PubKeyHash{ + PubKeyHash::new(#01234567890123456789012345678901234567890123456789000001) +} +const MARKETPLACE_ADDRESS: Address = Address::new( + Credential::new_pubkey(PubKeyHash::new(#01234567890123456789012345678901234567890123456789222222)), + Option[StakingCredential]::None ) // ---------- Functions ---------- @@ -57,7 +60,7 @@ func check_payouts_aux(outputs: []TxOutput, payouts: []Payout) -> Int { first_output: TxOutput = outputs.head; rest_outputs: []TxOutput = outputs.tail; - assert(first_output.datum == OutputDatum::None, "Rest outputs' datum must be None"); + assert(first_output.datum == OutputDatum::new_none(), "Rest outputs' datum must be None"); payout: Payout = payouts.head; rest_payouts: []Payout = payouts.tail; @@ -150,14 +153,14 @@ func check_payouts(outputs: []TxOutput, payouts: []Payout, datum_tag: OutputDatu /// to compare to. func check_marketplace_payout(output: TxOutput, marketplace_fee: Int, datum_tag: OutputDatum) -> Bool { assert(output.datum == datum_tag, "Marketplace fee output's datum must be match datum tag"); - + // Match constant marketplace address assert(output.address == MARKETPLACE_ADDRESS, "Marketplace address must be correct"); // Output value quantity must equal the marketplace fee // this prevents people from not paying a fee by submitting // transactions not constructed by Jpg. - expected_output_value = Value::new(AssetClass::ADA, marketplace_fee); + expected_output_value: Value = Value::new(AssetClass::ADA, marketplace_fee); assert(output.value.contains(expected_output_value), "Marketplace fee must be paid"); // prevent token spamming @@ -198,12 +201,12 @@ func main(datum: Datum, redeemer: Redeemer, ctx: ScriptContext) -> Bool { marketplace_output: TxOutput = payout_outputs.head; rest_outputs: []TxOutput = payout_outputs.tail; - payouts_sum: Int = check_payouts(rest_outputs, payouts, OutputDatum::None); + payouts_sum: Int = check_payouts(rest_outputs, payouts, OutputDatum::new_none()); // This approximates the marketplace fee given only the payouts to a very high degree. // For a payouts in excess of 100k ada the error is less than 40000 lovelace. marketplace_fee: Int = payouts_sum * 50 / 49 / 50; - + // Make sure that the marketplace output // is correct. check_marketplace_payout(marketplace_output, marketplace_fee, datum_tag) @@ -217,4 +220,4 @@ func main(datum: Datum, redeemer: Redeemer, ctx: ScriptContext) -> Bool { tx.is_signed_by(datum.owner) } } -} +} \ No newline at end of file diff --git a/src/tests/constants.ts b/src/tests/constants.ts index 0f0c854..170cefe 100644 --- a/src/tests/constants.ts +++ b/src/tests/constants.ts @@ -5,7 +5,7 @@ const HANDLE_POLICY_ID = const AUTHORIZERS_PUB_KEY_HAHSES = [ helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789000001" - ), + ), /// vailid helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789000002" ), @@ -51,7 +51,7 @@ const PAYOUT_ADDRESSES = [ ), ]; -const minLovelace = 2_000_000n; +const minLovelace = 10_000_000n; export { HANDLE_POLICY_ID, diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts index cdd26e3..d09bcfd 100644 --- a/src/tests/fixtures.ts +++ b/src/tests/fixtures.ts @@ -5,6 +5,7 @@ import { buildDatum } from "./utils"; import * as helios from "@koralabs/helios"; import { AssetNameLabel } from "@koralabs/kora-labs-common"; import { + convertJsontoCbor, Fixture, getAddressAtDerivation, getNewFakeUtxoId, @@ -15,19 +16,39 @@ helios.config.set({ IS_TESTNET: false, AUTO_SET_VALIDITY_RANGE: true }); class BuyFixture extends Fixture { handleName = "golddydev"; + + buyRedeemer = { + constructor_0: [0], + }; + buyRedeemerCbor: string = ""; + + spendingUtxoId: string = ""; payouts: Payout[] = []; owner: helios.PubKeyHash = OWNER_PUB_KEY_HASH; authorizers: helios.PubKeyHash[] = []; - datumTag: helios.Datum = new helios.Datum(); + datumTag: helios.Datum | null = null; payoutOutputs: Payout[] = []; + constructor(validatorHash: helios.ValidatorHash) { + super(validatorHash); + } + async initialize() { + this.buyRedeemerCbor = await convertJsontoCbor(this.buyRedeemer); + this.redeemer = helios.UplcData.fromCbor(this.buyRedeemerCbor); const datum = await buildDatum(this.payouts, this.owner); this.inputs = [ - new helios.TxInput( /// Handle NFT to Buy + new helios.TxInput( // money & collateral new helios.TxOutputId(getNewFakeUtxoId()), new helios.TxOutput( await getAddressAtDerivation(0), + new helios.Value(BigInt(500_000_000)) + ) + ), + new helios.TxInput( /// Handle NFT to Buy + new helios.TxOutputId(this.spendingUtxoId), + new helios.TxOutput( + this.scriptAddress, new helios.Value(minLovelace, [ [ HANDLE_POLICY_ID, diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index 2a119bd..9ca0d18 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -32,8 +32,9 @@ const runTests = async (file: string) => { { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; - fixture.datumTag = buildDatumTag( - new helios.TxOutputId(getNewFakeUtxoId()) + fixture.spendingUtxoId = getNewFakeUtxoId(); + fixture.datumTag = await buildDatumTag( + new helios.TxOutputId(fixture.spendingUtxoId) ); fixture.payoutOutputs = [ { @@ -50,5 +51,5 @@ const runTests = async (file: string) => { }; (async () => { - await runTests("../contract/marketplace.helios"); + await runTests("src/contract/marketplace.helios"); })(); diff --git a/src/tests/types.ts b/src/tests/types.ts index 609be7d..d700f2a 100644 --- a/src/tests/types.ts +++ b/src/tests/types.ts @@ -2,7 +2,7 @@ import * as helios from "@koralabs/helios"; interface Payout { address: helios.Address; - amountLovelace: bigint; + amountLovelace: number; } export { Payout }; diff --git a/src/tests/utils.ts b/src/tests/utils.ts index 5cedb57..31f976d 100644 --- a/src/tests/utils.ts +++ b/src/tests/utils.ts @@ -4,14 +4,16 @@ import * as helios from "@koralabs/helios"; import { convertJsontoCbor } from "@koralabs/kora-labs-contract-testing"; import Decimal from "decimal.js"; -const adaToLovelace = (ada: number): bigint => - BigInt(new Decimal(ada).mul(Math.pow(10, 6)).floor().toString()); +const adaToLovelace = (ada: number): number => + new Decimal(ada).mul(Math.pow(10, 6)).floor().toNumber(); -const buildDatumTag = (outputRef: helios.TxOutputId): helios.Datum => { +const buildDatumTag = async ( + outputRef: helios.TxOutputId +): Promise => { + const cbor = outputRef._toUplcData().toCborHex(); + const hashed = helios.Crypto.blake2b(helios.hexToBytes(cbor)); return helios.Datum.inline( - helios.UplcData.fromCbor( - helios.Crypto.blake2b(helios.textToBytes(outputRef.toCborHex())) - ) + helios.UplcData.fromCbor(helios.Cbor.encodeBytes(hashed)) ); }; @@ -19,19 +21,21 @@ const buildDatum = async ( payouts: Payout[], owner: helios.PubKeyHash ): Promise => { - const constrPayout = (payout: Payout) => ({ - constructor_0: [ - `0x${helios.bytesToHex(payout.address.bytes)}`, - payout.amountLovelace, - ], - }); + const constrPayout = (payout: Payout) => [ + { + constructor_0: [ + { constructor_0: [`0x${payout.address.pubKeyHash?.hex || ""}`] }, + { + constructor_1: payout.address.stakingHash + ? [`0x${payout.address.pubKeyHash?.hex || ""}`] + : [], + }, + ], + }, + payout.amountLovelace, + ]; - const datum = { - constructor_0: [ - payouts.map(constrPayout), - `0x${helios.bytesToHex(owner.bytes)}`, - ], - }; + const datum = [payouts.map(constrPayout), `0x${owner.hex}`]; const datumCbor = await convertJsontoCbor(datum); return helios.Datum.inline(helios.UplcData.fromCbor(datumCbor)); }; diff --git a/tsconfig.json b/tsconfig.json index 121e543..1264a2a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,6 @@ "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, - "outDir": "dist", "declaration": true }, "include": ["src/**/*", "src/tests/**/*"], From 4c4c92f3ec9eebb16b4fc86fbcdc003584dad160 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 22 Aug 2024 01:57:25 +0800 Subject: [PATCH 04/20] update folder name --- .github/{workflow => workflows}/CI.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{workflow => workflows}/CI.yml (100%) diff --git a/.github/workflow/CI.yml b/.github/workflows/CI.yml similarity index 100% rename from .github/workflow/CI.yml rename to .github/workflows/CI.yml From eb9be7c905ccfba5e34ffd6011633e7113d5f5d8 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 22 Aug 2024 02:04:22 +0800 Subject: [PATCH 05/20] add more tests --- .github/workflows/CI.yml | 2 +- src/tests/tx.test.ts | 66 ++++++++++++++++++++++++++++++++++++++-- src/tests/utils.ts | 4 +-- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 38ff444..ee2a7d0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -3,7 +3,7 @@ name: CI on: push: branches: - - main + - master pull_request: jobs: diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index 9ca0d18..19e45eb 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -21,10 +21,11 @@ const runTests = async (file: string) => { /// --------------- BUY --------------- - /// ---------- Should Approve - Buy without Authorizer ---------- + /// ---------- Should Approve ---------- + /// Buy without Authorizer, paying Marketplace Fee await tester.test( "Buy", - "Can Buy NFT without authorizer", + "can buy nft without authorizer", new Test(program, async (hash) => { const fixture = new BuyFixture(hash); fixture.payouts = [ @@ -33,7 +34,7 @@ const runTests = async (file: string) => { { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; fixture.spendingUtxoId = getNewFakeUtxoId(); - fixture.datumTag = await buildDatumTag( + fixture.datumTag = buildDatumTag( new helios.TxOutputId(fixture.spendingUtxoId) ); fixture.payoutOutputs = [ @@ -48,6 +49,65 @@ const runTests = async (file: string) => { return await fixture.initialize(); }) ); + + /// ---------- Should Deny - Marketplace Output Datum Tag is not correct ---------- + /// Buy without Authorizer, paying Marketplace Fee + await tester.test( + "Buy", + "can not buy nft without authorizer, if marketplace output datum tag is not correct", + new Test(program, async (hash) => { + const fixture = new BuyFixture(hash); + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + fixture.spendingUtxoId = getNewFakeUtxoId(); + fixture.payoutOutputs = [ + { + address: MARKETPLACE_ADDRESS, + amountLovelace: adaToLovelace(2), + }, + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + return await fixture.initialize(); + }), + false, + "Marketplace fee output's datum must be match datum tag" + ); + + /// ---------- Should Deny - Marketplace Fee is not correct ---------- + /// Buy without Authorizer, paying Marketplace Fee + await tester.test( + "Buy", + "can not buy nft without authorizer, if marketplace fee is not correct", + new Test(program, async (hash) => { + const fixture = new BuyFixture(hash); + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + fixture.spendingUtxoId = getNewFakeUtxoId(); + fixture.datumTag = buildDatumTag( + new helios.TxOutputId(fixture.spendingUtxoId) + ); + fixture.payoutOutputs = [ + { + address: MARKETPLACE_ADDRESS, + amountLovelace: adaToLovelace(2), + }, + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + return await fixture.initialize(); + }), + false, + "Marketplace fee must be paid" + ); }; (async () => { diff --git a/src/tests/utils.ts b/src/tests/utils.ts index 31f976d..e1d62d8 100644 --- a/src/tests/utils.ts +++ b/src/tests/utils.ts @@ -7,9 +7,7 @@ import Decimal from "decimal.js"; const adaToLovelace = (ada: number): number => new Decimal(ada).mul(Math.pow(10, 6)).floor().toNumber(); -const buildDatumTag = async ( - outputRef: helios.TxOutputId -): Promise => { +const buildDatumTag = (outputRef: helios.TxOutputId): helios.Datum => { const cbor = outputRef._toUplcData().toCborHex(); const hashed = helios.Crypto.blake2b(helios.hexToBytes(cbor)); return helios.Datum.inline( From 0760481ee0a878809743935b22b964b11db0f3fd Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 22 Aug 2024 22:14:44 +0800 Subject: [PATCH 06/20] add tests --- src/tests/constants.ts | 5 +- src/tests/fixtures.ts | 91 +++++++++++++- src/tests/tx.test.ts | 266 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 348 insertions(+), 14 deletions(-) diff --git a/src/tests/constants.ts b/src/tests/constants.ts index 170cefe..1225761 100644 --- a/src/tests/constants.ts +++ b/src/tests/constants.ts @@ -2,10 +2,12 @@ import * as helios from "@koralabs/helios"; const HANDLE_POLICY_ID = "f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a"; +const SPAM_TOKEN_POLICY_ID = + "01234567890123456789012345678901234567890123456789999999"; const AUTHORIZERS_PUB_KEY_HAHSES = [ helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789000001" - ), /// vailid + ), /// valid helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789000002" ), @@ -55,6 +57,7 @@ const minLovelace = 10_000_000n; export { HANDLE_POLICY_ID, + SPAM_TOKEN_POLICY_ID, AUTHORIZERS_PUB_KEY_HAHSES, OWNER_PUB_KEY_HASH, MARKETPLACE_ADDRESS, diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts index d09bcfd..b0e516e 100644 --- a/src/tests/fixtures.ts +++ b/src/tests/fixtures.ts @@ -1,4 +1,9 @@ -import { HANDLE_POLICY_ID, minLovelace, OWNER_PUB_KEY_HASH } from "./constants"; +import { + HANDLE_POLICY_ID, + minLovelace, + OWNER_PUB_KEY_HASH, + SPAM_TOKEN_POLICY_ID, +} from "./constants"; import { Payout } from "./types"; import { buildDatum } from "./utils"; @@ -17,9 +22,8 @@ helios.config.set({ IS_TESTNET: false, AUTO_SET_VALIDITY_RANGE: true }); class BuyFixture extends Fixture { handleName = "golddydev"; - buyRedeemer = { - constructor_0: [0], - }; + payoutOutputsOffset = 0; + buyRedeemer = { constructor_0: [0] }; buyRedeemerCbor: string = ""; spendingUtxoId: string = ""; @@ -34,6 +38,9 @@ class BuyFixture extends Fixture { } async initialize() { + this.buyRedeemer = { + constructor_0: [this.payoutOutputsOffset], + }; this.buyRedeemerCbor = await convertJsontoCbor(this.buyRedeemer); this.redeemer = helios.UplcData.fromCbor(this.buyRedeemerCbor); const datum = await buildDatum(this.payouts, this.owner); @@ -45,6 +52,18 @@ class BuyFixture extends Fixture { new helios.Value(BigInt(500_000_000)) ) ), + new helios.TxInput( // spam money + new helios.TxOutputId(getNewFakeUtxoId()), + new helios.TxOutput( + await getAddressAtDerivation(0), + new helios.Value(BigInt(100_000_000), [ + [ + SPAM_TOKEN_POLICY_ID, + [[Buffer.from("Spam").toString("hex"), 100_000_000]], + ], + ]) + ) + ), new helios.TxInput( /// Handle NFT to Buy new helios.TxOutputId(this.spendingUtxoId), new helios.TxOutput( @@ -72,7 +91,7 @@ class BuyFixture extends Fixture { new helios.TxOutput( /// marketplace address payout.address, new helios.Value(payout.amountLovelace), - index == 0 ? this.datumTag : undefined + index == this.payoutOutputsOffset ? this.datumTag : undefined ) ); @@ -82,4 +101,64 @@ class BuyFixture extends Fixture { } } -export { BuyFixture }; +class WithdrawOrUpdateFixture extends Fixture { + handleName = "golddydev"; + + withdrawOrUpdateRedeemer = { constructor_1: [] }; + withdrawOrUpdateRedeemerCbor: string = ""; + + payouts: Payout[] = []; + newPayouts: Payout[] | undefined = undefined; + owner: helios.PubKeyHash = OWNER_PUB_KEY_HASH; + + nftOutputAddress: helios.Address = helios.Address.fromHash(this.owner); + + constructor(validatorHash: helios.ValidatorHash) { + super(validatorHash); + } + + async initialize() { + this.withdrawOrUpdateRedeemerCbor = await convertJsontoCbor( + this.withdrawOrUpdateRedeemer + ); + this.redeemer = helios.UplcData.fromCbor(this.withdrawOrUpdateRedeemerCbor); + const datum = await buildDatum(this.payouts, this.owner); + + const nftValue = new helios.Value(minLovelace, [ + [ + HANDLE_POLICY_ID, + [ + [ + `${AssetNameLabel.LBL_222}${Buffer.from(this.handleName).toString( + "hex" + )}`, + 1, + ], + ], + ], + ]); + this.inputs = [ + new helios.TxInput( // money & collateral + new helios.TxOutputId(getNewFakeUtxoId()), + new helios.TxOutput( + await getAddressAtDerivation(0), + new helios.Value(BigInt(500_000_000)) + ) + ), + new helios.TxInput( /// Handle NFT to withdraw or update + new helios.TxOutputId(getNewFakeUtxoId()), + new helios.TxOutput(this.scriptAddress, nftValue, datum) + ), + ]; + + const newDatum = this.newPayouts + ? await buildDatum(this.newPayouts, this.owner) + : null; + this.outputs = [ + new helios.TxOutput(this.nftOutputAddress, nftValue, newDatum), + ]; + return this; + } +} + +export { BuyFixture, WithdrawOrUpdateFixture }; diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index 19e45eb..089593a 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -1,5 +1,10 @@ -import { MARKETPLACE_ADDRESS, PAYOUT_ADDRESSES } from "./constants"; -import { BuyFixture } from "./fixtures"; +import { + AUTHORIZERS_PUB_KEY_HAHSES, + MARKETPLACE_ADDRESS, + PAYOUT_ADDRESSES, + SPAM_TOKEN_POLICY_ID, +} from "./constants"; +import { BuyFixture, WithdrawOrUpdateFixture } from "./fixtures"; import { adaToLovelace, buildDatumTag } from "./utils"; import * as helios from "@koralabs/helios"; @@ -14,7 +19,7 @@ import fs from "fs/promises"; const runTests = async (file: string) => { const walletAddress = await getAddressAtDerivation(0); const tester = new ContractTester(walletAddress, false); - await tester.init(); + await tester.init("Update"); const contractFile = (await fs.readFile(file)).toString(); const program = helios.Program.new(contractFile); //new instance @@ -28,16 +33,52 @@ const runTests = async (file: string) => { "can buy nft without authorizer", new Test(program, async (hash) => { const fixture = new BuyFixture(hash); + fixture.spendingUtxoId = getNewFakeUtxoId(); + fixture.datumTag = buildDatumTag( + new helios.TxOutputId(fixture.spendingUtxoId) + ); + fixture.payouts = [ { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; + fixture.payoutOutputs = [ + { + address: MARKETPLACE_ADDRESS, + amountLovelace: adaToLovelace(Math.ceil((100 + 150 + 80) / 49)), + }, + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + return await fixture.initialize(); + }) + ); + + /// ---------- Should Approve ---------- + /// Buy without Authorizer, paying Marketplace Fee, with payout_outputs_offset = 4 + await tester.test( + "Buy", + "can buy nft without authorizer with offset", + new Test(program, async (hash) => { + const fixture = new BuyFixture(hash); + fixture.payoutOutputsOffset = 4; fixture.spendingUtxoId = getNewFakeUtxoId(); fixture.datumTag = buildDatumTag( new helios.TxOutputId(fixture.spendingUtxoId) ); + + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; fixture.payoutOutputs = [ + { address: PAYOUT_ADDRESSES[4], amountLovelace: adaToLovelace(10) }, + { address: PAYOUT_ADDRESSES[4], amountLovelace: adaToLovelace(10) }, + { address: PAYOUT_ADDRESSES[4], amountLovelace: adaToLovelace(5) }, + { address: PAYOUT_ADDRESSES[4], amountLovelace: adaToLovelace(2) }, { address: MARKETPLACE_ADDRESS, amountLovelace: adaToLovelace(Math.ceil((100 + 150 + 80) / 49)), @@ -50,6 +91,33 @@ const runTests = async (file: string) => { }) ); + /// ---------- Should Approve ---------- + /// Buy with Authorizer, not paying Marketplace Fee + await tester.test( + "Buy", + "can buy nft with authorizer", + new Test(program, async (hash) => { + const fixture = new BuyFixture(hash); + fixture.authorizers = [AUTHORIZERS_PUB_KEY_HAHSES[0]]; + fixture.spendingUtxoId = getNewFakeUtxoId(); + fixture.datumTag = buildDatumTag( + new helios.TxOutputId(fixture.spendingUtxoId) + ); + + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + fixture.payoutOutputs = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + return await fixture.initialize(); + }) + ); + /// ---------- Should Deny - Marketplace Output Datum Tag is not correct ---------- /// Buy without Authorizer, paying Marketplace Fee await tester.test( @@ -57,12 +125,13 @@ const runTests = async (file: string) => { "can not buy nft without authorizer, if marketplace output datum tag is not correct", new Test(program, async (hash) => { const fixture = new BuyFixture(hash); + fixture.spendingUtxoId = getNewFakeUtxoId(); + fixture.payouts = [ { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; - fixture.spendingUtxoId = getNewFakeUtxoId(); fixture.payoutOutputs = [ { address: MARKETPLACE_ADDRESS, @@ -85,19 +154,52 @@ const runTests = async (file: string) => { "can not buy nft without authorizer, if marketplace fee is not correct", new Test(program, async (hash) => { const fixture = new BuyFixture(hash); + fixture.spendingUtxoId = getNewFakeUtxoId(); + fixture.datumTag = buildDatumTag( + new helios.TxOutputId(fixture.spendingUtxoId) + ); + fixture.payouts = [ { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; + fixture.payoutOutputs = [ + { + address: MARKETPLACE_ADDRESS, + amountLovelace: adaToLovelace(2), + }, + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + return await fixture.initialize(); + }), + false, + "Marketplace fee must be paid" + ); + + /// ---------- Should Deny - Marketplace Address is not correct ---------- + /// Buy without Authorizer, paying Marketplace Fee + await tester.test( + "Buy", + "can not buy nft without authorizer, if marketplace address is not correct", + new Test(program, async (hash) => { + const fixture = new BuyFixture(hash); fixture.spendingUtxoId = getNewFakeUtxoId(); fixture.datumTag = buildDatumTag( new helios.TxOutputId(fixture.spendingUtxoId) ); + + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; fixture.payoutOutputs = [ { - address: MARKETPLACE_ADDRESS, - amountLovelace: adaToLovelace(2), + address: PAYOUT_ADDRESSES[4], /// wrong marketplace address + amountLovelace: adaToLovelace(Math.ceil((100 + 150 + 80) / 49)), }, { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, @@ -106,7 +208,157 @@ const runTests = async (file: string) => { return await fixture.initialize(); }), false, - "Marketplace fee must be paid" + "Marketplace address must be correct" + ); + + /// ---------- Should Deny - Token Spamming ---------- + /// Buy without Authorizer, paying Marketplace Fee + await tester.test( + "Buy", + "can not buy nft without authorizer, if token spam to marketplace address", + new Test(program, async (hash) => { + const fixture = new BuyFixture(hash); + fixture.spendingUtxoId = getNewFakeUtxoId(); + fixture.datumTag = buildDatumTag( + new helios.TxOutputId(fixture.spendingUtxoId) + ); + + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + fixture.payoutOutputs = [ + { + address: MARKETPLACE_ADDRESS, /// wrong marketplace address + amountLovelace: adaToLovelace(Math.ceil((100 + 150 + 80) / 49)), + }, + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + const initialized = await fixture.initialize(); + initialized.outputs?.[0].setValue( + new helios.Value(adaToLovelace(Math.ceil((100 + 150 + 80) / 49)), [ + [ + SPAM_TOKEN_POLICY_ID, + [[Buffer.from("Spam").toString("hex"), 100_000_000]], + ], + ]) + ); + return initialized; + }), + false, + "Must pay with only lovelace" + ); + + /// ---------- Should Deny - Authorizer is not correct ---------- + /// Buy with Authorizer, not paying Marketplace Fee + await tester.test( + "Buy", + "can not buy nft with authorizer, if authorizer is not correct", + new Test(program, async (hash) => { + const fixture = new BuyFixture(hash); + fixture.authorizers = [AUTHORIZERS_PUB_KEY_HAHSES[2]]; + fixture.spendingUtxoId = getNewFakeUtxoId(); + fixture.datumTag = buildDatumTag( + new helios.TxOutputId(fixture.spendingUtxoId) + ); + + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + fixture.payoutOutputs = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + return await fixture.initialize(); + }), + false, + "First output address must be matched with payout" + ); + + /// --------------- WITHDRAW or UPDATE --------------- + + /// ---------- Should Approve ---------- + /// Withdraw + await tester.test( + "Withdraw", + "can withdraw nft", + new Test(program, async (hash) => { + const fixture = new WithdrawOrUpdateFixture(hash); + + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + fixture.signatories = [fixture.owner]; + return await fixture.initialize(); + }) + ); + + /// ---------- Should Deny - Owner not signed ---------- + /// Withdraw without owner signature + await tester.test( + "Withdraw", + "can not withdraw nft, if owner not signed", + new Test(program, async (hash) => { + const fixture = new WithdrawOrUpdateFixture(hash); + + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + return await fixture.initialize(); + }), + false + ); + + /// ---------- Should Approve ---------- + /// Update + await tester.test( + "Update", + "can update nft", + new Test(program, async (hash) => { + const fixture = new WithdrawOrUpdateFixture(hash); + + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + fixture.newPayouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + ]; + fixture.signatories = [fixture.owner]; + return await fixture.initialize(); + }) + ); + + /// ---------- Should Deny - Owner not signed ---------- + /// Update without owner signature + await tester.test( + "Update", + "can not update nft, if owner not signed", + new Test(program, async (hash) => { + const fixture = new WithdrawOrUpdateFixture(hash); + + fixture.payouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, + { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, + ]; + fixture.newPayouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + ]; + return await fixture.initialize(); + }), + false ); }; From 13f0048111719c1acf80c696ecb8a0553a5fa65a Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 22 Aug 2024 22:15:03 +0800 Subject: [PATCH 07/20] update tester init --- src/tests/tx.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index 089593a..a9bfba1 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -19,7 +19,7 @@ import fs from "fs/promises"; const runTests = async (file: string) => { const walletAddress = await getAddressAtDerivation(0); const tester = new ContractTester(walletAddress, false); - await tester.init("Update"); + await tester.init(); const contractFile = (await fs.readFile(file)).toString(); const program = helios.Program.new(contractFile); //new instance From 5fcd3158c096b90fcf0f42ae87704adaddef6eb3 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Tue, 27 Aug 2024 23:18:00 +0800 Subject: [PATCH 08/20] add list command --- .env.example | 2 + .eslintrc.json | 3 +- bin/marketplace | 10 ++++ package-lock.json | 29 +++++++++- package.json | 8 ++- src/cli.ts | 12 ++++ src/commands/list.ts | 49 ++++++++++++++++ src/config.ts | 23 ++++++++ src/{tests/utils.ts => datum.ts} | 10 ++-- src/entrypoint.ts | 37 +++++++++++++ src/helpers/blockfrost/index.ts | 1 + src/helpers/blockfrost/network.ts | 11 ++++ src/helpers/common/file.ts | 12 ++++ src/helpers/common/index.ts | 2 + src/helpers/common/invariant.ts | 19 +++++++ src/helpers/config/index.ts | 28 ++++++++++ src/helpers/error/convert.ts | 29 ++++++++++ src/helpers/error/handleable.ts | 31 +++++++++++ src/helpers/error/handleableAsync.ts | 35 ++++++++++++ src/helpers/error/index.ts | 5 ++ src/helpers/index.ts | 4 ++ src/list.ts | 83 ++++++++++++++++++++++++++++ src/tests/constants.ts | 14 +++-- src/tests/fixtures.ts | 11 ++-- src/tests/tx.test.ts | 4 +- src/{tests => }/types.ts | 0 src/utils/common.ts | 6 ++ src/utils/contract.ts | 24 ++++++++ src/utils/index.ts | 2 + 29 files changed, 483 insertions(+), 21 deletions(-) create mode 100644 .env.example create mode 100755 bin/marketplace create mode 100644 src/cli.ts create mode 100644 src/commands/list.ts create mode 100644 src/config.ts rename src/{tests/utils.ts => datum.ts} (82%) create mode 100644 src/entrypoint.ts create mode 100644 src/helpers/blockfrost/index.ts create mode 100644 src/helpers/blockfrost/network.ts create mode 100644 src/helpers/common/file.ts create mode 100644 src/helpers/common/index.ts create mode 100644 src/helpers/common/invariant.ts create mode 100644 src/helpers/config/index.ts create mode 100644 src/helpers/error/convert.ts create mode 100644 src/helpers/error/handleable.ts create mode 100644 src/helpers/error/handleableAsync.ts create mode 100644 src/helpers/error/index.ts create mode 100644 src/helpers/index.ts create mode 100644 src/list.ts rename src/{tests => }/types.ts (100%) create mode 100644 src/utils/common.ts create mode 100644 src/utils/contract.ts create mode 100644 src/utils/index.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7684b5a --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +BLOCKFROST_API_KEY = +HANDLE_POLICY_ID = f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a diff --git a/.eslintrc.json b/.eslintrc.json index c4f3805..7c1b546 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -57,6 +57,7 @@ ["^.+\\.?(css)$"] ] } - ] + ], + "simple-import-sort/exports": "error" } } diff --git a/bin/marketplace b/bin/marketplace new file mode 100755 index 0000000..6d32802 --- /dev/null +++ b/bin/marketplace @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e + +SCRIPT_PATH=$(readlink -f "$0") +SCRIPT_DIR=$(dirname "$SCRIPT_PATH") +SCRIPT=$(realpath "$SCRIPT_DIR/../handles-marketplace-contracts/src/entrypoints/cli.ts" 2>/dev/null || realpath "$SCRIPT_DIR/../src/entrypoint.ts") +TSX=$(realpath "$SCRIPT_DIR/../node_modules/.bin/tsx") + +"$TSX" "$SCRIPT" "$@" diff --git a/package-lock.json b/package-lock.json index acfb791..723c168 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,13 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "decimal.js": "^10.4.3" + "app-root-path": "^3.1.0", + "commander": "^12.1.0", + "decimal.js": "^10.4.3", + "ts-res": "^1.1.1" + }, + "bin": { + "marketplace": "bin/marketplace" }, "devDependencies": { "@koralabs/helios": "0.16.8-1", @@ -937,6 +943,14 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1355,6 +1369,14 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "engines": { + "node": ">=18" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3979,6 +4001,11 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-res": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ts-res/-/ts-res-1.1.1.tgz", + "integrity": "sha512-mhpSnTiHdJELzr00XaXlXg9SwOEyybZieocKuF2yRrjofg2ZgNNX4diKQ775FydnpUEvif9r1Y0EVt1Lz5iJCw==" + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", diff --git a/package.json b/package.json index f19a11f..ddf8a6c 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,9 @@ "lint": "concurrently \"npx prettier --check '**/*.{js,ts,json,.*}'\" \"npx eslint . --max-warnings=0\"", "test": "tsx -r dotenv/config src/tests/tx.test.ts" }, + "bin": { + "marketplace": "./bin/marketplace" + }, "keywords": [], "author": "Kora Labs ", "license": "ISC", @@ -30,6 +33,9 @@ "tsx": "^4.17.0" }, "dependencies": { - "decimal.js": "^10.4.3" + "app-root-path": "^3.1.0", + "commander": "^12.1.0", + "decimal.js": "^10.4.3", + "ts-res": "^1.1.1" } } diff --git a/src/cli.ts b/src/cli.ts new file mode 100644 index 0000000..ad05328 --- /dev/null +++ b/src/cli.ts @@ -0,0 +1,12 @@ +import { packageJson } from "./helpers"; + +import { Command } from "commander"; + +const program = new Command(); + +program + .name("marketplace") + .version(packageJson.version) + .description(packageJson.description); + +export default program; diff --git a/src/commands/list.ts b/src/commands/list.ts new file mode 100644 index 0000000..fa1b45b --- /dev/null +++ b/src/commands/list.ts @@ -0,0 +1,49 @@ +import program from "../cli"; +import { loadConfig } from "../config"; +import { list } from "../list"; +import { adaToLovelace } from "../utils"; + +import * as helios from "@koralabs/helios"; + +const buyCommand = program + .command("list") + .description("List Handle NFT on Marketplace") + .argument("", "Ada Handle Name to list on marketplace") + .argument("", "Price in ada") + .argument("
", "Address to perform listing") + .argument("", "Address who create this NFT") + .action( + async ( + handleName: string, + priceString: string, + bech32Address: string, + creatorBech32Address: string + ) => { + const configResult = loadConfig(); + if (!configResult.ok) return program.error(configResult.error); + const config = configResult.data; + + const address = helios.Address.fromBech32(bech32Address); + const creatorAddress = helios.Address.fromBech32(creatorBech32Address); + const txResult = await list( + config.blockfrostApiKey, + address, + config.handlePolicyId, + handleName, + [ + { address, amountLovelace: adaToLovelace(Number(priceString) * 0.9) }, + { + address: creatorAddress, + amountLovelace: adaToLovelace(Number(priceString) * 0.1), + }, + ], + address + ); + + if (!txResult.ok) return program.error(txResult.error); + console.log("Transaction CBOR Hex, copy and paste to wallet\n"); + console.log(txResult.data.toCborHex()); + } + ); + +export default buyCommand; diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..7a4a7eb --- /dev/null +++ b/src/config.ts @@ -0,0 +1,23 @@ +import { get, getNetwork, loadEnv } from "./helpers"; + +import { Err, Ok } from "ts-res"; + +loadEnv(); + +const loadConfig = () => { + const blockfrostApiKey = get("BLOCKFROST_API_KEY", "string"); + if (!blockfrostApiKey.ok) return Err(blockfrostApiKey.error); + + const handlePolicyId = get("HANDLE_POLICY_ID", "string"); + if (!handlePolicyId.ok) return Err(handlePolicyId.error); + + const network = getNetwork(blockfrostApiKey.data); + + return Ok({ + blockfrostApiKey: blockfrostApiKey.data, + handlePolicyId: handlePolicyId.data, + network, + }); +}; + +export { loadConfig }; diff --git a/src/tests/utils.ts b/src/datum.ts similarity index 82% rename from src/tests/utils.ts rename to src/datum.ts index e1d62d8..6955205 100644 --- a/src/tests/utils.ts +++ b/src/datum.ts @@ -1,11 +1,8 @@ +import { invariant } from "./helpers"; import { Payout } from "./types"; import * as helios from "@koralabs/helios"; import { convertJsontoCbor } from "@koralabs/kora-labs-contract-testing"; -import Decimal from "decimal.js"; - -const adaToLovelace = (ada: number): number => - new Decimal(ada).mul(Math.pow(10, 6)).floor().toNumber(); const buildDatumTag = (outputRef: helios.TxOutputId): helios.Datum => { const cbor = outputRef._toUplcData().toCborHex(); @@ -17,8 +14,9 @@ const buildDatumTag = (outputRef: helios.TxOutputId): helios.Datum => { const buildDatum = async ( payouts: Payout[], - owner: helios.PubKeyHash + owner: helios.Address ): Promise => { + invariant(!!owner.pubKeyHash, "Not valid owner"); const constrPayout = (payout: Payout) => [ { constructor_0: [ @@ -38,4 +36,4 @@ const buildDatum = async ( return helios.Datum.inline(helios.UplcData.fromCbor(datumCbor)); }; -export { adaToLovelace, buildDatumTag, buildDatum }; +export { buildDatum, buildDatumTag }; diff --git a/src/entrypoint.ts b/src/entrypoint.ts new file mode 100644 index 0000000..8062690 --- /dev/null +++ b/src/entrypoint.ts @@ -0,0 +1,37 @@ +import program from "./cli"; +import { getDirname, loadEnv } from "./helpers"; + +import fs from "fs/promises"; +import path from "path"; + +const commandsDir = path.join(getDirname(import.meta.url), "commands"); + +const loadCommands = async (directory: string) => { + const items = await fs.readdir(directory, { withFileTypes: true }); + + for (const item of items) { + const fullPath = path.join(directory, item.name); + + if (item.isDirectory()) await loadCommands(fullPath); + else if ( + item.isFile() && + item.name.endsWith(".ts") && + !item.name.endsWith(".d.ts") + ) + await import(fullPath); + } +}; + +const run = async () => { + loadEnv(); + await loadCommands(commandsDir); + + try { + await program.parseAsync(process.argv); + } catch (error) { + console.error(error); + process.exit(1); + } +}; + +run(); diff --git a/src/helpers/blockfrost/index.ts b/src/helpers/blockfrost/index.ts new file mode 100644 index 0000000..3646679 --- /dev/null +++ b/src/helpers/blockfrost/index.ts @@ -0,0 +1 @@ +export * from "./network"; diff --git a/src/helpers/blockfrost/network.ts b/src/helpers/blockfrost/network.ts new file mode 100644 index 0000000..1476408 --- /dev/null +++ b/src/helpers/blockfrost/network.ts @@ -0,0 +1,11 @@ +const getNetwork = (apiKey: string): "mainnet" | "preview" | "preprod" => { + const network = apiKey.substring(0, 7); + + if (network !== "mainnet" && network !== "preview" && network !== "preprod") { + throw new Error(`Unknown network ${network}`); + } + + return network; +}; + +export { getNetwork }; diff --git a/src/helpers/common/file.ts b/src/helpers/common/file.ts new file mode 100644 index 0000000..a103153 --- /dev/null +++ b/src/helpers/common/file.ts @@ -0,0 +1,12 @@ +import appRoot from "app-root-path"; +import fs from "fs"; +import path, { dirname } from "path"; +import { fileURLToPath } from "url"; + +const getDirname = (calledFrom: string) => dirname(fileURLToPath(calledFrom)); + +const packageJson = JSON.parse( + fs.readFileSync(path.join(appRoot.path, "package.json"), "utf-8") +); + +export { getDirname, packageJson }; diff --git a/src/helpers/common/index.ts b/src/helpers/common/index.ts new file mode 100644 index 0000000..e0d0517 --- /dev/null +++ b/src/helpers/common/index.ts @@ -0,0 +1,2 @@ +export * from "./file"; +export * from "./invariant"; diff --git a/src/helpers/common/invariant.ts b/src/helpers/common/invariant.ts new file mode 100644 index 0000000..0bfbb57 --- /dev/null +++ b/src/helpers/common/invariant.ts @@ -0,0 +1,19 @@ +const prefix: string = "Invariant failed"; + +const invariant: ( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + condition: any, + message?: string | (() => string) +) => asserts condition = (condition, message?: string | (() => string)) => { + if (condition) { + return; + } + + const provided: string | undefined = + typeof message === "function" ? message() : message; + + const value: string = provided ? `${prefix}: ${provided}` : prefix; + throw new Error(value); +}; + +export { invariant }; diff --git a/src/helpers/config/index.ts b/src/helpers/config/index.ts new file mode 100644 index 0000000..55cd03d --- /dev/null +++ b/src/helpers/config/index.ts @@ -0,0 +1,28 @@ +import { mayFail } from "../error"; + +import { config, DotenvConfigOptions } from "dotenv"; +import { Err, Ok, Result } from "ts-res"; + +type ConfigTypeNames = "string" | "number"; +type ConfigTypes = string | number; + +const loadEnv = (options?: DotenvConfigOptions) => { + mayFail(() => config(options)); +}; + +function get(key: string, type: "string"): Result; +function get(key: string, type: "number"): Result; +function get(key: string, type: ConfigTypeNames): Result { + const v = process.env[key]; + if (v === undefined) return Err(`${key} is not set.`); + if (type === "string") return Ok(v); + if (!Number.isNaN(Number(v))) return Ok(Number(v)); + return Err(`${key} in env is not ${type} type.`); +} + +function has(key: string): boolean { + const v = process.env[key]; + return v !== undefined; +} + +export { get, has, loadEnv }; diff --git a/src/helpers/error/convert.ts b/src/helpers/error/convert.ts new file mode 100644 index 0000000..2aeba8f --- /dev/null +++ b/src/helpers/error/convert.ts @@ -0,0 +1,29 @@ +import { stringify } from "flatted"; + +const convertError = (item: unknown): string => { + if (typeof item === "undefined") { + return "undefined"; + } + + if ( + item && + typeof item === "object" && + "message" in item && + typeof item.message === "string" + ) + return item.message; + + if (typeof item === "string") return item; + + const stringified = (() => { + try { + return stringify(item).slice(1).slice(0, -1); + } catch { + return String(item); + } + })(); + + return stringified.replace(/^'|'$/g, ""); +}; + +export default convertError; diff --git a/src/helpers/error/handleable.ts b/src/helpers/error/handleable.ts new file mode 100644 index 0000000..c43c22b --- /dev/null +++ b/src/helpers/error/handleable.ts @@ -0,0 +1,31 @@ +import convertError from "./convert"; + +import { Err, Ok, Result } from "ts-res"; + +type Callback = () => T; +type ErrType = string | Error | void | undefined; +type HandleableResult = Result & { + handle: (handler: (error: E) => void) => Result; +}; + +const toHandleable = ( + result: Result +): HandleableResult => { + return { + ...result, + handle: (handler: (error: E) => void) => { + if (!result.ok) handler(result.error); + return result; + }, + }; +}; + +const mayFail = (callback: Callback): HandleableResult => { + try { + return toHandleable(Ok(callback())); + } catch (error) { + return toHandleable(Err(convertError(error))); + } +}; + +export { mayFail }; diff --git a/src/helpers/error/handleableAsync.ts b/src/helpers/error/handleableAsync.ts new file mode 100644 index 0000000..d658321 --- /dev/null +++ b/src/helpers/error/handleableAsync.ts @@ -0,0 +1,35 @@ +import convertError from "./convert"; + +import { Err, Ok, Result } from "ts-res"; + +type Callback = () => Promise; +type ErrType = string | Error | void | undefined; +type HandleableResult = { + handle: (handler: (e: E) => void) => HandleableResult; + complete: () => Promise>; +}; + +const mayFailAsync = ( + callback: Callback +): HandleableResult => { + const createHandleable = ( + handler: (e: string) => void + ): HandleableResult => { + return { + handle: (handler) => createHandleable(handler), + complete: async (): Promise> => { + try { + return Ok(await callback()); + } catch (err) { + const errMsg = convertError(err); + handler(errMsg); + return Err(errMsg); + } + }, + }; + }; + + return createHandleable(() => {}); +}; + +export { mayFailAsync }; diff --git a/src/helpers/error/index.ts b/src/helpers/error/index.ts new file mode 100644 index 0000000..f9cdf71 --- /dev/null +++ b/src/helpers/error/index.ts @@ -0,0 +1,5 @@ +import convertError from "./convert"; + +export * from "./handleable"; +export * from "./handleableAsync"; +export { convertError }; diff --git a/src/helpers/index.ts b/src/helpers/index.ts new file mode 100644 index 0000000..eac96b2 --- /dev/null +++ b/src/helpers/index.ts @@ -0,0 +1,4 @@ +export * from "./blockfrost"; +export * from "./common"; +export * from "./config"; +export * from "./error"; diff --git a/src/list.ts b/src/list.ts new file mode 100644 index 0000000..89e1147 --- /dev/null +++ b/src/list.ts @@ -0,0 +1,83 @@ +import { buildDatum } from "./datum"; +import { getNetwork, mayFailAsync } from "./helpers"; +import { Payout } from "./types"; +import { getUplcProgram } from "./utils"; + +import * as helios from "@koralabs/helios"; +import { AssetNameLabel } from "@koralabs/kora-labs-common"; +import { Err, Ok, Result } from "ts-res"; + +/// payouts +const list = async ( + blockfrostApiKey: string, + address: helios.Address, + handlePolicyId: string, + handleName: string, + payouts: Payout[], + owner: helios.Address +): Promise> => { + const network = getNetwork(blockfrostApiKey); + helios.config.set({ + IS_TESTNET: network != "mainnet", + AUTO_SET_VALIDITY_RANGE: true, + }); + + const api = new helios.BlockfrostV0(network, blockfrostApiKey); + const paramterResult = await mayFailAsync(() => + api.getParameters() + ).complete(); + if (!paramterResult.ok) + return Err(`Getting Network Parameter ${paramterResult.error}`); + const paramter = paramterResult.data; + + const utxosResult = await mayFailAsync(() => + api.getUtxos(address) + ).complete(); + if (!utxosResult.ok) return Err(`Getting UTxOs error: ${utxosResult.error}`); + const utxos = utxosResult.data; + + const uplcProgramResult = await mayFailAsync(() => + getUplcProgram() + ).complete(); + if (!uplcProgramResult.ok) + return Err(`Getting Uplc Program error: ${uplcProgramResult.error}`); + const uplcProgram = uplcProgramResult.data; + + const handleAsset = new helios.Assets([ + [ + handlePolicyId, + [ + [ + `${AssetNameLabel.LBL_222}${Buffer.from(handleName).toString("hex")}`, + 1, + ], + ], + ], + ]); + + const minFee = 5_000_000n; + const minValue = new helios.Value(minFee, handleAsset); + const [selected] = helios.CoinSelection.selectLargestFirst(utxos, minValue); + + const tx = new helios.Tx(); + tx.addInputs(selected); + + const datum = await buildDatum(payouts, owner); + const output = new helios.TxOutput( + helios.Address.fromHash(uplcProgram.validatorHash, true), + new helios.Value(0n, handleAsset), + datum + ); + output.correctLovelace(paramter); + tx.addOutput(output); + + const txCompleteResult = await mayFailAsync(() => + tx.finalize(paramter, address) + ).complete(); + if (!txCompleteResult.ok) + return Err(`Finalizing Tx error: ${txCompleteResult.error}`); + + return Ok(txCompleteResult.data); +}; + +export { list }; diff --git a/src/tests/constants.ts b/src/tests/constants.ts index 1225761..56ae171 100644 --- a/src/tests/constants.ts +++ b/src/tests/constants.ts @@ -15,8 +15,10 @@ const AUTHORIZERS_PUB_KEY_HAHSES = [ "01234567890123456789012345678901234567890123456789000003" ), ]; -const OWNER_PUB_KEY_HASH = helios.PubKeyHash.fromHex( - "01234567890123456789012345678901234567890123456789111111" +const ONWER_ADDRESS = helios.Address.fromHash( + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789111111" + ) ); const MARKETPLACE_ADDRESS = helios.Address.fromHash( @@ -56,11 +58,11 @@ const PAYOUT_ADDRESSES = [ const minLovelace = 10_000_000n; export { - HANDLE_POLICY_ID, - SPAM_TOKEN_POLICY_ID, AUTHORIZERS_PUB_KEY_HAHSES, - OWNER_PUB_KEY_HASH, + HANDLE_POLICY_ID, MARKETPLACE_ADDRESS, - PAYOUT_ADDRESSES, minLovelace, + ONWER_ADDRESS, + PAYOUT_ADDRESSES, + SPAM_TOKEN_POLICY_ID, }; diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts index b0e516e..efbf943 100644 --- a/src/tests/fixtures.ts +++ b/src/tests/fixtures.ts @@ -1,11 +1,12 @@ +import { buildDatum } from "../datum"; +import { Payout } from "../types"; + import { HANDLE_POLICY_ID, minLovelace, - OWNER_PUB_KEY_HASH, + ONWER_ADDRESS, SPAM_TOKEN_POLICY_ID, } from "./constants"; -import { Payout } from "./types"; -import { buildDatum } from "./utils"; import * as helios from "@koralabs/helios"; import { AssetNameLabel } from "@koralabs/kora-labs-common"; @@ -28,7 +29,7 @@ class BuyFixture extends Fixture { spendingUtxoId: string = ""; payouts: Payout[] = []; - owner: helios.PubKeyHash = OWNER_PUB_KEY_HASH; + owner: helios.Address = ONWER_ADDRESS; authorizers: helios.PubKeyHash[] = []; datumTag: helios.Datum | null = null; payoutOutputs: Payout[] = []; @@ -109,7 +110,7 @@ class WithdrawOrUpdateFixture extends Fixture { payouts: Payout[] = []; newPayouts: Payout[] | undefined = undefined; - owner: helios.PubKeyHash = OWNER_PUB_KEY_HASH; + owner: helios.Address = ONWER_ADDRESS; nftOutputAddress: helios.Address = helios.Address.fromHash(this.owner); diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index a9bfba1..8ada582 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -1,3 +1,6 @@ +import { buildDatumTag } from "../datum"; +import { adaToLovelace } from "../utils"; + import { AUTHORIZERS_PUB_KEY_HAHSES, MARKETPLACE_ADDRESS, @@ -5,7 +8,6 @@ import { SPAM_TOKEN_POLICY_ID, } from "./constants"; import { BuyFixture, WithdrawOrUpdateFixture } from "./fixtures"; -import { adaToLovelace, buildDatumTag } from "./utils"; import * as helios from "@koralabs/helios"; import { diff --git a/src/tests/types.ts b/src/types.ts similarity index 100% rename from src/tests/types.ts rename to src/types.ts diff --git a/src/utils/common.ts b/src/utils/common.ts new file mode 100644 index 0000000..ab335d3 --- /dev/null +++ b/src/utils/common.ts @@ -0,0 +1,6 @@ +import Decimal from "decimal.js"; + +const adaToLovelace = (ada: number): number => + new Decimal(ada).mul(Math.pow(10, 6)).floor().toNumber(); + +export { adaToLovelace }; diff --git a/src/utils/contract.ts b/src/utils/contract.ts new file mode 100644 index 0000000..6478ca9 --- /dev/null +++ b/src/utils/contract.ts @@ -0,0 +1,24 @@ +import { getDirname } from "../helpers"; + +import * as helios from "@koralabs/helios"; +import fs from "fs/promises"; +import path from "path"; + +const dirname = getDirname(import.meta.url); +const contractPath = path.join(dirname, "../contract/marketplace.helios"); + +const getHeliosProgram = async (): Promise => { + const contractFile = (await fs.readFile(contractPath)).toString(); + const program = helios.Program.new(contractFile); + return program; +}; + +const getUplcProgram = async ( + optimize: boolean = false +): Promise => { + const program = await getHeliosProgram(); + + return program.compile(optimize); +}; + +export { getHeliosProgram, getUplcProgram }; diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..93aceda --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from "./common"; +export * from "./contract"; From a4a107e10e1c813611ff6e72050c0e3a10acf2ad Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Tue, 27 Aug 2024 23:49:14 +0800 Subject: [PATCH 09/20] parameterize --- src/commands/list.ts | 12 +++++++++++- src/contract/marketplace.helios | 8 +++++--- src/list.ts | 7 ++++--- src/tests/constants.ts | 8 +++----- src/tests/fixtures.ts | 6 ++++-- src/tests/tx.test.ts | 2 ++ src/types.ts | 7 ++++++- src/utils/contract.ts | 10 ++++++++-- 8 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/commands/list.ts b/src/commands/list.ts index fa1b45b..eaafb10 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -37,7 +37,17 @@ const buyCommand = program amountLovelace: adaToLovelace(Number(priceString) * 0.1), }, ], - address + address, + { + authorizers: [ + helios.PubKeyHash.fromHex( + "633a0061fcdb8aca5b86ef3a177fdcb0c178ccca3066b0be7197f3a1" + ), + ], + marketplaceAddress: helios.Address.fromBech32( + "addr_test1qp3n5qrplndc4jjmsmhn59mlmjcvz7xvegcxdv97wxtl8gthwj7fp7cy0tpvdzmd46u3c9tvjfxrpjc2faaqzm43wrpshmp3xw" + ), + } ); if (!txResult.ok) return program.error(txResult.error); diff --git a/src/contract/marketplace.helios b/src/contract/marketplace.helios index 300c491..c84bfc4 100644 --- a/src/contract/marketplace.helios +++ b/src/contract/marketplace.helios @@ -38,11 +38,13 @@ enum Redeemer { // ---------- Parameters ---------- const AUTHORIZERS: []PubKeyHash = []PubKeyHash{ - PubKeyHash::new(#01234567890123456789012345678901234567890123456789000001) + PubKeyHash::new(#) } const MARKETPLACE_ADDRESS: Address = Address::new( - Credential::new_pubkey(PubKeyHash::new(#01234567890123456789012345678901234567890123456789222222)), - Option[StakingCredential]::None + Credential::new_pubkey(PubKeyHash::new(#)), + Option[StakingCredential]::Some{ + StakingCredential::new_hash(StakingHash::new_stakekey(PubKeyHash::new(#))) + } ) // ---------- Functions ---------- diff --git a/src/list.ts b/src/list.ts index 89e1147..9a86971 100644 --- a/src/list.ts +++ b/src/list.ts @@ -1,6 +1,6 @@ import { buildDatum } from "./datum"; import { getNetwork, mayFailAsync } from "./helpers"; -import { Payout } from "./types"; +import { Parameters, Payout } from "./types"; import { getUplcProgram } from "./utils"; import * as helios from "@koralabs/helios"; @@ -14,7 +14,8 @@ const list = async ( handlePolicyId: string, handleName: string, payouts: Payout[], - owner: helios.Address + owner: helios.Address, + parameters: Parameters ): Promise> => { const network = getNetwork(blockfrostApiKey); helios.config.set({ @@ -37,7 +38,7 @@ const list = async ( const utxos = utxosResult.data; const uplcProgramResult = await mayFailAsync(() => - getUplcProgram() + getUplcProgram(parameters) ).complete(); if (!uplcProgramResult.ok) return Err(`Getting Uplc Program error: ${uplcProgramResult.error}`); diff --git a/src/tests/constants.ts b/src/tests/constants.ts index 56ae171..a45eb86 100644 --- a/src/tests/constants.ts +++ b/src/tests/constants.ts @@ -6,7 +6,7 @@ const SPAM_TOKEN_POLICY_ID = "01234567890123456789012345678901234567890123456789999999"; const AUTHORIZERS_PUB_KEY_HAHSES = [ helios.PubKeyHash.fromHex( - "01234567890123456789012345678901234567890123456789000001" + "633a0061fcdb8aca5b86ef3a177fdcb0c178ccca3066b0be7197f3a1" ), /// valid helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789000002" @@ -21,10 +21,8 @@ const ONWER_ADDRESS = helios.Address.fromHash( ) ); -const MARKETPLACE_ADDRESS = helios.Address.fromHash( - helios.PubKeyHash.fromHex( - "01234567890123456789012345678901234567890123456789222222" - ) +const MARKETPLACE_ADDRESS = helios.Address.fromBech32( + "addr_test1qp3n5qrplndc4jjmsmhn59mlmjcvz7xvegcxdv97wxtl8gthwj7fp7cy0tpvdzmd46u3c9tvjfxrpjc2faaqzm43wrpshmp3xw" ); const PAYOUT_ADDRESSES = [ diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts index efbf943..74762a2 100644 --- a/src/tests/fixtures.ts +++ b/src/tests/fixtures.ts @@ -18,7 +18,7 @@ import { } from "@koralabs/kora-labs-contract-testing"; /// setup -helios.config.set({ IS_TESTNET: false, AUTO_SET_VALIDITY_RANGE: true }); +helios.config.set({ IS_TESTNET: true, AUTO_SET_VALIDITY_RANGE: true }); class BuyFixture extends Fixture { handleName = "golddydev"; @@ -112,7 +112,9 @@ class WithdrawOrUpdateFixture extends Fixture { newPayouts: Payout[] | undefined = undefined; owner: helios.Address = ONWER_ADDRESS; - nftOutputAddress: helios.Address = helios.Address.fromHash(this.owner); + nftOutputAddress: helios.Address = helios.Address.fromBech32( + this.owner.toBech32() + ); constructor(validatorHash: helios.ValidatorHash) { super(validatorHash); diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index 8ada582..d99f7ce 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -25,6 +25,8 @@ const runTests = async (file: string) => { const contractFile = (await fs.readFile(file)).toString(); const program = helios.Program.new(contractFile); //new instance + program.parameters.AUTHORIZERS = [AUTHORIZERS_PUB_KEY_HAHSES[0]]; + program.parameters.MARKETPLACE_ADDRESS = MARKETPLACE_ADDRESS; /// --------------- BUY --------------- diff --git a/src/types.ts b/src/types.ts index d700f2a..f26a46e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,4 +5,9 @@ interface Payout { amountLovelace: number; } -export { Payout }; +interface Parameters { + authorizers: helios.PubKeyHash[]; + marketplaceAddress: helios.Address; +} + +export { Parameters, Payout }; diff --git a/src/utils/contract.ts b/src/utils/contract.ts index 6478ca9..f3fad64 100644 --- a/src/utils/contract.ts +++ b/src/utils/contract.ts @@ -1,4 +1,5 @@ import { getDirname } from "../helpers"; +import { Parameters } from "../types"; import * as helios from "@koralabs/helios"; import fs from "fs/promises"; @@ -7,16 +8,21 @@ import path from "path"; const dirname = getDirname(import.meta.url); const contractPath = path.join(dirname, "../contract/marketplace.helios"); -const getHeliosProgram = async (): Promise => { +const getHeliosProgram = async ( + parameters: Parameters +): Promise => { const contractFile = (await fs.readFile(contractPath)).toString(); const program = helios.Program.new(contractFile); + program.parameters.AUTHORIZERS = parameters.authorizers; + program.parameters.MARKETPLACE_ADDRESS = parameters.marketplaceAddress; return program; }; const getUplcProgram = async ( + parameters: Parameters, optimize: boolean = false ): Promise => { - const program = await getHeliosProgram(); + const program = await getHeliosProgram(parameters); return program.compile(optimize); }; From 9ca019c6a61a9dfec0b1880fc8817d55bb6f210e Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 29 Aug 2024 22:38:46 +0800 Subject: [PATCH 10/20] update contract and update tests --- package-lock.json | 1 + src/buy.ts | 100 ++++++++++++++++++++++++++++++++ src/commands/buy.ts | 42 ++++++++++++++ src/commands/list.ts | 17 ++---- src/config.ts | 14 +++++ src/contract/marketplace.helios | 17 ++---- src/datum.ts | 39 +++++++++---- src/list.ts | 15 +++-- src/tests/constants.ts | 25 ++++++-- src/tests/fixtures.ts | 3 - src/tests/tx.test.ts | 3 + src/types.ts | 7 ++- src/update.ts | 0 src/withdraw.ts | 0 14 files changed, 233 insertions(+), 50 deletions(-) create mode 100644 src/buy.ts create mode 100644 src/commands/buy.ts create mode 100644 src/update.ts create mode 100644 src/withdraw.ts diff --git a/package-lock.json b/package-lock.json index 723c168..88541a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1262,6 +1262,7 @@ "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", "dev": true, + "license": "MIT", "dependencies": { "nofilter": "^3.1.0" }, diff --git a/src/buy.ts b/src/buy.ts new file mode 100644 index 0000000..1209320 --- /dev/null +++ b/src/buy.ts @@ -0,0 +1,100 @@ +import { buildDatum, decodeDatum } from "./datum"; +import { getNetwork, mayFailAsync } from "./helpers"; +import { Parameters, Payout } from "./types"; +import { getUplcProgram } from "./utils"; + +import * as helios from "@koralabs/helios"; +import { AssetNameLabel } from "@koralabs/kora-labs-common"; +import { Err, Ok, Result } from "ts-res"; + +const buy = async ( + blockfrostApiKey: string, + address: helios.Address, + handlePolicyId: string, + handleName: string, + txHash: string, + txIndex: number, + parameters: Parameters +): Promise> => { + const network = getNetwork(blockfrostApiKey); + helios.config.set({ + IS_TESTNET: network != "mainnet", + AUTO_SET_VALIDITY_RANGE: true, + }); + + const api = new helios.BlockfrostV0(network, blockfrostApiKey); + const paramterResult = await mayFailAsync(() => + api.getParameters() + ).complete(); + if (!paramterResult.ok) + return Err(`Getting Network Parameter ${paramterResult.error}`); + const paramter = paramterResult.data; + + const handleUtxoResult = await mayFailAsync(() => + api.getUtxo(new helios.TxOutputId(`${txHash}#${txIndex}`)) + ).complete(); + if (!handleUtxoResult.ok) + return Err(`Getting Handle UTxO error: ${handleUtxoResult.error}`); + const handleUtxo = handleUtxoResult.data; + + const utxosResult = await mayFailAsync(() => + api.getUtxos(address) + ).complete(); + if (!utxosResult.ok) return Err(`Getting UTxOs error: ${utxosResult.error}`); + const utxos = utxosResult.data; + + const uplcProgramResult = await mayFailAsync(() => + getUplcProgram(parameters) + ).complete(); + if (!uplcProgramResult.ok) + return Err(`Getting Uplc Program error: ${uplcProgramResult.error}`); + const uplcProgram = uplcProgramResult.data; + + const handleRawDatum = handleUtxo.output.datum; + if (!handleRawDatum) return Err("Handle UTxO datum not found"); + const datumResult = await mayFailAsync(() => + decodeDatum(handleRawDatum) + ).complete(); + if (!datumResult.ok) + return Err(`Decoding Datum Cbor error: ${datumResult.error}`); + const datum = datumResult.data; + + // const handleAsset = new helios.Assets([ + // [ + // handlePolicyId, + // [ + // [ + // `${AssetNameLabel.LBL_222}${Buffer.from(handleName).toString("hex")}`, + // 1, + // ], + // ], + // ], + // ]); + + // const minFee = 5_000_000n; + // const minValue = new helios.Value(minFee, handleAsset); + // const [selected] = helios.CoinSelection.selectLargestFirst(utxos, minValue); + + // const tx = new helios.Tx(); + // tx.addInputs(selected); + + // const datum = await buildDatum(payouts, owner); + // const output = new helios.TxOutput( + // helios.Address.fromHash(uplcProgram.validatorHash, true), + // new helios.Value(0n, handleAsset), + // datum + // ); + // output.correctLovelace(paramter); + // tx.addOutput(output); + + // const txCompleteResult = await mayFailAsync(() => + // tx.finalize(paramter, address) + // ).complete(); + // if (!txCompleteResult.ok) + // return Err(`Finalizing Tx error: ${txCompleteResult.error}`); + + // return Ok(txCompleteResult.data); + return Ok(); +}; + +export { buy }; diff --git a/src/commands/buy.ts b/src/commands/buy.ts new file mode 100644 index 0000000..ade252c --- /dev/null +++ b/src/commands/buy.ts @@ -0,0 +1,42 @@ +import { buy } from "../buy"; +import program from "../cli"; +import { loadConfig } from "../config"; + +import * as helios from "@koralabs/helios"; + +const buyCommand = program + .command("buy") + .description("Buy Handle NFT on Marketplace") + .argument("
", "Address to perform buying") + .argument("", "Ada Handle Name to list on marketplace") + .argument("", "Transaction Hash of UTxO where handle is") + .argument("", "Transaction Index of UTxO where handle is") + .action( + async ( + bech32Address: string, + handleName: string, + txHash: string, + txIndex: string + ) => { + const configResult = loadConfig(); + if (!configResult.ok) return program.error(configResult.error); + const config = configResult.data; + + const address = helios.Address.fromBech32(bech32Address); + const txResult = await buy( + config.blockfrostApiKey, + address, + config.handlePolicyId, + handleName, + txHash, + parseInt(txIndex), + config.paramters + ); + + if (!txResult.ok) return program.error(txResult.error); + console.log("\nTransaction CBOR Hex, copy and paste to wallet\n"); + // console.log(txResult.data.toCborHex()); + } + ); + +export default buyCommand; diff --git a/src/commands/list.ts b/src/commands/list.ts index eaafb10..9a25c0b 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -8,15 +8,15 @@ import * as helios from "@koralabs/helios"; const buyCommand = program .command("list") .description("List Handle NFT on Marketplace") + .argument("
", "Address to perform listing") .argument("", "Ada Handle Name to list on marketplace") .argument("", "Price in ada") - .argument("
", "Address to perform listing") .argument("", "Address who create this NFT") .action( async ( + bech32Address: string, handleName: string, priceString: string, - bech32Address: string, creatorBech32Address: string ) => { const configResult = loadConfig(); @@ -38,20 +38,11 @@ const buyCommand = program }, ], address, - { - authorizers: [ - helios.PubKeyHash.fromHex( - "633a0061fcdb8aca5b86ef3a177fdcb0c178ccca3066b0be7197f3a1" - ), - ], - marketplaceAddress: helios.Address.fromBech32( - "addr_test1qp3n5qrplndc4jjmsmhn59mlmjcvz7xvegcxdv97wxtl8gthwj7fp7cy0tpvdzmd46u3c9tvjfxrpjc2faaqzm43wrpshmp3xw" - ), - } + config.paramters ); if (!txResult.ok) return program.error(txResult.error); - console.log("Transaction CBOR Hex, copy and paste to wallet\n"); + console.log("\nTransaction CBOR Hex, copy and paste to wallet\n"); console.log(txResult.data.toCborHex()); } ); diff --git a/src/config.ts b/src/config.ts index 7a4a7eb..6777f80 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,7 @@ import { get, getNetwork, loadEnv } from "./helpers"; +import { Parameters } from "./types"; +import * as helios from "@koralabs/helios"; import { Err, Ok } from "ts-res"; loadEnv(); @@ -13,10 +15,22 @@ const loadConfig = () => { const network = getNetwork(blockfrostApiKey.data); + const paramters: Parameters = { + authorizers: [ + helios.PubKeyHash.fromHex( + "633a0061fcdb8aca5b86ef3a177fdcb0c178ccca3066b0be7197f3a1" + ), + ], + marketplaceAddress: helios.Address.fromBech32( + "addr_test1qp3n5qrplndc4jjmsmhn59mlmjcvz7xvegcxdv97wxtl8gthwj7fp7cy0tpvdzmd46u3c9tvjfxrpjc2faaqzm43wrpshmp3xw" + ), + }; + return Ok({ blockfrostApiKey: blockfrostApiKey.data, handlePolicyId: handlePolicyId.data, network, + paramters, }); }; diff --git a/src/contract/marketplace.helios b/src/contract/marketplace.helios index c84bfc4..f032f1e 100644 --- a/src/contract/marketplace.helios +++ b/src/contract/marketplace.helios @@ -9,7 +9,7 @@ spending marketplace // one of the outputs. struct Payout { - address: Address + address: ByteArray amount_lovelace: Int } @@ -19,7 +19,7 @@ struct Datum { payouts: []Payout /// Flexible to allow discounts /// The key that listed the NFT - owner: PubKeyHash + owner: ByteArray } // ---------- Redeemer ---------- @@ -40,12 +40,7 @@ enum Redeemer { const AUTHORIZERS: []PubKeyHash = []PubKeyHash{ PubKeyHash::new(#) } -const MARKETPLACE_ADDRESS: Address = Address::new( - Credential::new_pubkey(PubKeyHash::new(#)), - Option[StakingCredential]::Some{ - StakingCredential::new_hash(StakingHash::new_stakekey(PubKeyHash::new(#))) - } -) +const MARKETPLACE_ADDRESS: Address = Address::from_bytes(#) // ---------- Functions ---------- @@ -72,7 +67,7 @@ func check_payouts_aux(outputs: []TxOutput, payouts: []Payout) -> Int { // The `Output` address must match // the address specified in the corresponding // payout from the datum. - assert(payout_address == first_output.address, "Output address must be matched with payout"); + assert(Address::from_bytes(payout_address) == first_output.address, "Output address must be matched with payout"); // Amount of lovelace in payout datum // must be greather than 0 assert(amount_lovelace > 0, "Payout amount must be greatner than 0"); @@ -118,7 +113,7 @@ func check_payouts(outputs: []TxOutput, payouts: []Payout, datum_tag: OutputDatu // The `Output` address must match // the address specified in the corresponding // payout from the datum. - assert(payout_address == first_output.address, "First output address must be matched with payout"); + assert(Address::from_bytes(payout_address) == first_output.address, "First output address must be matched with payout"); // Amount of lovelace in payout datum // must be greather than 0 @@ -219,7 +214,7 @@ func main(datum: Datum, redeemer: Redeemer, ctx: ScriptContext) -> Bool { // owner can cancel or update their listing // at any time. // is signed by owner - tx.is_signed_by(datum.owner) + tx.is_signed_by(PubKeyHash::new(datum.owner)) } } } \ No newline at end of file diff --git a/src/datum.ts b/src/datum.ts index 6955205..e0036fd 100644 --- a/src/datum.ts +++ b/src/datum.ts @@ -1,7 +1,8 @@ import { invariant } from "./helpers"; -import { Payout } from "./types"; +import { Datum, Payout } from "./types"; import * as helios from "@koralabs/helios"; +import { decodeCborToJson } from "@koralabs/kora-labs-common"; import { convertJsontoCbor } from "@koralabs/kora-labs-contract-testing"; const buildDatumTag = (outputRef: helios.TxOutputId): helios.Datum => { @@ -18,16 +19,7 @@ const buildDatum = async ( ): Promise => { invariant(!!owner.pubKeyHash, "Not valid owner"); const constrPayout = (payout: Payout) => [ - { - constructor_0: [ - { constructor_0: [`0x${payout.address.pubKeyHash?.hex || ""}`] }, - { - constructor_1: payout.address.stakingHash - ? [`0x${payout.address.pubKeyHash?.hex || ""}`] - : [], - }, - ], - }, + `0x${payout.address.hex}`, payout.amountLovelace, ]; @@ -36,4 +28,27 @@ const buildDatum = async ( return helios.Datum.inline(helios.UplcData.fromCbor(datumCbor)); }; -export { buildDatum, buildDatumTag }; +const decodeDatum = async (datum: helios.Datum): Promise => { + const decoded = await decodeCborToJson({ + cborString: datum.dump().inlineCbor, + forJson: false, + }); + console.log({ decoded }); + const owner = helios.Address.fromHex(decoded[1].slice(2)); + const payouts: Payout[] = await Promise.all( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + decoded[0].map(async (rawPayout: any) => { + const addressCbor = await convertJsontoCbor(rawPayout[0]); + const address = helios.Address.fromUplcData( + helios.UplcData.fromCbor(addressCbor) + ); + return { address, amountLovelace: rawPayout[1] } as Payout; + }) + ); + return { + payouts, + owner, + }; +}; + +export { buildDatum, buildDatumTag, decodeDatum }; diff --git a/src/list.ts b/src/list.ts index 9a86971..05abd02 100644 --- a/src/list.ts +++ b/src/list.ts @@ -1,5 +1,5 @@ import { buildDatum } from "./datum"; -import { getNetwork, mayFailAsync } from "./helpers"; +import { getNetwork, mayFail, mayFailAsync } from "./helpers"; import { Parameters, Payout } from "./types"; import { getUplcProgram } from "./utils"; @@ -7,7 +7,6 @@ import * as helios from "@koralabs/helios"; import { AssetNameLabel } from "@koralabs/kora-labs-common"; import { Err, Ok, Result } from "ts-res"; -/// payouts const list = async ( blockfrostApiKey: string, address: helios.Address, @@ -58,16 +57,22 @@ const list = async ( const minFee = 5_000_000n; const minValue = new helios.Value(minFee, handleAsset); - const [selected] = helios.CoinSelection.selectLargestFirst(utxos, minValue); + const selectResult = mayFail(() => + helios.CoinSelection.selectLargestFirst(utxos, minValue) + ); + if (!selectResult.ok) return Err(selectResult.error); + const [selected] = selectResult.data; const tx = new helios.Tx(); tx.addInputs(selected); - const datum = await buildDatum(payouts, owner); + const datum = await mayFailAsync(() => buildDatum(payouts, owner)).complete(); + if (!datum.ok) return Err(`Building Datum error: ${datum.error}`); + const output = new helios.TxOutput( helios.Address.fromHash(uplcProgram.validatorHash, true), new helios.Value(0n, handleAsset), - datum + datum.data ); output.correctLovelace(paramter); tx.addOutput(output); diff --git a/src/tests/constants.ts b/src/tests/constants.ts index a45eb86..a3faefb 100644 --- a/src/tests/constants.ts +++ b/src/tests/constants.ts @@ -26,29 +26,44 @@ const MARKETPLACE_ADDRESS = helios.Address.fromBech32( ); const PAYOUT_ADDRESSES = [ - helios.Address.fromHash( + helios.Address.fromHashes( helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789555551" + ), + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789666661" ) ), - helios.Address.fromHash( + helios.Address.fromHashes( helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789555552" + ), + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789666662" ) ), - helios.Address.fromHash( + helios.Address.fromHashes( helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789555553" + ), + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789666663" ) ), - helios.Address.fromHash( + helios.Address.fromHashes( helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789555554" + ), + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789666664" ) ), - helios.Address.fromHash( + helios.Address.fromHashes( helios.PubKeyHash.fromHex( "01234567890123456789012345678901234567890123456789555555" + ), + helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789666665" ) ), ]; diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts index 74762a2..b01b9e6 100644 --- a/src/tests/fixtures.ts +++ b/src/tests/fixtures.ts @@ -17,9 +17,6 @@ import { getNewFakeUtxoId, } from "@koralabs/kora-labs-contract-testing"; -/// setup -helios.config.set({ IS_TESTNET: true, AUTO_SET_VALIDITY_RANGE: true }); - class BuyFixture extends Fixture { handleName = "golddydev"; diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index d99f7ce..542076b 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -23,6 +23,9 @@ const runTests = async (file: string) => { const tester = new ContractTester(walletAddress, false); await tester.init(); + /// setup + helios.config.set({ IS_TESTNET: false, AUTO_SET_VALIDITY_RANGE: true }); + const contractFile = (await fs.readFile(file)).toString(); const program = helios.Program.new(contractFile); //new instance program.parameters.AUTHORIZERS = [AUTHORIZERS_PUB_KEY_HAHSES[0]]; diff --git a/src/types.ts b/src/types.ts index f26a46e..7b059aa 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,9 +5,14 @@ interface Payout { amountLovelace: number; } +interface Datum { + payouts: Payout[]; + owner: helios.Address; +} + interface Parameters { authorizers: helios.PubKeyHash[]; marketplaceAddress: helios.Address; } -export { Parameters, Payout }; +export { Datum, Parameters, Payout }; diff --git a/src/update.ts b/src/update.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/withdraw.ts b/src/withdraw.ts new file mode 100644 index 0000000..e69de29 From 1c78f23cfed175ff53fdf075eff4ad3fdf01189d Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Thu, 29 Aug 2024 23:55:14 +0800 Subject: [PATCH 11/20] update buy command --- src/buy.ts | 134 +++++++++++++++++++++++++++-------------- src/commands/buy.ts | 2 +- src/datum.ts | 54 ++++++++--------- src/list.ts | 7 ++- src/redeemer.ts | 13 ++++ src/tests/constants.ts | 3 + src/tests/fixtures.ts | 6 +- src/tests/tx.test.ts | 4 +- src/types.ts | 2 +- src/utils/common.ts | 4 +- 10 files changed, 145 insertions(+), 84 deletions(-) create mode 100644 src/redeemer.ts diff --git a/src/buy.ts b/src/buy.ts index 1209320..9d6269e 100644 --- a/src/buy.ts +++ b/src/buy.ts @@ -1,10 +1,11 @@ -import { buildDatum, decodeDatum } from "./datum"; -import { getNetwork, mayFailAsync } from "./helpers"; -import { Parameters, Payout } from "./types"; +import { buildDatumTag, decodeDatum } from "./datum"; +import { getNetwork, mayFail, mayFailAsync } from "./helpers"; +import { Parameters } from "./types"; import { getUplcProgram } from "./utils"; import * as helios from "@koralabs/helios"; import { AssetNameLabel } from "@koralabs/kora-labs-common"; +import { Buy } from "redeemer"; import { Err, Ok, Result } from "ts-res"; const buy = async ( @@ -15,20 +16,21 @@ const buy = async ( txHash: string, txIndex: number, parameters: Parameters -): Promise> => { +): Promise> => { const network = getNetwork(blockfrostApiKey); + const isTestnet = network != "mainnet"; helios.config.set({ - IS_TESTNET: network != "mainnet", + IS_TESTNET: isTestnet, AUTO_SET_VALIDITY_RANGE: true, }); const api = new helios.BlockfrostV0(network, blockfrostApiKey); - const paramterResult = await mayFailAsync(() => + const parameterResult = await mayFailAsync(() => api.getParameters() ).complete(); - if (!paramterResult.ok) - return Err(`Getting Network Parameter ${paramterResult.error}`); - const paramter = paramterResult.data; + if (!parameterResult.ok) + return Err(`Getting Network Parameter ${parameterResult.error}`); + const parameter = parameterResult.data; const handleUtxoResult = await mayFailAsync(() => api.getUtxo(new helios.TxOutputId(`${txHash}#${txIndex}`)) @@ -59,42 +61,84 @@ const buy = async ( return Err(`Decoding Datum Cbor error: ${datumResult.error}`); const datum = datumResult.data; - // const handleAsset = new helios.Assets([ - // [ - // handlePolicyId, - // [ - // [ - // `${AssetNameLabel.LBL_222}${Buffer.from(handleName).toString("hex")}`, - // 1, - // ], - // ], - // ], - // ]); - - // const minFee = 5_000_000n; - // const minValue = new helios.Value(minFee, handleAsset); - // const [selected] = helios.CoinSelection.selectLargestFirst(utxos, minValue); - - // const tx = new helios.Tx(); - // tx.addInputs(selected); - - // const datum = await buildDatum(payouts, owner); - // const output = new helios.TxOutput( - // helios.Address.fromHash(uplcProgram.validatorHash, true), - // new helios.Value(0n, handleAsset), - // datum - // ); - // output.correctLovelace(paramter); - // tx.addOutput(output); - - // const txCompleteResult = await mayFailAsync(() => - // tx.finalize(paramter, address) - // ).complete(); - // if (!txCompleteResult.ok) - // return Err(`Finalizing Tx error: ${txCompleteResult.error}`); - - // return Ok(txCompleteResult.data); - return Ok(); + /// build tx + + const tx = new helios.Tx(); + + /// take fund to pay payouts + const minFee = 5_000_000n; + const totalPayoutsLovelace = datum.payouts.reduce( + (acc, cur) => acc + cur.amountLovelace, + 0n + ); + const marketplaceFee = (totalPayoutsLovelace * 50n) / 49n / 50n; + const requiredValue = new helios.Value( + minFee + totalPayoutsLovelace + marketplaceFee + ); + const [selected] = helios.CoinSelection.selectLargestFirst( + utxos, + requiredValue + ); + tx.addInputs(selected); + + /// redeemer + const redeemer = mayFail(() => Buy(0)); + if (!redeemer.ok) return Err(`Making Redeemer error: ${redeemer.error}`); + + /// collect handle NFT to buy + tx.addInput(handleUtxo, redeemer.data); + tx.attachScript(uplcProgram); + + /// build datum tag + const datumTag = mayFail(() => buildDatumTag(handleUtxo.outputId)); + if (!datumTag.ok) return Err(`Building Datum Tag error: ${datumTag.error}`); + + /// add marketplace fee + const marketplaceFeeOutput = new helios.TxOutput( + parameters.marketplaceAddress, + new helios.Value(marketplaceFee), + datumTag.data + ); + marketplaceFeeOutput.correctLovelace(parameter); + tx.addOutput(marketplaceFeeOutput); + + /// add payout outputs + const payoutOutputs = datum.payouts.map( + (payout) => + new helios.TxOutput( + payout.address, + new helios.Value(payout.amountLovelace) + ) + ); + payoutOutputs.forEach((output) => output.correctLovelace(parameter)); + tx.addOutputs(payoutOutputs); + + /// add handle buy output + const handleAsset = new helios.Assets([ + [ + handlePolicyId, + [ + [ + `${AssetNameLabel.LBL_222}${Buffer.from(handleName).toString("hex")}`, + 1, + ], + ], + ], + ]); + const handleBuyOutput = new helios.TxOutput( + address, + new helios.Value(0, handleAsset) + ); + handleBuyOutput.correctLovelace(parameter); + tx.addOutput(handleBuyOutput); + + const txCompleteResult = await mayFailAsync(() => + tx.finalize(parameter, address) + ).complete(); + if (!txCompleteResult.ok) + return Err(`Finalizing Tx error: ${txCompleteResult.error}`); + + return Ok(txCompleteResult.data); }; export { buy }; diff --git a/src/commands/buy.ts b/src/commands/buy.ts index ade252c..1bf0b24 100644 --- a/src/commands/buy.ts +++ b/src/commands/buy.ts @@ -35,7 +35,7 @@ const buyCommand = program if (!txResult.ok) return program.error(txResult.error); console.log("\nTransaction CBOR Hex, copy and paste to wallet\n"); - // console.log(txResult.data.toCborHex()); + console.log(txResult.data.toCborHex()); } ); diff --git a/src/datum.ts b/src/datum.ts index e0036fd..57d47fb 100644 --- a/src/datum.ts +++ b/src/datum.ts @@ -3,7 +3,6 @@ import { Datum, Payout } from "./types"; import * as helios from "@koralabs/helios"; import { decodeCborToJson } from "@koralabs/kora-labs-common"; -import { convertJsontoCbor } from "@koralabs/kora-labs-contract-testing"; const buildDatumTag = (outputRef: helios.TxOutputId): helios.Datum => { const cbor = outputRef._toUplcData().toCborHex(); @@ -13,41 +12,42 @@ const buildDatumTag = (outputRef: helios.TxOutputId): helios.Datum => { ); }; -const buildDatum = async ( - payouts: Payout[], - owner: helios.Address -): Promise => { +const buildDatum = (payouts: Payout[], owner: helios.Address): helios.Datum => { invariant(!!owner.pubKeyHash, "Not valid owner"); - const constrPayout = (payout: Payout) => [ - `0x${payout.address.hex}`, - payout.amountLovelace, - ]; - - const datum = [payouts.map(constrPayout), `0x${owner.hex}`]; - const datumCbor = await convertJsontoCbor(datum); - return helios.Datum.inline(helios.UplcData.fromCbor(datumCbor)); + const data = new helios.ListData([ + new helios.ListData( + payouts.map( + (payout) => + new helios.ListData([ + new helios.ByteArrayData(payout.address.bytes), + new helios.IntData(payout.amountLovelace), + ]) + ) + ), + new helios.ByteArrayData(owner.bytes), + ]); + return helios.Datum.inline(data); }; const decodeDatum = async (datum: helios.Datum): Promise => { + const datumDataCborHex = datum.data?.toCborHex(); + invariant(datumDataCborHex, "Datum is invalid"); + const decoded = await decodeCborToJson({ - cborString: datum.dump().inlineCbor, - forJson: false, + cborString: datumDataCborHex, }); - console.log({ decoded }); + const owner = helios.Address.fromHex(decoded[1].slice(2)); - const payouts: Payout[] = await Promise.all( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - decoded[0].map(async (rawPayout: any) => { - const addressCbor = await convertJsontoCbor(rawPayout[0]); - const address = helios.Address.fromUplcData( - helios.UplcData.fromCbor(addressCbor) - ); - return { address, amountLovelace: rawPayout[1] } as Payout; - }) - ); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const payouts: Payout[] = decoded[0].map((rawPayout: any) => { + const address = helios.Address.fromHex(rawPayout[0].slice(2)); + const amountLovelace = BigInt(rawPayout[1]) as bigint; + return { address, amountLovelace } as Payout; + }); + return { - payouts, owner, + payouts, }; }; diff --git a/src/list.ts b/src/list.ts index 05abd02..d055444 100644 --- a/src/list.ts +++ b/src/list.ts @@ -17,8 +17,9 @@ const list = async ( parameters: Parameters ): Promise> => { const network = getNetwork(blockfrostApiKey); + const isTestnet = network != "mainnet"; helios.config.set({ - IS_TESTNET: network != "mainnet", + IS_TESTNET: isTestnet, AUTO_SET_VALIDITY_RANGE: true, }); @@ -66,11 +67,11 @@ const list = async ( const tx = new helios.Tx(); tx.addInputs(selected); - const datum = await mayFailAsync(() => buildDatum(payouts, owner)).complete(); + const datum = mayFail(() => buildDatum(payouts, owner)); if (!datum.ok) return Err(`Building Datum error: ${datum.error}`); const output = new helios.TxOutput( - helios.Address.fromHash(uplcProgram.validatorHash, true), + helios.Address.fromHash(uplcProgram.validatorHash), new helios.Value(0n, handleAsset), datum.data ); diff --git a/src/redeemer.ts b/src/redeemer.ts new file mode 100644 index 0000000..aac42da --- /dev/null +++ b/src/redeemer.ts @@ -0,0 +1,13 @@ +import * as helios from "@koralabs/helios"; + +const Buy = (payoutOutputsOffset: number): helios.UplcData => { + return new helios.ConstrData(0, [ + new helios.IntData(BigInt(payoutOutputsOffset)), + ]); +}; + +const WithdrawOrUpdate = (): helios.UplcData => { + return new helios.ConstrData(1, []); +}; + +export { Buy, WithdrawOrUpdate }; diff --git a/src/tests/constants.ts b/src/tests/constants.ts index a3faefb..a56664d 100644 --- a/src/tests/constants.ts +++ b/src/tests/constants.ts @@ -1,5 +1,8 @@ import * as helios from "@koralabs/helios"; +/// setup +helios.config.set({ IS_TESTNET: true, AUTO_SET_VALIDITY_RANGE: true }); + const HANDLE_POLICY_ID = "f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a"; const SPAM_TOKEN_POLICY_ID = diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts index b01b9e6..9675383 100644 --- a/src/tests/fixtures.ts +++ b/src/tests/fixtures.ts @@ -41,7 +41,7 @@ class BuyFixture extends Fixture { }; this.buyRedeemerCbor = await convertJsontoCbor(this.buyRedeemer); this.redeemer = helios.UplcData.fromCbor(this.buyRedeemerCbor); - const datum = await buildDatum(this.payouts, this.owner); + const datum = buildDatum(this.payouts, this.owner); this.inputs = [ new helios.TxInput( // money & collateral new helios.TxOutputId(getNewFakeUtxoId()), @@ -122,7 +122,7 @@ class WithdrawOrUpdateFixture extends Fixture { this.withdrawOrUpdateRedeemer ); this.redeemer = helios.UplcData.fromCbor(this.withdrawOrUpdateRedeemerCbor); - const datum = await buildDatum(this.payouts, this.owner); + const datum = buildDatum(this.payouts, this.owner); const nftValue = new helios.Value(minLovelace, [ [ @@ -152,7 +152,7 @@ class WithdrawOrUpdateFixture extends Fixture { ]; const newDatum = this.newPayouts - ? await buildDatum(this.newPayouts, this.owner) + ? buildDatum(this.newPayouts, this.owner) : null; this.outputs = [ new helios.TxOutput(this.nftOutputAddress, nftValue, newDatum), diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index 542076b..6d60a35 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -21,10 +21,10 @@ import fs from "fs/promises"; const runTests = async (file: string) => { const walletAddress = await getAddressAtDerivation(0); const tester = new ContractTester(walletAddress, false); - await tester.init(); + await tester.init("Buy", "can buy nft without authorizer"); /// setup - helios.config.set({ IS_TESTNET: false, AUTO_SET_VALIDITY_RANGE: true }); + helios.config.set({ IS_TESTNET: true, AUTO_SET_VALIDITY_RANGE: true }); const contractFile = (await fs.readFile(file)).toString(); const program = helios.Program.new(contractFile); //new instance diff --git a/src/types.ts b/src/types.ts index 7b059aa..b4f6224 100644 --- a/src/types.ts +++ b/src/types.ts @@ -2,7 +2,7 @@ import * as helios from "@koralabs/helios"; interface Payout { address: helios.Address; - amountLovelace: number; + amountLovelace: bigint; } interface Datum { diff --git a/src/utils/common.ts b/src/utils/common.ts index ab335d3..9b0fca6 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -1,6 +1,6 @@ import Decimal from "decimal.js"; -const adaToLovelace = (ada: number): number => - new Decimal(ada).mul(Math.pow(10, 6)).floor().toNumber(); +const adaToLovelace = (ada: number): bigint => + BigInt(new Decimal(ada).mul(Math.pow(10, 6)).floor().toString()); export { adaToLovelace }; From 9919acbbe5a64887b17b95aa245ece305052163e Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Fri, 30 Aug 2024 00:08:49 +0800 Subject: [PATCH 12/20] update redeemer functions --- src/buy.ts | 1 - src/tests/fixtures.ts | 18 +++--------------- src/tests/tx.test.ts | 2 +- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/buy.ts b/src/buy.ts index 9d6269e..a3d6bc6 100644 --- a/src/buy.ts +++ b/src/buy.ts @@ -62,7 +62,6 @@ const buy = async ( const datum = datumResult.data; /// build tx - const tx = new helios.Tx(); /// take fund to pay payouts diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts index 9675383..4a80715 100644 --- a/src/tests/fixtures.ts +++ b/src/tests/fixtures.ts @@ -1,4 +1,5 @@ import { buildDatum } from "../datum"; +import { Buy, WithdrawOrUpdate } from "../redeemer"; import { Payout } from "../types"; import { @@ -11,7 +12,6 @@ import { import * as helios from "@koralabs/helios"; import { AssetNameLabel } from "@koralabs/kora-labs-common"; import { - convertJsontoCbor, Fixture, getAddressAtDerivation, getNewFakeUtxoId, @@ -21,8 +21,6 @@ class BuyFixture extends Fixture { handleName = "golddydev"; payoutOutputsOffset = 0; - buyRedeemer = { constructor_0: [0] }; - buyRedeemerCbor: string = ""; spendingUtxoId: string = ""; payouts: Payout[] = []; @@ -36,11 +34,7 @@ class BuyFixture extends Fixture { } async initialize() { - this.buyRedeemer = { - constructor_0: [this.payoutOutputsOffset], - }; - this.buyRedeemerCbor = await convertJsontoCbor(this.buyRedeemer); - this.redeemer = helios.UplcData.fromCbor(this.buyRedeemerCbor); + this.redeemer = Buy(this.payoutOutputsOffset); const datum = buildDatum(this.payouts, this.owner); this.inputs = [ new helios.TxInput( // money & collateral @@ -102,9 +96,6 @@ class BuyFixture extends Fixture { class WithdrawOrUpdateFixture extends Fixture { handleName = "golddydev"; - withdrawOrUpdateRedeemer = { constructor_1: [] }; - withdrawOrUpdateRedeemerCbor: string = ""; - payouts: Payout[] = []; newPayouts: Payout[] | undefined = undefined; owner: helios.Address = ONWER_ADDRESS; @@ -118,10 +109,7 @@ class WithdrawOrUpdateFixture extends Fixture { } async initialize() { - this.withdrawOrUpdateRedeemerCbor = await convertJsontoCbor( - this.withdrawOrUpdateRedeemer - ); - this.redeemer = helios.UplcData.fromCbor(this.withdrawOrUpdateRedeemerCbor); + this.redeemer = WithdrawOrUpdate(); const datum = buildDatum(this.payouts, this.owner); const nftValue = new helios.Value(minLovelace, [ diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index 6d60a35..c9b1d28 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -21,7 +21,7 @@ import fs from "fs/promises"; const runTests = async (file: string) => { const walletAddress = await getAddressAtDerivation(0); const tester = new ContractTester(walletAddress, false); - await tester.init("Buy", "can buy nft without authorizer"); + await tester.init(); /// setup helios.config.set({ IS_TESTNET: true, AUTO_SET_VALIDITY_RANGE: true }); From 0875f8e059b882f74a15d331ca8cdba6dc661ee3 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Fri, 30 Aug 2024 20:46:47 +0800 Subject: [PATCH 13/20] add updated network params --- package-lock.json | 18 +- package.json | 2 +- src/buy.ts | 27 +- src/config.ts | 8 + src/utils/common.ts | 20 +- src/utils/params/preprod.json | 656 ++++++++++++++++++++++++++++++++++ src/utils/params/preview.json | 656 ++++++++++++++++++++++++++++++++++ tsconfig.json | 3 +- 8 files changed, 1370 insertions(+), 20 deletions(-) create mode 100644 src/utils/params/preprod.json create mode 100644 src/utils/params/preview.json diff --git a/package-lock.json b/package-lock.json index 88541a9..0c9f626 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "marketplace": "bin/marketplace" }, "devDependencies": { - "@koralabs/helios": "0.16.8-1", + "@koralabs/helios": "0.16.8-2", "@koralabs/kora-labs-common": "^4.0.7", "@koralabs/kora-labs-contract-testing": "0.0.7", "@types/node": "^22.1.0", @@ -568,10 +568,11 @@ "dev": true }, "node_modules/@koralabs/helios": { - "version": "0.16.8-1", - "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-1.tgz", - "integrity": "sha512-/pbL4lUP7CBELSxfMuZUhJ5rZ5B3T+kwaQ4joI9y+SDMFyfqySARcgv5+uTT1nnTd/gCgM3QzMUZBOL8BMM3AA==", - "dev": true + "version": "0.16.8-2", + "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-2.tgz", + "integrity": "sha512-qAKs3PgZye+vjWM9bZVgqVVJgA3CruVeDoFn6xAoH3us7seofSei3N1364bKTsYHTz+hEtMRcYU4GEtceaJs1A==", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@koralabs/kora-labs-common": { "version": "4.3.7", @@ -597,6 +598,13 @@ "bip39": "^3.1.0" } }, + "node_modules/@koralabs/kora-labs-contract-testing/node_modules/@koralabs/helios": { + "version": "0.16.8-1", + "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-1.tgz", + "integrity": "sha512-/pbL4lUP7CBELSxfMuZUhJ5rZ5B3T+kwaQ4joI9y+SDMFyfqySARcgv5+uTT1nnTd/gCgM3QzMUZBOL8BMM3AA==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/@noble/hashes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", diff --git a/package.json b/package.json index ddf8a6c..6b76ddb 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "author": "Kora Labs ", "license": "ISC", "devDependencies": { - "@koralabs/helios": "0.16.8-1", + "@koralabs/helios": "0.16.8-2", "@koralabs/kora-labs-common": "^4.0.7", "@koralabs/kora-labs-contract-testing": "0.0.7", "@types/node": "^22.1.0", diff --git a/src/buy.ts b/src/buy.ts index a3d6bc6..498efcc 100644 --- a/src/buy.ts +++ b/src/buy.ts @@ -1,7 +1,7 @@ import { buildDatumTag, decodeDatum } from "./datum"; import { getNetwork, mayFail, mayFailAsync } from "./helpers"; import { Parameters } from "./types"; -import { getUplcProgram } from "./utils"; +import { fetchNetworkParameters, getUplcProgram } from "./utils"; import * as helios from "@koralabs/helios"; import { AssetNameLabel } from "@koralabs/kora-labs-common"; @@ -25,12 +25,6 @@ const buy = async ( }); const api = new helios.BlockfrostV0(network, blockfrostApiKey); - const parameterResult = await mayFailAsync(() => - api.getParameters() - ).complete(); - if (!parameterResult.ok) - return Err(`Getting Network Parameter ${parameterResult.error}`); - const parameter = parameterResult.data; const handleUtxoResult = await mayFailAsync(() => api.getUtxo(new helios.TxOutputId(`${txHash}#${txIndex}`)) @@ -61,6 +55,16 @@ const buy = async ( return Err(`Decoding Datum Cbor error: ${datumResult.error}`); const datum = datumResult.data; + /// fetch protocol parameter + const networkParamsResult = await mayFailAsync(() => + fetchNetworkParameters(network) + ).complete(); + if (!networkParamsResult.ok) + return Err( + `Fetching Network Parameter error: ${networkParamsResult.error}` + ); + const networkParams = networkParamsResult.data; + /// build tx const tx = new helios.Tx(); @@ -98,7 +102,7 @@ const buy = async ( new helios.Value(marketplaceFee), datumTag.data ); - marketplaceFeeOutput.correctLovelace(parameter); + marketplaceFeeOutput.correctLovelace(networkParams); tx.addOutput(marketplaceFeeOutput); /// add payout outputs @@ -109,7 +113,7 @@ const buy = async ( new helios.Value(payout.amountLovelace) ) ); - payoutOutputs.forEach((output) => output.correctLovelace(parameter)); + payoutOutputs.forEach((output) => output.correctLovelace(networkParams)); tx.addOutputs(payoutOutputs); /// add handle buy output @@ -128,15 +132,14 @@ const buy = async ( address, new helios.Value(0, handleAsset) ); - handleBuyOutput.correctLovelace(parameter); + handleBuyOutput.correctLovelace(networkParams); tx.addOutput(handleBuyOutput); const txCompleteResult = await mayFailAsync(() => - tx.finalize(parameter, address) + tx.finalize(networkParams, address) ).complete(); if (!txCompleteResult.ok) return Err(`Finalizing Tx error: ${txCompleteResult.error}`); - return Ok(txCompleteResult.data); }; diff --git a/src/config.ts b/src/config.ts index 6777f80..4cc8986 100644 --- a/src/config.ts +++ b/src/config.ts @@ -24,6 +24,14 @@ const loadConfig = () => { marketplaceAddress: helios.Address.fromBech32( "addr_test1qp3n5qrplndc4jjmsmhn59mlmjcvz7xvegcxdv97wxtl8gthwj7fp7cy0tpvdzmd46u3c9tvjfxrpjc2faaqzm43wrpshmp3xw" ), + // authorizers: [ + // helios.PubKeyHash.fromHex( + // "ea018bbdec1b9963f3cf37a7d7d80c0fd16d29722d0453fcfa9549ae" + // ), + // ], + // marketplaceAddress: helios.Address.fromBech32( + // "addr_test1qr4qrzaaasdejclneum6047cps8azmffwgksg5lul225nth58fldnc83x5jnfxg37rmvmdv2rn3emrmh9ptry9vzvjxqn5c55p" + // ), }; return Ok({ diff --git a/src/utils/common.ts b/src/utils/common.ts index 9b0fca6..4a63c47 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -1,6 +1,24 @@ +import preprodParams from "./params/preprod.json"; +import previewParams from "./params/preview.json"; + +import * as helios from "@koralabs/helios"; +import { Network } from "@koralabs/kora-labs-common"; import Decimal from "decimal.js"; const adaToLovelace = (ada: number): bigint => BigInt(new Decimal(ada).mul(Math.pow(10, 6)).floor().toString()); -export { adaToLovelace }; +const fetchNetworkParameters = async ( + network: Network +): Promise => { + if (network == "preview") return new helios.NetworkParams(previewParams); + if (network == "preprod") return new helios.NetworkParams(preprodParams); + const networkParams = new helios.NetworkParams( + await fetch( + `https://d1t0d7c2nekuk0.cloudfront.net/${network.toLowerCase()}.json` + ).then((response) => response.json()) + ); + return networkParams; +}; + +export { adaToLovelace, fetchNetworkParameters }; diff --git a/src/utils/params/preprod.json b/src/utils/params/preprod.json new file mode 100644 index 0000000..232c019 --- /dev/null +++ b/src/utils/params/preprod.json @@ -0,0 +1,656 @@ +{ + "shelleyGenesis": { + "activeSlotsCoeff": 0.05, + "epochLength": 432000, + "genDelegs": { + "637f2e950b0fd8f8e3e811c5fbeb19e411e7a2bf37272b84b29c1a0b": { + "delegate": "aae9293510344ddd636364c2673e34e03e79e3eefa8dbaa70e326f7d", + "vrf": "227116365af2ed943f1a8b5e6557bfaa34996f1578eec667a5e2b361c51e4ce7" + }, + "8a4b77c4f534f8b8cc6f269e5ebb7ba77fa63a476e50e05e66d7051c": { + "delegate": "d15422b2e8b60e500a82a8f4ceaa98b04e55a0171d1125f6c58f8758", + "vrf": "0ada6c25d62db5e1e35d3df727635afa943b9e8a123ab83785e2281605b09ce2" + }, + "b00470cd193d67aac47c373602fccd4195aad3002c169b5570de1126": { + "delegate": "b3b539e9e7ed1b32fbf778bf2ebf0a6b9f980eac90ac86623d11881a", + "vrf": "0ff0ce9b820376e51c03b27877cd08f8ba40318f1a9f85a3db0b60dd03f71a7a" + }, + "b260ffdb6eba541fcf18601923457307647dce807851b9d19da133ab": { + "delegate": "7c64eb868b4ef566391a321c85323f41d2b95480d7ce56ad2abcb022", + "vrf": "7fb22abd39d550c9a022ec8104648a26240a9ff9c88b8b89a6e20d393c03098e" + }, + "ced1599fd821a39593e00592e5292bdc1437ae0f7af388ef5257344a": { + "delegate": "de7ca985023cf892f4de7f5f1d0a7181668884752d9ebb9e96c95059", + "vrf": "c301b7fc4d1b57fb60841bcec5e3d2db89602e5285801e522fce3790987b1124" + }, + "dd2a7d71a05bed11db61555ba4c658cb1ce06c8024193d064f2a66ae": { + "delegate": "1e113c218899ee7807f4028071d0e108fc790dade9fd1a0d0b0701ee", + "vrf": "faf2702aa4893c877c622ab22dfeaf1d0c8aab98b837fe2bf667314f0d043822" + }, + "f3b9e74f7d0f24d2314ea5dfbca94b65b2059d1ff94d97436b82d5b4": { + "delegate": "fd637b08cc379ef7b99c83b416458fcda8a01a606041779331008fb9", + "vrf": "37f2ea7c843a688159ddc2c38a2f997ab465150164a9136dca69564714b73268" + } + }, + "initialFunds": {}, + "maxKESEvolutions": 120, + "maxLovelaceSupply": 45000000000000000, + "networkId": "Testnet", + "networkMagic": 1, + "protocolParams": { + "a0": 0.1, + "decentralisationParam": 1, + "eMax": 18, + "extraEntropy": { + "tag": "NeutralNonce" + }, + "keyDeposit": 400000, + "maxBlockBodySize": 65536, + "maxBlockHeaderSize": 1100, + "maxTxSize": 16384, + "minFeeA": 44, + "minFeeB": 155381, + "minPoolCost": 0, + "minUTxOValue": 0, + "nOpt": 50, + "poolDeposit": 500000000, + "protocolVersion": { + "major": 2, + "minor": 0 + }, + "rho": 0.00178650067, + "tau": 0.1 + }, + "securityParam": 2160, + "slotLength": 1, + "slotsPerKESPeriod": 86400, + "staking": { + "pools": {}, + "stake": {} + }, + "systemStart": "2022-06-01T00:00:00Z", + "updateQuorum": 5 + }, + "alonzoGenesis": { + "lovelacePerUTxOWord": 34482, + "executionPrices": { + "prSteps": { + "numerator": 721, + "denominator": 10000000 + }, + "prMem": { + "numerator": 577, + "denominator": 10000 + } + }, + "maxTxExUnits": { + "exUnitsMem": 10000000, + "exUnitsSteps": 10000000000 + }, + "maxBlockExUnits": { + "exUnitsMem": 50000000, + "exUnitsSteps": 40000000000 + }, + "maxValueSize": 5000, + "collateralPercentage": 150, + "maxCollateralInputs": 3, + "costModels": { + "PlutusV1": { + "sha2_256-memory-arguments": 4, + "equalsString-cpu-arguments-constant": 1000, + "cekDelayCost-exBudgetMemory": 100, + "lessThanEqualsByteString-cpu-arguments-intercept": 103599, + "divideInteger-memory-arguments-minimum": 1, + "appendByteString-cpu-arguments-slope": 621, + "blake2b-cpu-arguments-slope": 29175, + "iData-cpu-arguments": 150000, + "encodeUtf8-cpu-arguments-slope": 1000, + "unBData-cpu-arguments": 150000, + "multiplyInteger-cpu-arguments-intercept": 61516, + "cekConstCost-exBudgetMemory": 100, + "nullList-cpu-arguments": 150000, + "equalsString-cpu-arguments-intercept": 150000, + "trace-cpu-arguments": 150000, + "mkNilData-memory-arguments": 32, + "lengthOfByteString-cpu-arguments": 150000, + "cekBuiltinCost-exBudgetCPU": 29773, + "bData-cpu-arguments": 150000, + "subtractInteger-cpu-arguments-slope": 0, + "unIData-cpu-arguments": 150000, + "consByteString-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-slope": 1, + "divideInteger-cpu-arguments-model-arguments-slope": 118, + "listData-cpu-arguments": 150000, + "headList-cpu-arguments": 150000, + "chooseData-memory-arguments": 32, + "equalsInteger-cpu-arguments-intercept": 136542, + "sha3_256-cpu-arguments-slope": 82363, + "sliceByteString-cpu-arguments-slope": 5000, + "unMapData-cpu-arguments": 150000, + "lessThanInteger-cpu-arguments-intercept": 179690, + "mkCons-cpu-arguments": 150000, + "appendString-memory-arguments-intercept": 0, + "modInteger-cpu-arguments-model-arguments-slope": 118, + "ifThenElse-cpu-arguments": 1, + "mkNilPairData-cpu-arguments": 150000, + "lessThanEqualsInteger-cpu-arguments-intercept": 145276, + "addInteger-memory-arguments-slope": 1, + "chooseList-memory-arguments": 32, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 150000, + "equalsData-memory-arguments": 1, + "subtractInteger-memory-arguments-slope": 1, + "appendByteString-memory-arguments-intercept": 0, + "lengthOfByteString-memory-arguments": 4, + "headList-memory-arguments": 32, + "listData-memory-arguments": 32, + "consByteString-cpu-arguments-intercept": 150000, + "unIData-memory-arguments": 32, + "remainderInteger-memory-arguments-minimum": 1, + "bData-memory-arguments": 32, + "lessThanByteString-cpu-arguments-slope": 248, + "encodeUtf8-memory-arguments-intercept": 0, + "cekStartupCost-exBudgetCPU": 100, + "multiplyInteger-memory-arguments-intercept": 0, + "unListData-memory-arguments": 32, + "remainderInteger-cpu-arguments-model-arguments-slope": 118, + "cekVarCost-exBudgetCPU": 29773, + "remainderInteger-memory-arguments-slope": 1, + "cekForceCost-exBudgetCPU": 29773, + "sha2_256-cpu-arguments-slope": 29175, + "equalsInteger-memory-arguments": 1, + "indexByteString-memory-arguments": 1, + "addInteger-memory-arguments-intercept": 1, + "chooseUnit-cpu-arguments": 150000, + "sndPair-cpu-arguments": 150000, + "cekLamCost-exBudgetCPU": 29773, + "fstPair-cpu-arguments": 150000, + "quotientInteger-memory-arguments-minimum": 1, + "decodeUtf8-cpu-arguments-slope": 1000, + "lessThanInteger-memory-arguments": 1, + "lessThanEqualsInteger-cpu-arguments-slope": 1366, + "fstPair-memory-arguments": 32, + "modInteger-memory-arguments-intercept": 0, + "unConstrData-cpu-arguments": 150000, + "lessThanEqualsInteger-memory-arguments": 1, + "chooseUnit-memory-arguments": 32, + "sndPair-memory-arguments": 32, + "addInteger-cpu-arguments-intercept": 197209, + "decodeUtf8-memory-arguments-slope": 8, + "equalsData-cpu-arguments-intercept": 150000, + "mapData-cpu-arguments": 150000, + "mkPairData-cpu-arguments": 150000, + "quotientInteger-cpu-arguments-constant": 148000, + "consByteString-memory-arguments-slope": 1, + "cekVarCost-exBudgetMemory": 100, + "indexByteString-cpu-arguments": 150000, + "unListData-cpu-arguments": 150000, + "equalsInteger-cpu-arguments-slope": 1326, + "cekStartupCost-exBudgetMemory": 100, + "subtractInteger-cpu-arguments-intercept": 197209, + "divideInteger-cpu-arguments-model-arguments-intercept": 425507, + "divideInteger-memory-arguments-intercept": 0, + "cekForceCost-exBudgetMemory": 100, + "blake2b-cpu-arguments-intercept": 2477736, + "remainderInteger-cpu-arguments-constant": 148000, + "tailList-cpu-arguments": 150000, + "encodeUtf8-cpu-arguments-intercept": 150000, + "equalsString-cpu-arguments-slope": 1000, + "lessThanByteString-memory-arguments": 1, + "multiplyInteger-cpu-arguments-slope": 11218, + "appendByteString-cpu-arguments-intercept": 396231, + "lessThanEqualsByteString-cpu-arguments-slope": 248, + "modInteger-memory-arguments-slope": 1, + "addInteger-cpu-arguments-slope": 0, + "equalsData-cpu-arguments-slope": 10000, + "decodeUtf8-memory-arguments-intercept": 0, + "chooseList-cpu-arguments": 150000, + "constrData-cpu-arguments": 150000, + "equalsByteString-memory-arguments": 1, + "cekApplyCost-exBudgetCPU": 29773, + "quotientInteger-memory-arguments-slope": 1, + "verifySignature-cpu-arguments-intercept": 3345831, + "unMapData-memory-arguments": 32, + "mkCons-memory-arguments": 32, + "sliceByteString-memory-arguments-slope": 1, + "sha3_256-memory-arguments": 4, + "ifThenElse-memory-arguments": 1, + "mkNilPairData-memory-arguments": 32, + "equalsByteString-cpu-arguments-slope": 247, + "appendString-cpu-arguments-intercept": 150000, + "quotientInteger-cpu-arguments-model-arguments-slope": 118, + "cekApplyCost-exBudgetMemory": 100, + "equalsString-memory-arguments": 1, + "multiplyInteger-memory-arguments-slope": 1, + "cekBuiltinCost-exBudgetMemory": 100, + "remainderInteger-memory-arguments-intercept": 0, + "sha2_256-cpu-arguments-intercept": 2477736, + "remainderInteger-cpu-arguments-model-arguments-intercept": 425507, + "lessThanEqualsByteString-memory-arguments": 1, + "tailList-memory-arguments": 32, + "mkNilData-cpu-arguments": 150000, + "chooseData-cpu-arguments": 150000, + "unBData-memory-arguments": 32, + "blake2b-memory-arguments": 4, + "iData-memory-arguments": 32, + "nullList-memory-arguments": 32, + "cekDelayCost-exBudgetCPU": 29773, + "subtractInteger-memory-arguments-intercept": 1, + "lessThanByteString-cpu-arguments-intercept": 103599, + "consByteString-cpu-arguments-slope": 1000, + "appendByteString-memory-arguments-slope": 1, + "trace-memory-arguments": 32, + "divideInteger-cpu-arguments-constant": 148000, + "cekConstCost-exBudgetCPU": 29773, + "encodeUtf8-memory-arguments-slope": 8, + "quotientInteger-cpu-arguments-model-arguments-intercept": 425507, + "mapData-memory-arguments": 32, + "appendString-cpu-arguments-slope": 1000, + "modInteger-cpu-arguments-constant": 148000, + "verifySignature-cpu-arguments-slope": 1, + "unConstrData-memory-arguments": 32, + "quotientInteger-memory-arguments-intercept": 0, + "equalsByteString-cpu-arguments-constant": 150000, + "sliceByteString-memory-arguments-intercept": 0, + "mkPairData-memory-arguments": 32, + "equalsByteString-cpu-arguments-intercept": 112536, + "appendString-memory-arguments-slope": 1, + "lessThanInteger-cpu-arguments-slope": 497, + "modInteger-cpu-arguments-model-arguments-intercept": 425507, + "modInteger-memory-arguments-minimum": 1, + "sha3_256-cpu-arguments-intercept": 0, + "verifySignature-memory-arguments": 1, + "cekLamCost-exBudgetMemory": 100, + "sliceByteString-cpu-arguments-intercept": 150000 + } + } + }, + "latestParams": { + "collateralPercentage": 150, + "costModels": { + "PlutusScriptV1": { + "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 + }, + "PlutusScriptV2": { + "addInteger-cpu-arguments-intercept": 100788, + "addInteger-cpu-arguments-slope": 420, + "addInteger-memory-arguments-intercept": 1, + "addInteger-memory-arguments-slope": 1, + "appendByteString-cpu-arguments-intercept": 1000, + "appendByteString-cpu-arguments-slope": 173, + "appendByteString-memory-arguments-intercept": 0, + "appendByteString-memory-arguments-slope": 1, + "appendString-cpu-arguments-intercept": 1000, + "appendString-cpu-arguments-slope": 59957, + "appendString-memory-arguments-intercept": 4, + "appendString-memory-arguments-slope": 1, + "bData-cpu-arguments": 11183, + "bData-memory-arguments": 32, + "blake2b_256-cpu-arguments-intercept": 201305, + "blake2b_256-cpu-arguments-slope": 8356, + "blake2b_256-memory-arguments": 4, + "cekApplyCost-exBudgetCPU": 16000, + "cekApplyCost-exBudgetMemory": 100, + "cekBuiltinCost-exBudgetCPU": 16000, + "cekBuiltinCost-exBudgetMemory": 100, + "cekConstCost-exBudgetCPU": 16000, + "cekConstCost-exBudgetMemory": 100, + "cekDelayCost-exBudgetCPU": 16000, + "cekDelayCost-exBudgetMemory": 100, + "cekForceCost-exBudgetCPU": 16000, + "cekForceCost-exBudgetMemory": 100, + "cekLamCost-exBudgetCPU": 16000, + "cekLamCost-exBudgetMemory": 100, + "cekStartupCost-exBudgetCPU": 100, + "cekStartupCost-exBudgetMemory": 100, + "cekVarCost-exBudgetCPU": 16000, + "cekVarCost-exBudgetMemory": 100, + "chooseData-cpu-arguments": 94375, + "chooseData-memory-arguments": 32, + "chooseList-cpu-arguments": 132994, + "chooseList-memory-arguments": 32, + "chooseUnit-cpu-arguments": 61462, + "chooseUnit-memory-arguments": 4, + "consByteString-cpu-arguments-intercept": 72010, + "consByteString-cpu-arguments-slope": 178, + "consByteString-memory-arguments-intercept": 0, + "consByteString-memory-arguments-slope": 1, + "constrData-cpu-arguments": 22151, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 91189, + "decodeUtf8-cpu-arguments-slope": 769, + "decodeUtf8-memory-arguments-intercept": 4, + "decodeUtf8-memory-arguments-slope": 2, + "divideInteger-cpu-arguments-constant": 85848, + "divideInteger-cpu-arguments-model-arguments-intercept": 228465, + "divideInteger-cpu-arguments-model-arguments-slope": 122, + "divideInteger-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-minimum": 1, + "divideInteger-memory-arguments-slope": 1, + "encodeUtf8-cpu-arguments-intercept": 1000, + "encodeUtf8-cpu-arguments-slope": 42921, + "encodeUtf8-memory-arguments-intercept": 4, + "encodeUtf8-memory-arguments-slope": 2, + "equalsByteString-cpu-arguments-constant": 24548, + "equalsByteString-cpu-arguments-intercept": 29498, + "equalsByteString-cpu-arguments-slope": 38, + "equalsByteString-memory-arguments": 1, + "equalsData-cpu-arguments-intercept": 898148, + "equalsData-cpu-arguments-slope": 27279, + "equalsData-memory-arguments": 1, + "equalsInteger-cpu-arguments-intercept": 51775, + "equalsInteger-cpu-arguments-slope": 558, + "equalsInteger-memory-arguments": 1, + "equalsString-cpu-arguments-constant": 39184, + "equalsString-cpu-arguments-intercept": 1000, + "equalsString-cpu-arguments-slope": 60594, + "equalsString-memory-arguments": 1, + "fstPair-cpu-arguments": 141895, + "fstPair-memory-arguments": 32, + "headList-cpu-arguments": 83150, + "headList-memory-arguments": 32, + "iData-cpu-arguments": 15299, + "iData-memory-arguments": 32, + "ifThenElse-cpu-arguments": 76049, + "ifThenElse-memory-arguments": 1, + "indexByteString-cpu-arguments": 13169, + "indexByteString-memory-arguments": 4, + "lengthOfByteString-cpu-arguments": 22100, + "lengthOfByteString-memory-arguments": 10, + "lessThanByteString-cpu-arguments-intercept": 28999, + "lessThanByteString-cpu-arguments-slope": 74, + "lessThanByteString-memory-arguments": 1, + "lessThanEqualsByteString-cpu-arguments-intercept": 28999, + "lessThanEqualsByteString-cpu-arguments-slope": 74, + "lessThanEqualsByteString-memory-arguments": 1, + "lessThanEqualsInteger-cpu-arguments-intercept": 43285, + "lessThanEqualsInteger-cpu-arguments-slope": 552, + "lessThanEqualsInteger-memory-arguments": 1, + "lessThanInteger-cpu-arguments-intercept": 44749, + "lessThanInteger-cpu-arguments-slope": 541, + "lessThanInteger-memory-arguments": 1, + "listData-cpu-arguments": 33852, + "listData-memory-arguments": 32, + "mapData-cpu-arguments": 68246, + "mapData-memory-arguments": 32, + "mkCons-cpu-arguments": 72362, + "mkCons-memory-arguments": 32, + "mkNilData-cpu-arguments": 7243, + "mkNilData-memory-arguments": 32, + "mkNilPairData-cpu-arguments": 7391, + "mkNilPairData-memory-arguments": 32, + "mkPairData-cpu-arguments": 11546, + "mkPairData-memory-arguments": 32, + "modInteger-cpu-arguments-constant": 85848, + "modInteger-cpu-arguments-model-arguments-intercept": 228465, + "modInteger-cpu-arguments-model-arguments-slope": 122, + "modInteger-memory-arguments-intercept": 0, + "modInteger-memory-arguments-minimum": 1, + "modInteger-memory-arguments-slope": 1, + "multiplyInteger-cpu-arguments-intercept": 90434, + "multiplyInteger-cpu-arguments-slope": 519, + "multiplyInteger-memory-arguments-intercept": 0, + "multiplyInteger-memory-arguments-slope": 1, + "nullList-cpu-arguments": 74433, + "nullList-memory-arguments": 32, + "quotientInteger-cpu-arguments-constant": 85848, + "quotientInteger-cpu-arguments-model-arguments-intercept": 228465, + "quotientInteger-cpu-arguments-model-arguments-slope": 122, + "quotientInteger-memory-arguments-intercept": 0, + "quotientInteger-memory-arguments-minimum": 1, + "quotientInteger-memory-arguments-slope": 1, + "remainderInteger-cpu-arguments-constant": 85848, + "remainderInteger-cpu-arguments-model-arguments-intercept": 228465, + "remainderInteger-cpu-arguments-model-arguments-slope": 122, + "remainderInteger-memory-arguments-intercept": 0, + "remainderInteger-memory-arguments-minimum": 1, + "remainderInteger-memory-arguments-slope": 1, + "serialiseData-cpu-arguments-intercept": 955506, + "serialiseData-cpu-arguments-slope": 213312, + "serialiseData-memory-arguments-intercept": 0, + "serialiseData-memory-arguments-slope": 2, + "sha2_256-cpu-arguments-intercept": 270652, + "sha2_256-cpu-arguments-slope": 22588, + "sha2_256-memory-arguments": 4, + "sha3_256-cpu-arguments-intercept": 1457325, + "sha3_256-cpu-arguments-slope": 64566, + "sha3_256-memory-arguments": 4, + "sliceByteString-cpu-arguments-intercept": 20467, + "sliceByteString-cpu-arguments-slope": 1, + "sliceByteString-memory-arguments-intercept": 4, + "sliceByteString-memory-arguments-slope": 0, + "sndPair-cpu-arguments": 141992, + "sndPair-memory-arguments": 32, + "subtractInteger-cpu-arguments-intercept": 100788, + "subtractInteger-cpu-arguments-slope": 420, + "subtractInteger-memory-arguments-intercept": 1, + "subtractInteger-memory-arguments-slope": 1, + "tailList-cpu-arguments": 81663, + "tailList-memory-arguments": 32, + "trace-cpu-arguments": 59498, + "trace-memory-arguments": 32, + "unBData-cpu-arguments": 20142, + "unBData-memory-arguments": 32, + "unConstrData-cpu-arguments": 24588, + "unConstrData-memory-arguments": 32, + "unIData-cpu-arguments": 20744, + "unIData-memory-arguments": 32, + "unListData-cpu-arguments": 25933, + "unListData-memory-arguments": 32, + "unMapData-cpu-arguments": 24623, + "unMapData-memory-arguments": 32, + "verifyEcdsaSecp256k1Signature-cpu-arguments": 43053543, + "verifyEcdsaSecp256k1Signature-memory-arguments": 10, + "verifyEd25519Signature-cpu-arguments-intercept": 53384111, + "verifyEd25519Signature-cpu-arguments-slope": 14333, + "verifyEd25519Signature-memory-arguments": 10, + "verifySchnorrSecp256k1Signature-cpu-arguments-intercept": 43574283, + "verifySchnorrSecp256k1Signature-cpu-arguments-slope": 26308, + "verifySchnorrSecp256k1Signature-memory-arguments": 10 + } + }, + "executionUnitPrices": { + "priceMemory": 0.0577, + "priceSteps": 7.21e-5 + }, + "maxBlockBodySize": 90112, + "maxBlockExecutionUnits": { + "memory": 62000000, + "steps": 20000000000 + }, + "maxBlockHeaderSize": 1100, + "maxCollateralInputs": 3, + "maxTxExecutionUnits": { + "memory": 14000000, + "steps": 10000000000 + }, + "maxTxSize": 16384, + "maxValueSize": 5000, + "minPoolCost": 170000000, + "monetaryExpansion": 0.003, + "poolPledgeInfluence": 0.3, + "poolRetireMaxEpoch": 18, + "protocolVersion": { + "major": 8, + "minor": 0 + }, + "stakeAddressDeposit": 2000000, + "stakePoolDeposit": 500000000, + "stakePoolTargetNum": 500, + "treasuryCut": 0.2, + "txFeeFixed": 155381, + "txFeePerByte": 44, + "utxoCostPerByte": 4310 + }, + "latestTip": { + "epoch": 117, + "hash": "2557d0c19d0594d665f0328cd9f94a1ab42b0f27312a2ada31300ae1d4d8b33d", + "slot": 49046780, + "time": 1704729980000 + } +} diff --git a/src/utils/params/preview.json b/src/utils/params/preview.json new file mode 100644 index 0000000..a83977a --- /dev/null +++ b/src/utils/params/preview.json @@ -0,0 +1,656 @@ +{ + "shelleyGenesis": { + "activeSlotsCoeff": 0.05, + "epochLength": 86400, + "genDelegs": { + "12b0f443d02861948a0fce9541916b014e8402984c7b83ad70a834ce": { + "delegate": "7c54a168c731f2f44ced620f3cca7c2bd90731cab223d5167aa994e6", + "vrf": "62d546a35e1be66a2b06e29558ef33f4222f1c466adbb59b52d800964d4e60ec" + }, + "3df542796a64e399b60c74acfbdb5afa1e114532fa36b46d6368ef3a": { + "delegate": "c44bc2f3cc7e98c0f227aa399e4035c33c0d775a0985875fff488e20", + "vrf": "4f9d334decadff6eba258b2df8ae1f02580a2628bce47ae7d957e1acd3f42a3c" + }, + "93fd5083ff20e7ab5570948831730073143bea5a5d5539852ed45889": { + "delegate": "82a02922f10105566b70366b07c758c8134fa91b3d8ae697dfa5e8e0", + "vrf": "8a57e94a9b4c65ec575f35d41edb1df399fa30fdf10775389f5d1ef670ca3f9f" + }, + "a86cab3ea72eabb2e8aafbbf4abbd2ba5bdfd04eea26a39b126a78e4": { + "delegate": "10257f6d3bae913514bdc96c9170b3166bf6838cca95736b0e418426", + "vrf": "1b54aad6b013145a0fc74bb5c2aa368ebaf3999e88637d78e09706d0cc29874a" + }, + "b799804a28885bd49c0e1b99d8b3b26de0fac17a5cf651ecf0c872f0": { + "delegate": "ebe606e22d932d51be2c1ce87e7d7e4c9a7d1f7df4a5535c29e23d22", + "vrf": "b3fc06a1f8ee69ff23185d9af453503be8b15b2652e1f9fb7c3ded6797a2d6f9" + }, + "d125812d6ab973a2c152a0525b7fd32d36ff13555a427966a9cac9b1": { + "delegate": "e302198135fb5b00bfe0b9b5623426f7cf03179ab7ba75f945d5b79b", + "vrf": "b45ca2ed95f92248fa0322ce1fc9f815a5a5aa2f21f1adc2c42c4dccfc7ba631" + }, + "ef27651990a26449a40767d5e06cdef1670a3f3ff4b951d385b51787": { + "delegate": "0e0b11e80d958732e587585d30978d683a061831d1b753878f549d05", + "vrf": "b860ec844f6cd476c4fabb4aa1ca72d5c74d82f3835aed3c9515a35b6e048719" + } + }, + "initialFunds": {}, + "maxKESEvolutions": 120, + "maxLovelaceSupply": 45000000000000000, + "networkId": "Testnet", + "networkMagic": 2, + "protocolParams": { + "a0": 0.1, + "decentralisationParam": 1, + "eMax": 18, + "extraEntropy": { + "tag": "NeutralNonce" + }, + "keyDeposit": 400000, + "maxBlockBodySize": 65536, + "maxBlockHeaderSize": 1100, + "maxTxSize": 16384, + "minFeeA": 44, + "minFeeB": 155381, + "minPoolCost": 0, + "minUTxOValue": 0, + "nOpt": 50, + "poolDeposit": 500000000, + "protocolVersion": { + "major": 5, + "minor": 0 + }, + "rho": 0.00178650067, + "tau": 0.1 + }, + "securityParam": 432, + "slotLength": 1, + "slotsPerKESPeriod": 86400, + "staking": { + "pools": {}, + "stake": {} + }, + "systemStart": "2022-08-09T00:00:00Z", + "updateQuorum": 5 + }, + "alonzoGenesis": { + "lovelacePerUTxOWord": 34482, + "executionPrices": { + "prSteps": { + "numerator": 721, + "denominator": 10000000 + }, + "prMem": { + "numerator": 577, + "denominator": 10000 + } + }, + "maxTxExUnits": { + "exUnitsMem": 10000000, + "exUnitsSteps": 10000000000 + }, + "maxBlockExUnits": { + "exUnitsMem": 50000000, + "exUnitsSteps": 40000000000 + }, + "maxValueSize": 5000, + "collateralPercentage": 150, + "maxCollateralInputs": 3, + "costModels": { + "PlutusV1": { + "sha2_256-memory-arguments": 4, + "equalsString-cpu-arguments-constant": 1000, + "cekDelayCost-exBudgetMemory": 100, + "lessThanEqualsByteString-cpu-arguments-intercept": 103599, + "divideInteger-memory-arguments-minimum": 1, + "appendByteString-cpu-arguments-slope": 621, + "blake2b-cpu-arguments-slope": 29175, + "iData-cpu-arguments": 150000, + "encodeUtf8-cpu-arguments-slope": 1000, + "unBData-cpu-arguments": 150000, + "multiplyInteger-cpu-arguments-intercept": 61516, + "cekConstCost-exBudgetMemory": 100, + "nullList-cpu-arguments": 150000, + "equalsString-cpu-arguments-intercept": 150000, + "trace-cpu-arguments": 150000, + "mkNilData-memory-arguments": 32, + "lengthOfByteString-cpu-arguments": 150000, + "cekBuiltinCost-exBudgetCPU": 29773, + "bData-cpu-arguments": 150000, + "subtractInteger-cpu-arguments-slope": 0, + "unIData-cpu-arguments": 150000, + "consByteString-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-slope": 1, + "divideInteger-cpu-arguments-model-arguments-slope": 118, + "listData-cpu-arguments": 150000, + "headList-cpu-arguments": 150000, + "chooseData-memory-arguments": 32, + "equalsInteger-cpu-arguments-intercept": 136542, + "sha3_256-cpu-arguments-slope": 82363, + "sliceByteString-cpu-arguments-slope": 5000, + "unMapData-cpu-arguments": 150000, + "lessThanInteger-cpu-arguments-intercept": 179690, + "mkCons-cpu-arguments": 150000, + "appendString-memory-arguments-intercept": 0, + "modInteger-cpu-arguments-model-arguments-slope": 118, + "ifThenElse-cpu-arguments": 1, + "mkNilPairData-cpu-arguments": 150000, + "lessThanEqualsInteger-cpu-arguments-intercept": 145276, + "addInteger-memory-arguments-slope": 1, + "chooseList-memory-arguments": 32, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 150000, + "equalsData-memory-arguments": 1, + "subtractInteger-memory-arguments-slope": 1, + "appendByteString-memory-arguments-intercept": 0, + "lengthOfByteString-memory-arguments": 4, + "headList-memory-arguments": 32, + "listData-memory-arguments": 32, + "consByteString-cpu-arguments-intercept": 150000, + "unIData-memory-arguments": 32, + "remainderInteger-memory-arguments-minimum": 1, + "bData-memory-arguments": 32, + "lessThanByteString-cpu-arguments-slope": 248, + "encodeUtf8-memory-arguments-intercept": 0, + "cekStartupCost-exBudgetCPU": 100, + "multiplyInteger-memory-arguments-intercept": 0, + "unListData-memory-arguments": 32, + "remainderInteger-cpu-arguments-model-arguments-slope": 118, + "cekVarCost-exBudgetCPU": 29773, + "remainderInteger-memory-arguments-slope": 1, + "cekForceCost-exBudgetCPU": 29773, + "sha2_256-cpu-arguments-slope": 29175, + "equalsInteger-memory-arguments": 1, + "indexByteString-memory-arguments": 1, + "addInteger-memory-arguments-intercept": 1, + "chooseUnit-cpu-arguments": 150000, + "sndPair-cpu-arguments": 150000, + "cekLamCost-exBudgetCPU": 29773, + "fstPair-cpu-arguments": 150000, + "quotientInteger-memory-arguments-minimum": 1, + "decodeUtf8-cpu-arguments-slope": 1000, + "lessThanInteger-memory-arguments": 1, + "lessThanEqualsInteger-cpu-arguments-slope": 1366, + "fstPair-memory-arguments": 32, + "modInteger-memory-arguments-intercept": 0, + "unConstrData-cpu-arguments": 150000, + "lessThanEqualsInteger-memory-arguments": 1, + "chooseUnit-memory-arguments": 32, + "sndPair-memory-arguments": 32, + "addInteger-cpu-arguments-intercept": 197209, + "decodeUtf8-memory-arguments-slope": 8, + "equalsData-cpu-arguments-intercept": 150000, + "mapData-cpu-arguments": 150000, + "mkPairData-cpu-arguments": 150000, + "quotientInteger-cpu-arguments-constant": 148000, + "consByteString-memory-arguments-slope": 1, + "cekVarCost-exBudgetMemory": 100, + "indexByteString-cpu-arguments": 150000, + "unListData-cpu-arguments": 150000, + "equalsInteger-cpu-arguments-slope": 1326, + "cekStartupCost-exBudgetMemory": 100, + "subtractInteger-cpu-arguments-intercept": 197209, + "divideInteger-cpu-arguments-model-arguments-intercept": 425507, + "divideInteger-memory-arguments-intercept": 0, + "cekForceCost-exBudgetMemory": 100, + "blake2b-cpu-arguments-intercept": 2477736, + "remainderInteger-cpu-arguments-constant": 148000, + "tailList-cpu-arguments": 150000, + "encodeUtf8-cpu-arguments-intercept": 150000, + "equalsString-cpu-arguments-slope": 1000, + "lessThanByteString-memory-arguments": 1, + "multiplyInteger-cpu-arguments-slope": 11218, + "appendByteString-cpu-arguments-intercept": 396231, + "lessThanEqualsByteString-cpu-arguments-slope": 248, + "modInteger-memory-arguments-slope": 1, + "addInteger-cpu-arguments-slope": 0, + "equalsData-cpu-arguments-slope": 10000, + "decodeUtf8-memory-arguments-intercept": 0, + "chooseList-cpu-arguments": 150000, + "constrData-cpu-arguments": 150000, + "equalsByteString-memory-arguments": 1, + "cekApplyCost-exBudgetCPU": 29773, + "quotientInteger-memory-arguments-slope": 1, + "verifySignature-cpu-arguments-intercept": 3345831, + "unMapData-memory-arguments": 32, + "mkCons-memory-arguments": 32, + "sliceByteString-memory-arguments-slope": 1, + "sha3_256-memory-arguments": 4, + "ifThenElse-memory-arguments": 1, + "mkNilPairData-memory-arguments": 32, + "equalsByteString-cpu-arguments-slope": 247, + "appendString-cpu-arguments-intercept": 150000, + "quotientInteger-cpu-arguments-model-arguments-slope": 118, + "cekApplyCost-exBudgetMemory": 100, + "equalsString-memory-arguments": 1, + "multiplyInteger-memory-arguments-slope": 1, + "cekBuiltinCost-exBudgetMemory": 100, + "remainderInteger-memory-arguments-intercept": 0, + "sha2_256-cpu-arguments-intercept": 2477736, + "remainderInteger-cpu-arguments-model-arguments-intercept": 425507, + "lessThanEqualsByteString-memory-arguments": 1, + "tailList-memory-arguments": 32, + "mkNilData-cpu-arguments": 150000, + "chooseData-cpu-arguments": 150000, + "unBData-memory-arguments": 32, + "blake2b-memory-arguments": 4, + "iData-memory-arguments": 32, + "nullList-memory-arguments": 32, + "cekDelayCost-exBudgetCPU": 29773, + "subtractInteger-memory-arguments-intercept": 1, + "lessThanByteString-cpu-arguments-intercept": 103599, + "consByteString-cpu-arguments-slope": 1000, + "appendByteString-memory-arguments-slope": 1, + "trace-memory-arguments": 32, + "divideInteger-cpu-arguments-constant": 148000, + "cekConstCost-exBudgetCPU": 29773, + "encodeUtf8-memory-arguments-slope": 8, + "quotientInteger-cpu-arguments-model-arguments-intercept": 425507, + "mapData-memory-arguments": 32, + "appendString-cpu-arguments-slope": 1000, + "modInteger-cpu-arguments-constant": 148000, + "verifySignature-cpu-arguments-slope": 1, + "unConstrData-memory-arguments": 32, + "quotientInteger-memory-arguments-intercept": 0, + "equalsByteString-cpu-arguments-constant": 150000, + "sliceByteString-memory-arguments-intercept": 0, + "mkPairData-memory-arguments": 32, + "equalsByteString-cpu-arguments-intercept": 112536, + "appendString-memory-arguments-slope": 1, + "lessThanInteger-cpu-arguments-slope": 497, + "modInteger-cpu-arguments-model-arguments-intercept": 425507, + "modInteger-memory-arguments-minimum": 1, + "sha3_256-cpu-arguments-intercept": 0, + "verifySignature-memory-arguments": 1, + "cekLamCost-exBudgetMemory": 100, + "sliceByteString-cpu-arguments-intercept": 150000 + } + } + }, + "latestParams": { + "collateralPercentage": 150, + "costModels": { + "PlutusScriptV1": { + "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 + }, + "PlutusScriptV2": { + "addInteger-cpu-arguments-intercept": 100788, + "addInteger-cpu-arguments-slope": 420, + "addInteger-memory-arguments-intercept": 1, + "addInteger-memory-arguments-slope": 1, + "appendByteString-cpu-arguments-intercept": 1000, + "appendByteString-cpu-arguments-slope": 173, + "appendByteString-memory-arguments-intercept": 0, + "appendByteString-memory-arguments-slope": 1, + "appendString-cpu-arguments-intercept": 1000, + "appendString-cpu-arguments-slope": 59957, + "appendString-memory-arguments-intercept": 4, + "appendString-memory-arguments-slope": 1, + "bData-cpu-arguments": 11183, + "bData-memory-arguments": 32, + "blake2b_256-cpu-arguments-intercept": 201305, + "blake2b_256-cpu-arguments-slope": 8356, + "blake2b_256-memory-arguments": 4, + "cekApplyCost-exBudgetCPU": 16000, + "cekApplyCost-exBudgetMemory": 100, + "cekBuiltinCost-exBudgetCPU": 16000, + "cekBuiltinCost-exBudgetMemory": 100, + "cekConstCost-exBudgetCPU": 16000, + "cekConstCost-exBudgetMemory": 100, + "cekDelayCost-exBudgetCPU": 16000, + "cekDelayCost-exBudgetMemory": 100, + "cekForceCost-exBudgetCPU": 16000, + "cekForceCost-exBudgetMemory": 100, + "cekLamCost-exBudgetCPU": 16000, + "cekLamCost-exBudgetMemory": 100, + "cekStartupCost-exBudgetCPU": 100, + "cekStartupCost-exBudgetMemory": 100, + "cekVarCost-exBudgetCPU": 16000, + "cekVarCost-exBudgetMemory": 100, + "chooseData-cpu-arguments": 94375, + "chooseData-memory-arguments": 32, + "chooseList-cpu-arguments": 132994, + "chooseList-memory-arguments": 32, + "chooseUnit-cpu-arguments": 61462, + "chooseUnit-memory-arguments": 4, + "consByteString-cpu-arguments-intercept": 72010, + "consByteString-cpu-arguments-slope": 178, + "consByteString-memory-arguments-intercept": 0, + "consByteString-memory-arguments-slope": 1, + "constrData-cpu-arguments": 22151, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 91189, + "decodeUtf8-cpu-arguments-slope": 769, + "decodeUtf8-memory-arguments-intercept": 4, + "decodeUtf8-memory-arguments-slope": 2, + "divideInteger-cpu-arguments-constant": 85848, + "divideInteger-cpu-arguments-model-arguments-intercept": 228465, + "divideInteger-cpu-arguments-model-arguments-slope": 122, + "divideInteger-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-minimum": 1, + "divideInteger-memory-arguments-slope": 1, + "encodeUtf8-cpu-arguments-intercept": 1000, + "encodeUtf8-cpu-arguments-slope": 42921, + "encodeUtf8-memory-arguments-intercept": 4, + "encodeUtf8-memory-arguments-slope": 2, + "equalsByteString-cpu-arguments-constant": 24548, + "equalsByteString-cpu-arguments-intercept": 29498, + "equalsByteString-cpu-arguments-slope": 38, + "equalsByteString-memory-arguments": 1, + "equalsData-cpu-arguments-intercept": 898148, + "equalsData-cpu-arguments-slope": 27279, + "equalsData-memory-arguments": 1, + "equalsInteger-cpu-arguments-intercept": 51775, + "equalsInteger-cpu-arguments-slope": 558, + "equalsInteger-memory-arguments": 1, + "equalsString-cpu-arguments-constant": 39184, + "equalsString-cpu-arguments-intercept": 1000, + "equalsString-cpu-arguments-slope": 60594, + "equalsString-memory-arguments": 1, + "fstPair-cpu-arguments": 141895, + "fstPair-memory-arguments": 32, + "headList-cpu-arguments": 83150, + "headList-memory-arguments": 32, + "iData-cpu-arguments": 15299, + "iData-memory-arguments": 32, + "ifThenElse-cpu-arguments": 76049, + "ifThenElse-memory-arguments": 1, + "indexByteString-cpu-arguments": 13169, + "indexByteString-memory-arguments": 4, + "lengthOfByteString-cpu-arguments": 22100, + "lengthOfByteString-memory-arguments": 10, + "lessThanByteString-cpu-arguments-intercept": 28999, + "lessThanByteString-cpu-arguments-slope": 74, + "lessThanByteString-memory-arguments": 1, + "lessThanEqualsByteString-cpu-arguments-intercept": 28999, + "lessThanEqualsByteString-cpu-arguments-slope": 74, + "lessThanEqualsByteString-memory-arguments": 1, + "lessThanEqualsInteger-cpu-arguments-intercept": 43285, + "lessThanEqualsInteger-cpu-arguments-slope": 552, + "lessThanEqualsInteger-memory-arguments": 1, + "lessThanInteger-cpu-arguments-intercept": 44749, + "lessThanInteger-cpu-arguments-slope": 541, + "lessThanInteger-memory-arguments": 1, + "listData-cpu-arguments": 33852, + "listData-memory-arguments": 32, + "mapData-cpu-arguments": 68246, + "mapData-memory-arguments": 32, + "mkCons-cpu-arguments": 72362, + "mkCons-memory-arguments": 32, + "mkNilData-cpu-arguments": 7243, + "mkNilData-memory-arguments": 32, + "mkNilPairData-cpu-arguments": 7391, + "mkNilPairData-memory-arguments": 32, + "mkPairData-cpu-arguments": 11546, + "mkPairData-memory-arguments": 32, + "modInteger-cpu-arguments-constant": 85848, + "modInteger-cpu-arguments-model-arguments-intercept": 228465, + "modInteger-cpu-arguments-model-arguments-slope": 122, + "modInteger-memory-arguments-intercept": 0, + "modInteger-memory-arguments-minimum": 1, + "modInteger-memory-arguments-slope": 1, + "multiplyInteger-cpu-arguments-intercept": 90434, + "multiplyInteger-cpu-arguments-slope": 519, + "multiplyInteger-memory-arguments-intercept": 0, + "multiplyInteger-memory-arguments-slope": 1, + "nullList-cpu-arguments": 74433, + "nullList-memory-arguments": 32, + "quotientInteger-cpu-arguments-constant": 85848, + "quotientInteger-cpu-arguments-model-arguments-intercept": 228465, + "quotientInteger-cpu-arguments-model-arguments-slope": 122, + "quotientInteger-memory-arguments-intercept": 0, + "quotientInteger-memory-arguments-minimum": 1, + "quotientInteger-memory-arguments-slope": 1, + "remainderInteger-cpu-arguments-constant": 85848, + "remainderInteger-cpu-arguments-model-arguments-intercept": 228465, + "remainderInteger-cpu-arguments-model-arguments-slope": 122, + "remainderInteger-memory-arguments-intercept": 0, + "remainderInteger-memory-arguments-minimum": 1, + "remainderInteger-memory-arguments-slope": 1, + "serialiseData-cpu-arguments-intercept": 955506, + "serialiseData-cpu-arguments-slope": 213312, + "serialiseData-memory-arguments-intercept": 0, + "serialiseData-memory-arguments-slope": 2, + "sha2_256-cpu-arguments-intercept": 270652, + "sha2_256-cpu-arguments-slope": 22588, + "sha2_256-memory-arguments": 4, + "sha3_256-cpu-arguments-intercept": 1457325, + "sha3_256-cpu-arguments-slope": 64566, + "sha3_256-memory-arguments": 4, + "sliceByteString-cpu-arguments-intercept": 20467, + "sliceByteString-cpu-arguments-slope": 1, + "sliceByteString-memory-arguments-intercept": 4, + "sliceByteString-memory-arguments-slope": 0, + "sndPair-cpu-arguments": 141992, + "sndPair-memory-arguments": 32, + "subtractInteger-cpu-arguments-intercept": 100788, + "subtractInteger-cpu-arguments-slope": 420, + "subtractInteger-memory-arguments-intercept": 1, + "subtractInteger-memory-arguments-slope": 1, + "tailList-cpu-arguments": 81663, + "tailList-memory-arguments": 32, + "trace-cpu-arguments": 59498, + "trace-memory-arguments": 32, + "unBData-cpu-arguments": 20142, + "unBData-memory-arguments": 32, + "unConstrData-cpu-arguments": 24588, + "unConstrData-memory-arguments": 32, + "unIData-cpu-arguments": 20744, + "unIData-memory-arguments": 32, + "unListData-cpu-arguments": 25933, + "unListData-memory-arguments": 32, + "unMapData-cpu-arguments": 24623, + "unMapData-memory-arguments": 32, + "verifyEcdsaSecp256k1Signature-cpu-arguments": 43053543, + "verifyEcdsaSecp256k1Signature-memory-arguments": 10, + "verifyEd25519Signature-cpu-arguments-intercept": 53384111, + "verifyEd25519Signature-cpu-arguments-slope": 14333, + "verifyEd25519Signature-memory-arguments": 10, + "verifySchnorrSecp256k1Signature-cpu-arguments-intercept": 43574283, + "verifySchnorrSecp256k1Signature-cpu-arguments-slope": 26308, + "verifySchnorrSecp256k1Signature-memory-arguments": 10 + } + }, + "executionUnitPrices": { + "priceMemory": 0.0577, + "priceSteps": 7.21e-5 + }, + "maxBlockBodySize": 90112, + "maxBlockExecutionUnits": { + "memory": 62000000, + "steps": 20000000000 + }, + "maxBlockHeaderSize": 1100, + "maxCollateralInputs": 3, + "maxTxExecutionUnits": { + "memory": 14000000, + "steps": 10000000000 + }, + "maxTxSize": 16384, + "maxValueSize": 5000, + "minPoolCost": 170000000, + "monetaryExpansion": 0.003, + "poolPledgeInfluence": 0.3, + "poolRetireMaxEpoch": 18, + "protocolVersion": { + "major": 8, + "minor": 0 + }, + "stakeAddressDeposit": 2000000, + "stakePoolDeposit": 500000000, + "stakePoolTargetNum": 500, + "treasuryCut": 0.2, + "txFeeFixed": 155381, + "txFeePerByte": 44, + "utxoCostPerByte": 4310 + }, + "latestTip": { + "epoch": 440, + "hash": "4a84377e54da8b2b09610ff28e2908464589153add346490b48ef74393e43c1c", + "slot": 38073978, + "time": 1704729978000 + } +} diff --git a/tsconfig.json b/tsconfig.json index 1264a2a..ee7a32d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,8 @@ "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, - "declaration": true + "declaration": true, + "resolveJsonModule": true }, "include": ["src/**/*", "src/tests/**/*"], "exclude": ["node_modules"] From 0a2ca5fb0c5ee22310c86de45673dd1537aa3517 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Sat, 31 Aug 2024 00:55:31 +0800 Subject: [PATCH 14/20] add withdraw --- src/commands/withdraw.ts | 42 ++++++++++++++ src/withdraw.ts | 118 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 src/commands/withdraw.ts diff --git a/src/commands/withdraw.ts b/src/commands/withdraw.ts new file mode 100644 index 0000000..cac360b --- /dev/null +++ b/src/commands/withdraw.ts @@ -0,0 +1,42 @@ +import program from "../cli"; +import { loadConfig } from "../config"; +import { withdraw } from "../withdraw"; + +import * as helios from "@koralabs/helios"; + +const withdrawCommand = program + .command("withdraw") + .description("Withdraw Handle NFT from Marketplace") + .argument("
", "Address to perform withdraw") + .argument("", "Ada Handle Name to list on marketplace") + .argument("", "Transaction Hash of UTxO where handle is") + .argument("", "Transaction Index of UTxO where handle is") + .action( + async ( + bech32Address: string, + handleName: string, + txHash: string, + txIndex: string + ) => { + const configResult = loadConfig(); + if (!configResult.ok) return program.error(configResult.error); + const config = configResult.data; + + const address = helios.Address.fromBech32(bech32Address); + const txResult = await withdraw( + config.blockfrostApiKey, + address, + config.handlePolicyId, + handleName, + txHash, + parseInt(txIndex), + config.paramters + ); + + if (!txResult.ok) return program.error(txResult.error); + console.log("\nTransaction CBOR Hex, copy and paste to wallet\n"); + console.log(txResult.data.toCborHex()); + } + ); + +export default withdrawCommand; diff --git a/src/withdraw.ts b/src/withdraw.ts index e69de29..a43746f 100644 --- a/src/withdraw.ts +++ b/src/withdraw.ts @@ -0,0 +1,118 @@ +import { decodeDatum } from "./datum"; +import { getNetwork, mayFail, mayFailAsync } from "./helpers"; +import { Parameters } from "./types"; +import { fetchNetworkParameters, getUplcProgram } from "./utils"; + +import * as helios from "@koralabs/helios"; +import { AssetNameLabel } from "@koralabs/kora-labs-common"; +import { WithdrawOrUpdate } from "redeemer"; +import { Err, Ok, Result } from "ts-res"; + +const withdraw = async ( + blockfrostApiKey: string, + address: helios.Address, + handlePolicyId: string, + handleName: string, + txHash: string, + txIndex: number, + parameters: Parameters +): Promise> => { + const network = getNetwork(blockfrostApiKey); + const isTestnet = network != "mainnet"; + helios.config.set({ + IS_TESTNET: isTestnet, + AUTO_SET_VALIDITY_RANGE: true, + }); + + const api = new helios.BlockfrostV0(network, blockfrostApiKey); + + const handleUtxoResult = await mayFailAsync(() => + api.getUtxo(new helios.TxOutputId(`${txHash}#${txIndex}`)) + ).complete(); + if (!handleUtxoResult.ok) + return Err(`Getting Handle UTxO error: ${handleUtxoResult.error}`); + const handleUtxo = handleUtxoResult.data; + + const utxosResult = await mayFailAsync(() => + api.getUtxos(address) + ).complete(); + if (!utxosResult.ok) return Err(`Getting UTxOs error: ${utxosResult.error}`); + const utxos = utxosResult.data; + + const uplcProgramResult = await mayFailAsync(() => + getUplcProgram(parameters) + ).complete(); + if (!uplcProgramResult.ok) + return Err(`Getting Uplc Program error: ${uplcProgramResult.error}`); + const uplcProgram = uplcProgramResult.data; + + const handleRawDatum = handleUtxo.output.datum; + if (!handleRawDatum) return Err("Handle UTxO datum not found"); + const datumResult = await mayFailAsync(() => + decodeDatum(handleRawDatum) + ).complete(); + if (!datumResult.ok) + return Err(`Decoding Datum Cbor error: ${datumResult.error}`); + const datum = datumResult.data; + + /// fetch protocol parameter + const networkParamsResult = await mayFailAsync(() => + fetchNetworkParameters(network) + ).complete(); + if (!networkParamsResult.ok) + return Err( + `Fetching Network Parameter error: ${networkParamsResult.error}` + ); + const networkParams = networkParamsResult.data; + + /// build tx + const tx = new helios.Tx(); + + /// take fund to pay payouts + const minFee = 5_000_000n; + const [selected] = helios.CoinSelection.selectLargestFirst( + utxos, + new helios.Value(minFee) + ); + tx.addInputs(selected); + + /// redeemer + const redeemer = mayFail(() => WithdrawOrUpdate()); + if (!redeemer.ok) return Err(`Making Redeemer error: ${redeemer.error}`); + + /// collect handle NFT to buy + tx.addInput(handleUtxo, redeemer.data); + tx.attachScript(uplcProgram); + + /// add owner signature + if (!datum.owner.pubKeyHash) return Err("Owner in Datum is not correct"); + tx.addSigner(datum.owner.pubKeyHash); + + /// add handle withdraw output + const handleAsset = new helios.Assets([ + [ + handlePolicyId, + [ + [ + `${AssetNameLabel.LBL_222}${Buffer.from(handleName).toString("hex")}`, + 1, + ], + ], + ], + ]); + const handleWithdrawOutput = new helios.TxOutput( + address, + new helios.Value(0, handleAsset) + ); + handleWithdrawOutput.correctLovelace(networkParams); + tx.addOutput(handleWithdrawOutput); + + const txCompleteResult = await mayFailAsync(() => + tx.finalize(networkParams, address) + ).complete(); + if (!txCompleteResult.ok) + return Err(`Finalizing Tx error: ${txCompleteResult.error}`); + return Ok(txCompleteResult.data); +}; + +export { withdraw }; From 9ae75f9ee0318c9077572268ba7dc68c7589b4e8 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Sat, 31 Aug 2024 01:09:03 +0800 Subject: [PATCH 15/20] fix --- package-lock.json | 15 ++++----------- package.json | 2 +- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c9f626..841f480 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "marketplace": "bin/marketplace" }, "devDependencies": { - "@koralabs/helios": "0.16.8-2", + "@koralabs/helios": "0.16.8-1", "@koralabs/kora-labs-common": "^4.0.7", "@koralabs/kora-labs-contract-testing": "0.0.7", "@types/node": "^22.1.0", @@ -568,9 +568,9 @@ "dev": true }, "node_modules/@koralabs/helios": { - "version": "0.16.8-2", - "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-2.tgz", - "integrity": "sha512-qAKs3PgZye+vjWM9bZVgqVVJgA3CruVeDoFn6xAoH3us7seofSei3N1364bKTsYHTz+hEtMRcYU4GEtceaJs1A==", + "version": "0.16.8-1", + "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-1.tgz", + "integrity": "sha512-/pbL4lUP7CBELSxfMuZUhJ5rZ5B3T+kwaQ4joI9y+SDMFyfqySARcgv5+uTT1nnTd/gCgM3QzMUZBOL8BMM3AA==", "dev": true, "license": "BSD-3-Clause" }, @@ -598,13 +598,6 @@ "bip39": "^3.1.0" } }, - "node_modules/@koralabs/kora-labs-contract-testing/node_modules/@koralabs/helios": { - "version": "0.16.8-1", - "resolved": "https://registry.npmjs.org/@koralabs/helios/-/helios-0.16.8-1.tgz", - "integrity": "sha512-/pbL4lUP7CBELSxfMuZUhJ5rZ5B3T+kwaQ4joI9y+SDMFyfqySARcgv5+uTT1nnTd/gCgM3QzMUZBOL8BMM3AA==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/@noble/hashes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", diff --git a/package.json b/package.json index 6b76ddb..ddf8a6c 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "author": "Kora Labs ", "license": "ISC", "devDependencies": { - "@koralabs/helios": "0.16.8-2", + "@koralabs/helios": "0.16.8-1", "@koralabs/kora-labs-common": "^4.0.7", "@koralabs/kora-labs-contract-testing": "0.0.7", "@types/node": "^22.1.0", From 9b92fbfd40a471b07fc0a42d64a7b7c6ab54e624 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Mon, 2 Sep 2024 09:52:19 +0800 Subject: [PATCH 16/20] add buy and update command --- src/buy.ts | 20 +------ src/commands/buy.ts | 42 ++++++--------- src/commands/update.ts | 57 ++++++++++++++++++++ src/commands/withdraw.ts | 42 ++++++--------- src/list.ts | 8 +-- src/update.ts | 112 +++++++++++++++++++++++++++++++++++++++ src/withdraw.ts | 24 ++------- 7 files changed, 212 insertions(+), 93 deletions(-) create mode 100644 src/commands/update.ts diff --git a/src/buy.ts b/src/buy.ts index 498efcc..c2ff747 100644 --- a/src/buy.ts +++ b/src/buy.ts @@ -4,15 +4,12 @@ import { Parameters } from "./types"; import { fetchNetworkParameters, getUplcProgram } from "./utils"; import * as helios from "@koralabs/helios"; -import { AssetNameLabel } from "@koralabs/kora-labs-common"; import { Buy } from "redeemer"; import { Err, Ok, Result } from "ts-res"; const buy = async ( blockfrostApiKey: string, address: helios.Address, - handlePolicyId: string, - handleName: string, txHash: string, txIndex: number, parameters: Parameters @@ -117,24 +114,11 @@ const buy = async ( tx.addOutputs(payoutOutputs); /// add handle buy output - const handleAsset = new helios.Assets([ - [ - handlePolicyId, - [ - [ - `${AssetNameLabel.LBL_222}${Buffer.from(handleName).toString("hex")}`, - 1, - ], - ], - ], - ]); - const handleBuyOutput = new helios.TxOutput( - address, - new helios.Value(0, handleAsset) - ); + const handleBuyOutput = new helios.TxOutput(address, handleUtxo.value); handleBuyOutput.correctLovelace(networkParams); tx.addOutput(handleBuyOutput); + /// finalize tx const txCompleteResult = await mayFailAsync(() => tx.finalize(networkParams, address) ).complete(); diff --git a/src/commands/buy.ts b/src/commands/buy.ts index 1bf0b24..d6d524e 100644 --- a/src/commands/buy.ts +++ b/src/commands/buy.ts @@ -8,35 +8,25 @@ const buyCommand = program .command("buy") .description("Buy Handle NFT on Marketplace") .argument("
", "Address to perform buying") - .argument("", "Ada Handle Name to list on marketplace") .argument("", "Transaction Hash of UTxO where handle is") .argument("", "Transaction Index of UTxO where handle is") - .action( - async ( - bech32Address: string, - handleName: string, - txHash: string, - txIndex: string - ) => { - const configResult = loadConfig(); - if (!configResult.ok) return program.error(configResult.error); - const config = configResult.data; + .action(async (bech32Address: string, txHash: string, txIndex: string) => { + const configResult = loadConfig(); + if (!configResult.ok) return program.error(configResult.error); + const config = configResult.data; - const address = helios.Address.fromBech32(bech32Address); - const txResult = await buy( - config.blockfrostApiKey, - address, - config.handlePolicyId, - handleName, - txHash, - parseInt(txIndex), - config.paramters - ); + const address = helios.Address.fromBech32(bech32Address); + const txResult = await buy( + config.blockfrostApiKey, + address, + txHash, + parseInt(txIndex), + config.paramters + ); - if (!txResult.ok) return program.error(txResult.error); - console.log("\nTransaction CBOR Hex, copy and paste to wallet\n"); - console.log(txResult.data.toCborHex()); - } - ); + if (!txResult.ok) return program.error(txResult.error); + console.log("\nTransaction CBOR Hex, copy and paste to wallet\n"); + console.log(txResult.data.toCborHex()); + }); export default buyCommand; diff --git a/src/commands/update.ts b/src/commands/update.ts new file mode 100644 index 0000000..3c5a439 --- /dev/null +++ b/src/commands/update.ts @@ -0,0 +1,57 @@ +import program from "../cli"; +import { loadConfig } from "../config"; +import { update } from "../update"; +import { adaToLovelace } from "../utils"; + +import * as helios from "@koralabs/helios"; + +const updateCommand = program + .command("update") + .description("Update Handle NFT on Marketplace") + .argument("
", "Address to perform update") + .argument("", "Transaction Hash of UTxO where handle is") + .argument("", "Transaction Index of UTxO where handle is") + .argument("", "New Price in ada") + .argument("", "Address who create this NFT") + .action( + async ( + bech32Address: string, + txHash: string, + txIndex: string, + newPriceString: string, + newCreatorBech32Address: string + ) => { + const configResult = loadConfig(); + if (!configResult.ok) return program.error(configResult.error); + const config = configResult.data; + + const address = helios.Address.fromBech32(bech32Address); + const newCreatorAddress = helios.Address.fromBech32( + newCreatorBech32Address + ); + const txResult = await update( + config.blockfrostApiKey, + address, + txHash, + parseInt(txIndex), + [ + { + address, + amountLovelace: adaToLovelace(Number(newPriceString) * 0.9), + }, + { + address: newCreatorAddress, + amountLovelace: adaToLovelace(Number(newPriceString) * 0.1), + }, + ], + address, + config.paramters + ); + + if (!txResult.ok) return program.error(txResult.error); + console.log("\nTransaction CBOR Hex, copy and paste to wallet\n"); + console.log(txResult.data.toCborHex()); + } + ); + +export default updateCommand; diff --git a/src/commands/withdraw.ts b/src/commands/withdraw.ts index cac360b..bf44d80 100644 --- a/src/commands/withdraw.ts +++ b/src/commands/withdraw.ts @@ -8,35 +8,25 @@ const withdrawCommand = program .command("withdraw") .description("Withdraw Handle NFT from Marketplace") .argument("
", "Address to perform withdraw") - .argument("", "Ada Handle Name to list on marketplace") .argument("", "Transaction Hash of UTxO where handle is") .argument("", "Transaction Index of UTxO where handle is") - .action( - async ( - bech32Address: string, - handleName: string, - txHash: string, - txIndex: string - ) => { - const configResult = loadConfig(); - if (!configResult.ok) return program.error(configResult.error); - const config = configResult.data; + .action(async (bech32Address: string, txHash: string, txIndex: string) => { + const configResult = loadConfig(); + if (!configResult.ok) return program.error(configResult.error); + const config = configResult.data; - const address = helios.Address.fromBech32(bech32Address); - const txResult = await withdraw( - config.blockfrostApiKey, - address, - config.handlePolicyId, - handleName, - txHash, - parseInt(txIndex), - config.paramters - ); + const address = helios.Address.fromBech32(bech32Address); + const txResult = await withdraw( + config.blockfrostApiKey, + address, + txHash, + parseInt(txIndex), + config.paramters + ); - if (!txResult.ok) return program.error(txResult.error); - console.log("\nTransaction CBOR Hex, copy and paste to wallet\n"); - console.log(txResult.data.toCborHex()); - } - ); + if (!txResult.ok) return program.error(txResult.error); + console.log("\nTransaction CBOR Hex, copy and paste to wallet\n"); + console.log(txResult.data.toCborHex()); + }); export default withdrawCommand; diff --git a/src/list.ts b/src/list.ts index d055444..b83ce7a 100644 --- a/src/list.ts +++ b/src/list.ts @@ -44,6 +44,7 @@ const list = async ( return Err(`Getting Uplc Program error: ${uplcProgramResult.error}`); const uplcProgram = uplcProgramResult.data; + /// take fund and handle asset const handleAsset = new helios.Assets([ [ handlePolicyId, @@ -70,13 +71,14 @@ const list = async ( const datum = mayFail(() => buildDatum(payouts, owner)); if (!datum.ok) return Err(`Building Datum error: ${datum.error}`); - const output = new helios.TxOutput( + /// ada handle list update + const handleListOutput = new helios.TxOutput( helios.Address.fromHash(uplcProgram.validatorHash), new helios.Value(0n, handleAsset), datum.data ); - output.correctLovelace(paramter); - tx.addOutput(output); + handleListOutput.correctLovelace(paramter); + tx.addOutput(handleListOutput); const txCompleteResult = await mayFailAsync(() => tx.finalize(paramter, address) diff --git a/src/update.ts b/src/update.ts index e69de29..4e1b1bc 100644 --- a/src/update.ts +++ b/src/update.ts @@ -0,0 +1,112 @@ +import { buildDatum, decodeDatum } from "./datum"; +import { getNetwork, mayFail, mayFailAsync } from "./helpers"; +import { Parameters, Payout } from "./types"; +import { fetchNetworkParameters, getUplcProgram } from "./utils"; + +import * as helios from "@koralabs/helios"; +import { WithdrawOrUpdate } from "redeemer"; +import { Err, Ok, Result } from "ts-res"; + +const update = async ( + blockfrostApiKey: string, + address: helios.Address, + txHash: string, + txIndex: number, + newPayouts: Payout[], + newOwner: helios.Address, + parameters: Parameters +): Promise> => { + const network = getNetwork(blockfrostApiKey); + const isTestnet = network != "mainnet"; + helios.config.set({ + IS_TESTNET: isTestnet, + AUTO_SET_VALIDITY_RANGE: true, + }); + + const api = new helios.BlockfrostV0(network, blockfrostApiKey); + + const handleUtxoResult = await mayFailAsync(() => + api.getUtxo(new helios.TxOutputId(`${txHash}#${txIndex}`)) + ).complete(); + if (!handleUtxoResult.ok) + return Err(`Getting Handle UTxO error: ${handleUtxoResult.error}`); + const handleUtxo = handleUtxoResult.data; + + const utxosResult = await mayFailAsync(() => + api.getUtxos(address) + ).complete(); + if (!utxosResult.ok) return Err(`Getting UTxOs error: ${utxosResult.error}`); + const utxos = utxosResult.data; + + const uplcProgramResult = await mayFailAsync(() => + getUplcProgram(parameters) + ).complete(); + if (!uplcProgramResult.ok) + return Err(`Getting Uplc Program error: ${uplcProgramResult.error}`); + const uplcProgram = uplcProgramResult.data; + + const handleRawDatum = handleUtxo.output.datum; + if (!handleRawDatum) return Err("Handle UTxO datum not found"); + const datumResult = await mayFailAsync(() => + decodeDatum(handleRawDatum) + ).complete(); + if (!datumResult.ok) + return Err(`Decoding Datum Cbor error: ${datumResult.error}`); + const datum = datumResult.data; + + /// fetch protocol parameter + const networkParamsResult = await mayFailAsync(() => + fetchNetworkParameters(network) + ).complete(); + if (!networkParamsResult.ok) + return Err( + `Fetching Network Parameter error: ${networkParamsResult.error}` + ); + const networkParams = networkParamsResult.data; + + /// build tx + const tx = new helios.Tx(); + + /// take fund + const minFee = 5_000_000n; + const [selected] = helios.CoinSelection.selectLargestFirst( + utxos, + new helios.Value(minFee) + ); + tx.addInputs(selected); + + /// redeemer + const redeemer = mayFail(() => WithdrawOrUpdate()); + if (!redeemer.ok) return Err(`Making Redeemer error: ${redeemer.error}`); + + /// collect handle NFT to update + tx.addInput(handleUtxo, redeemer.data); + tx.attachScript(uplcProgram); + + /// add owner signature + if (!datum.owner.pubKeyHash) return Err("Owner in Datum is not correct"); + tx.addSigner(datum.owner.pubKeyHash); + + /// build new datum + const newDatum = mayFail(() => buildDatum(newPayouts, newOwner)); + if (!newDatum.ok) return Err(`Building New Datum error: ${newDatum.error}`); + + /// add handle update output + const handleUpdateOutput = new helios.TxOutput( + helios.Address.fromHash(uplcProgram.validatorHash), + handleUtxo.value, + newDatum.data + ); + handleUpdateOutput.correctLovelace(networkParams); + tx.addOutput(handleUpdateOutput); + + /// finalize tx + const txCompleteResult = await mayFailAsync(() => + tx.finalize(networkParams, address) + ).complete(); + if (!txCompleteResult.ok) + return Err(`Finalizing Tx error: ${txCompleteResult.error}`); + return Ok(txCompleteResult.data); +}; + +export { update }; diff --git a/src/withdraw.ts b/src/withdraw.ts index a43746f..ed444fb 100644 --- a/src/withdraw.ts +++ b/src/withdraw.ts @@ -4,15 +4,12 @@ import { Parameters } from "./types"; import { fetchNetworkParameters, getUplcProgram } from "./utils"; import * as helios from "@koralabs/helios"; -import { AssetNameLabel } from "@koralabs/kora-labs-common"; import { WithdrawOrUpdate } from "redeemer"; import { Err, Ok, Result } from "ts-res"; const withdraw = async ( blockfrostApiKey: string, address: helios.Address, - handlePolicyId: string, - handleName: string, txHash: string, txIndex: number, parameters: Parameters @@ -68,7 +65,7 @@ const withdraw = async ( /// build tx const tx = new helios.Tx(); - /// take fund to pay payouts + /// take fund const minFee = 5_000_000n; const [selected] = helios.CoinSelection.selectLargestFirst( utxos, @@ -80,7 +77,7 @@ const withdraw = async ( const redeemer = mayFail(() => WithdrawOrUpdate()); if (!redeemer.ok) return Err(`Making Redeemer error: ${redeemer.error}`); - /// collect handle NFT to buy + /// collect handle NFT to withdraw tx.addInput(handleUtxo, redeemer.data); tx.attachScript(uplcProgram); @@ -89,24 +86,11 @@ const withdraw = async ( tx.addSigner(datum.owner.pubKeyHash); /// add handle withdraw output - const handleAsset = new helios.Assets([ - [ - handlePolicyId, - [ - [ - `${AssetNameLabel.LBL_222}${Buffer.from(handleName).toString("hex")}`, - 1, - ], - ], - ], - ]); - const handleWithdrawOutput = new helios.TxOutput( - address, - new helios.Value(0, handleAsset) - ); + const handleWithdrawOutput = new helios.TxOutput(address, handleUtxo.value); handleWithdrawOutput.correctLovelace(networkParams); tx.addOutput(handleWithdrawOutput); + /// finalize tx const txCompleteResult = await mayFailAsync(() => tx.finalize(networkParams, address) ).complete(); From 4b8d5164388f84afe2c9de0b762927c478b53fea Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Mon, 2 Sep 2024 10:27:46 +0800 Subject: [PATCH 17/20] fix making datum --- src/contract/marketplace.helios | 3 ++- src/datum.ts | 4 ++-- src/tests/tx.test.ts | 15 +++++++++++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/contract/marketplace.helios b/src/contract/marketplace.helios index f032f1e..a1af21d 100644 --- a/src/contract/marketplace.helios +++ b/src/contract/marketplace.helios @@ -214,7 +214,8 @@ func main(datum: Datum, redeemer: Redeemer, ctx: ScriptContext) -> Bool { // owner can cancel or update their listing // at any time. // is signed by owner - tx.is_signed_by(PubKeyHash::new(datum.owner)) + assert(tx.is_signed_by(PubKeyHash::new(datum.owner)), "Must be signed by owner"); + true } } } \ No newline at end of file diff --git a/src/datum.ts b/src/datum.ts index 57d47fb..0f20a64 100644 --- a/src/datum.ts +++ b/src/datum.ts @@ -24,7 +24,7 @@ const buildDatum = (payouts: Payout[], owner: helios.Address): helios.Datum => { ]) ) ), - new helios.ByteArrayData(owner.bytes), + new helios.ByteArrayData(owner.pubKeyHash.bytes), ]); return helios.Datum.inline(data); }; @@ -37,7 +37,7 @@ const decodeDatum = async (datum: helios.Datum): Promise => { cborString: datumDataCborHex, }); - const owner = helios.Address.fromHex(decoded[1].slice(2)); + const owner = helios.Address.fromHash(decoded[1].slice(2)); // eslint-disable-next-line @typescript-eslint/no-explicit-any const payouts: Payout[] = decoded[0].map((rawPayout: any) => { const address = helios.Address.fromHex(rawPayout[0].slice(2)); diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index c9b1d28..f8af200 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -1,4 +1,5 @@ import { buildDatumTag } from "../datum"; +import { invariant } from "../helpers"; import { adaToLovelace } from "../utils"; import { @@ -303,7 +304,9 @@ const runTests = async (file: string) => { { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; - fixture.signatories = [fixture.owner]; + + invariant(fixture.owner.pubKeyHash, "Fixture owner is not valid"); + fixture.signatories = [fixture.owner.pubKeyHash]; return await fixture.initialize(); }) ); @@ -323,7 +326,8 @@ const runTests = async (file: string) => { ]; return await fixture.initialize(); }), - false + false, + "Must be signed by owner" ); /// ---------- Should Approve ---------- @@ -342,7 +346,9 @@ const runTests = async (file: string) => { fixture.newPayouts = [ { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, ]; - fixture.signatories = [fixture.owner]; + + invariant(fixture.owner.pubKeyHash, "Fixture owner is not valid"); + fixture.signatories = [fixture.owner.pubKeyHash]; return await fixture.initialize(); }) ); @@ -365,7 +371,8 @@ const runTests = async (file: string) => { ]; return await fixture.initialize(); }), - false + false, + "Must be signed by owner" ); }; From 04ed08fc2a0545392ddc451a27d3ab85ae0c185e Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Mon, 2 Sep 2024 13:20:30 +0800 Subject: [PATCH 18/20] refactor --- src/commands/list.ts | 5 +- src/datum.ts | 12 ++-- src/list.ts | 2 +- src/tests/constants.ts | 4 ++ src/tests/fixtures.ts | 122 +++++++++++++++++++++++++++++++---------- src/tests/tx.test.ts | 55 +++++++++---------- src/types.ts | 2 +- src/update.ts | 3 +- src/withdraw.ts | 3 +- 9 files changed, 138 insertions(+), 70 deletions(-) diff --git a/src/commands/list.ts b/src/commands/list.ts index 9a25c0b..0103b24 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -4,6 +4,7 @@ import { list } from "../list"; import { adaToLovelace } from "../utils"; import * as helios from "@koralabs/helios"; +import { invariant } from "helpers"; const buyCommand = program .command("list") @@ -25,6 +26,8 @@ const buyCommand = program const address = helios.Address.fromBech32(bech32Address); const creatorAddress = helios.Address.fromBech32(creatorBech32Address); + invariant(address.pubKeyHash, "Address is invalid"); + const txResult = await list( config.blockfrostApiKey, address, @@ -37,7 +40,7 @@ const buyCommand = program amountLovelace: adaToLovelace(Number(priceString) * 0.1), }, ], - address, + address.pubKeyHash, config.paramters ); diff --git a/src/datum.ts b/src/datum.ts index 0f20a64..74d12b1 100644 --- a/src/datum.ts +++ b/src/datum.ts @@ -12,8 +12,10 @@ const buildDatumTag = (outputRef: helios.TxOutputId): helios.Datum => { ); }; -const buildDatum = (payouts: Payout[], owner: helios.Address): helios.Datum => { - invariant(!!owner.pubKeyHash, "Not valid owner"); +const buildDatum = ( + payouts: Payout[], + owner: helios.PubKeyHash +): helios.Datum => { const data = new helios.ListData([ new helios.ListData( payouts.map( @@ -24,7 +26,7 @@ const buildDatum = (payouts: Payout[], owner: helios.Address): helios.Datum => { ]) ) ), - new helios.ByteArrayData(owner.pubKeyHash.bytes), + new helios.ByteArrayData(owner.bytes), ]); return helios.Datum.inline(data); }; @@ -37,7 +39,7 @@ const decodeDatum = async (datum: helios.Datum): Promise => { cborString: datumDataCborHex, }); - const owner = helios.Address.fromHash(decoded[1].slice(2)); + const owner = helios.PubKeyHash.fromHex(decoded[1].slice(2)); // eslint-disable-next-line @typescript-eslint/no-explicit-any const payouts: Payout[] = decoded[0].map((rawPayout: any) => { const address = helios.Address.fromHex(rawPayout[0].slice(2)); @@ -46,8 +48,8 @@ const decodeDatum = async (datum: helios.Datum): Promise => { }); return { - owner, payouts, + owner, }; }; diff --git a/src/list.ts b/src/list.ts index b83ce7a..ee2f8e4 100644 --- a/src/list.ts +++ b/src/list.ts @@ -13,7 +13,7 @@ const list = async ( handlePolicyId: string, handleName: string, payouts: Payout[], - owner: helios.Address, + owner: helios.PubKeyHash, parameters: Parameters ): Promise> => { const network = getNetwork(blockfrostApiKey); diff --git a/src/tests/constants.ts b/src/tests/constants.ts index a56664d..f92ee1f 100644 --- a/src/tests/constants.ts +++ b/src/tests/constants.ts @@ -23,6 +23,9 @@ const ONWER_ADDRESS = helios.Address.fromHash( "01234567890123456789012345678901234567890123456789111111" ) ); +const OWNER_PUB_KEY_KEY = helios.PubKeyHash.fromHex( + "01234567890123456789012345678901234567890123456789111111" +); const MARKETPLACE_ADDRESS = helios.Address.fromBech32( "addr_test1qp3n5qrplndc4jjmsmhn59mlmjcvz7xvegcxdv97wxtl8gthwj7fp7cy0tpvdzmd46u3c9tvjfxrpjc2faaqzm43wrpshmp3xw" @@ -79,6 +82,7 @@ export { MARKETPLACE_ADDRESS, minLovelace, ONWER_ADDRESS, + OWNER_PUB_KEY_KEY, PAYOUT_ADDRESSES, SPAM_TOKEN_POLICY_ID, }; diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts index 4a80715..0b98c79 100644 --- a/src/tests/fixtures.ts +++ b/src/tests/fixtures.ts @@ -6,6 +6,7 @@ import { HANDLE_POLICY_ID, minLovelace, ONWER_ADDRESS, + OWNER_PUB_KEY_KEY, SPAM_TOKEN_POLICY_ID, } from "./constants"; @@ -36,6 +37,21 @@ class BuyFixture extends Fixture { async initialize() { this.redeemer = Buy(this.payoutOutputsOffset); const datum = buildDatum(this.payouts, this.owner); + + const handleAsset = new helios.Assets([ + [ + HANDLE_POLICY_ID, + [ + [ + `${AssetNameLabel.LBL_222}${Buffer.from(this.handleName).toString( + "hex" + )}`, + 1, + ], + ], + ], + ]); + this.inputs = [ new helios.TxInput( // money & collateral new helios.TxOutputId(getNewFakeUtxoId()), @@ -60,19 +76,7 @@ class BuyFixture extends Fixture { new helios.TxOutputId(this.spendingUtxoId), new helios.TxOutput( this.scriptAddress, - new helios.Value(minLovelace, [ - [ - HANDLE_POLICY_ID, - [ - [ - `${AssetNameLabel.LBL_222}${Buffer.from( - this.handleName - ).toString("hex")}`, - 1, - ], - ], - ], - ]), + new helios.Value(minLovelace, handleAsset), datum ) ), @@ -80,7 +84,7 @@ class BuyFixture extends Fixture { this.outputs = this.payoutOutputs.map( (payout, index) => - new helios.TxOutput( /// marketplace address + new helios.TxOutput( payout.address, new helios.Value(payout.amountLovelace), index == this.payoutOutputsOffset ? this.datumTag : undefined @@ -93,16 +97,14 @@ class BuyFixture extends Fixture { } } -class WithdrawOrUpdateFixture extends Fixture { +class UpdateFixture extends Fixture { handleName = "golddydev"; payouts: Payout[] = []; - newPayouts: Payout[] | undefined = undefined; - owner: helios.Address = ONWER_ADDRESS; + ownerPubKeyHash: helios.PubKeyHash = OWNER_PUB_KEY_KEY; - nftOutputAddress: helios.Address = helios.Address.fromBech32( - this.owner.toBech32() - ); + newPayouts: Payout[] = []; + newOwnerPubKeyHash = helios.PubKeyHash.fromHex(this.ownerPubKeyHash.hex); constructor(validatorHash: helios.ValidatorHash) { super(validatorHash); @@ -110,9 +112,9 @@ class WithdrawOrUpdateFixture extends Fixture { async initialize() { this.redeemer = WithdrawOrUpdate(); - const datum = buildDatum(this.payouts, this.owner); + const datum = buildDatum(this.payouts, this.ownerPubKeyHash); - const nftValue = new helios.Value(minLovelace, [ + const handleAsset = new helios.Assets([ [ HANDLE_POLICY_ID, [ @@ -133,20 +135,82 @@ class WithdrawOrUpdateFixture extends Fixture { new helios.Value(BigInt(500_000_000)) ) ), - new helios.TxInput( /// Handle NFT to withdraw or update + new helios.TxInput( /// Handle NFT to update new helios.TxOutputId(getNewFakeUtxoId()), - new helios.TxOutput(this.scriptAddress, nftValue, datum) + new helios.TxOutput( + this.scriptAddress, + new helios.Value(minLovelace, handleAsset), + datum + ) ), ]; - const newDatum = this.newPayouts - ? buildDatum(this.newPayouts, this.owner) - : null; + const newDatum = buildDatum(this.newPayouts, this.newOwnerPubKeyHash); this.outputs = [ - new helios.TxOutput(this.nftOutputAddress, nftValue, newDatum), + new helios.TxOutput( + this.scriptAddress, + new helios.Value(minLovelace, handleAsset), + newDatum + ), ]; + + return this; + } +} + +class WithdrawFixture extends Fixture { + handleName = "golddydev"; + + payouts: Payout[] = []; + ownerPubKeyHash: helios.PubKeyHash = OWNER_PUB_KEY_KEY; + + constructor(validatorHash: helios.ValidatorHash) { + super(validatorHash); + } + + async initialize() { + this.redeemer = WithdrawOrUpdate(); + const datum = buildDatum(this.payouts, this.ownerPubKeyHash); + + const handleAsset = new helios.Assets([ + [ + HANDLE_POLICY_ID, + [ + [ + `${AssetNameLabel.LBL_222}${Buffer.from(this.handleName).toString( + "hex" + )}`, + 1, + ], + ], + ], + ]); + + const fundAddress = await getAddressAtDerivation(0); + this.inputs = [ + new helios.TxInput( // money & collateral + new helios.TxOutputId(getNewFakeUtxoId()), + new helios.TxOutput(fundAddress, new helios.Value(BigInt(500_000_000))) + ), + new helios.TxInput( /// Handle NFT to withdraw + new helios.TxOutputId(getNewFakeUtxoId()), + new helios.TxOutput( + this.scriptAddress, + new helios.Value(minLovelace, handleAsset), + datum + ) + ), + ]; + + this.outputs = [ + new helios.TxOutput( + fundAddress, + new helios.Value(minLovelace, handleAsset) + ), + ]; + return this; } } -export { BuyFixture, WithdrawOrUpdateFixture }; +export { BuyFixture, UpdateFixture, WithdrawFixture }; diff --git a/src/tests/tx.test.ts b/src/tests/tx.test.ts index f8af200..b1e036b 100644 --- a/src/tests/tx.test.ts +++ b/src/tests/tx.test.ts @@ -1,5 +1,4 @@ import { buildDatumTag } from "../datum"; -import { invariant } from "../helpers"; import { adaToLovelace } from "../utils"; import { @@ -8,7 +7,7 @@ import { PAYOUT_ADDRESSES, SPAM_TOKEN_POLICY_ID, } from "./constants"; -import { BuyFixture, WithdrawOrUpdateFixture } from "./fixtures"; +import { BuyFixture, UpdateFixture, WithdrawFixture } from "./fixtures"; import * as helios from "@koralabs/helios"; import { @@ -289,41 +288,45 @@ const runTests = async (file: string) => { "First output address must be matched with payout" ); - /// --------------- WITHDRAW or UPDATE --------------- + /// --------------- UPDATE --------------- /// ---------- Should Approve ---------- - /// Withdraw await tester.test( - "Withdraw", - "can withdraw nft", + "Update", + "can update nft", new Test(program, async (hash) => { - const fixture = new WithdrawOrUpdateFixture(hash); + const fixture = new UpdateFixture(hash); fixture.payouts = [ { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; + fixture.newPayouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + ]; - invariant(fixture.owner.pubKeyHash, "Fixture owner is not valid"); - fixture.signatories = [fixture.owner.pubKeyHash]; + fixture.signatories = [fixture.ownerPubKeyHash]; return await fixture.initialize(); }) ); /// ---------- Should Deny - Owner not signed ---------- - /// Withdraw without owner signature + /// Update without owner signature await tester.test( - "Withdraw", - "can not withdraw nft, if owner not signed", + "Update", + "can not update nft, if owner not signed", new Test(program, async (hash) => { - const fixture = new WithdrawOrUpdateFixture(hash); + const fixture = new UpdateFixture(hash); fixture.payouts = [ { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; + fixture.newPayouts = [ + { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, + ]; return await fixture.initialize(); }), false, @@ -331,44 +334,38 @@ const runTests = async (file: string) => { ); /// ---------- Should Approve ---------- - /// Update + /// Withdraw await tester.test( - "Update", - "can update nft", + "Withdraw", + "can withdraw nft", new Test(program, async (hash) => { - const fixture = new WithdrawOrUpdateFixture(hash); + const fixture = new WithdrawFixture(hash); fixture.payouts = [ { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; - fixture.newPayouts = [ - { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, - ]; - invariant(fixture.owner.pubKeyHash, "Fixture owner is not valid"); - fixture.signatories = [fixture.owner.pubKeyHash]; + fixture.signatories = [fixture.ownerPubKeyHash]; return await fixture.initialize(); }) ); /// ---------- Should Deny - Owner not signed ---------- - /// Update without owner signature + /// Withdraw without owner signature await tester.test( - "Update", - "can not update nft, if owner not signed", + "Withdraw", + "can not withdraw nft, if owner not signed", new Test(program, async (hash) => { - const fixture = new WithdrawOrUpdateFixture(hash); + const fixture = new WithdrawFixture(hash); fixture.payouts = [ { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, { address: PAYOUT_ADDRESSES[1], amountLovelace: adaToLovelace(150) }, { address: PAYOUT_ADDRESSES[2], amountLovelace: adaToLovelace(80) }, ]; - fixture.newPayouts = [ - { address: PAYOUT_ADDRESSES[0], amountLovelace: adaToLovelace(100) }, - ]; + return await fixture.initialize(); }), false, diff --git a/src/types.ts b/src/types.ts index b4f6224..ddcfdd9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,7 +7,7 @@ interface Payout { interface Datum { payouts: Payout[]; - owner: helios.Address; + owner: helios.PubKeyHash; } interface Parameters { diff --git a/src/update.ts b/src/update.ts index 4e1b1bc..2b0989d 100644 --- a/src/update.ts +++ b/src/update.ts @@ -84,8 +84,7 @@ const update = async ( tx.attachScript(uplcProgram); /// add owner signature - if (!datum.owner.pubKeyHash) return Err("Owner in Datum is not correct"); - tx.addSigner(datum.owner.pubKeyHash); + tx.addSigner(datum.owner); /// build new datum const newDatum = mayFail(() => buildDatum(newPayouts, newOwner)); diff --git a/src/withdraw.ts b/src/withdraw.ts index ed444fb..54131aa 100644 --- a/src/withdraw.ts +++ b/src/withdraw.ts @@ -82,8 +82,7 @@ const withdraw = async ( tx.attachScript(uplcProgram); /// add owner signature - if (!datum.owner.pubKeyHash) return Err("Owner in Datum is not correct"); - tx.addSigner(datum.owner.pubKeyHash); + tx.addSigner(datum.owner); /// add handle withdraw output const handleWithdrawOutput = new helios.TxOutput(address, handleUtxo.value); From cb50692d507f3fb75ac7fd195e62b3b5b5c1a5cf Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Mon, 2 Sep 2024 13:38:17 +0800 Subject: [PATCH 19/20] refactor --- src/buy.ts | 26 ++++++++++++-------------- src/list.ts | 11 +++++------ src/update.ts | 20 ++++++++------------ src/withdraw.ts | 20 ++++++++------------ 4 files changed, 33 insertions(+), 44 deletions(-) diff --git a/src/buy.ts b/src/buy.ts index c2ff747..ed9c65a 100644 --- a/src/buy.ts +++ b/src/buy.ts @@ -62,9 +62,6 @@ const buy = async ( ); const networkParams = networkParamsResult.data; - /// build tx - const tx = new helios.Tx(); - /// take fund to pay payouts const minFee = 5_000_000n; const totalPayoutsLovelace = datum.payouts.reduce( @@ -79,30 +76,24 @@ const buy = async ( utxos, requiredValue ); - tx.addInputs(selected); - /// redeemer + /// make redeemer const redeemer = mayFail(() => Buy(0)); if (!redeemer.ok) return Err(`Making Redeemer error: ${redeemer.error}`); - /// collect handle NFT to buy - tx.addInput(handleUtxo, redeemer.data); - tx.attachScript(uplcProgram); - /// build datum tag const datumTag = mayFail(() => buildDatumTag(handleUtxo.outputId)); if (!datumTag.ok) return Err(`Building Datum Tag error: ${datumTag.error}`); - /// add marketplace fee + /// marketplace fee output const marketplaceFeeOutput = new helios.TxOutput( parameters.marketplaceAddress, new helios.Value(marketplaceFee), datumTag.data ); marketplaceFeeOutput.correctLovelace(networkParams); - tx.addOutput(marketplaceFeeOutput); - /// add payout outputs + /// payout outputs const payoutOutputs = datum.payouts.map( (payout) => new helios.TxOutput( @@ -111,12 +102,19 @@ const buy = async ( ) ); payoutOutputs.forEach((output) => output.correctLovelace(networkParams)); - tx.addOutputs(payoutOutputs); /// add handle buy output const handleBuyOutput = new helios.TxOutput(address, handleUtxo.value); handleBuyOutput.correctLovelace(networkParams); - tx.addOutput(handleBuyOutput); + + /// build tx + const tx = new helios.Tx() + .addInputs(selected) + .addInput(handleUtxo, redeemer.data) + .attachScript(uplcProgram) + .addOutput(marketplaceFeeOutput) + .addOutputs(payoutOutputs) + .addOutput(handleBuyOutput); /// finalize tx const txCompleteResult = await mayFailAsync(() => diff --git a/src/list.ts b/src/list.ts index ee2f8e4..1ce533d 100644 --- a/src/list.ts +++ b/src/list.ts @@ -45,6 +45,7 @@ const list = async ( const uplcProgram = uplcProgramResult.data; /// take fund and handle asset + const minFee = 5_000_000n; const handleAsset = new helios.Assets([ [ handlePolicyId, @@ -56,8 +57,6 @@ const list = async ( ], ], ]); - - const minFee = 5_000_000n; const minValue = new helios.Value(minFee, handleAsset); const selectResult = mayFail(() => helios.CoinSelection.selectLargestFirst(utxos, minValue) @@ -65,9 +64,7 @@ const list = async ( if (!selectResult.ok) return Err(selectResult.error); const [selected] = selectResult.data; - const tx = new helios.Tx(); - tx.addInputs(selected); - + /// build datum const datum = mayFail(() => buildDatum(payouts, owner)); if (!datum.ok) return Err(`Building Datum error: ${datum.error}`); @@ -78,7 +75,9 @@ const list = async ( datum.data ); handleListOutput.correctLovelace(paramter); - tx.addOutput(handleListOutput); + + /// build tx + const tx = new helios.Tx().addInputs(selected).addOutput(handleListOutput); const txCompleteResult = await mayFailAsync(() => tx.finalize(paramter, address) diff --git a/src/update.ts b/src/update.ts index 2b0989d..9afc8c6 100644 --- a/src/update.ts +++ b/src/update.ts @@ -64,28 +64,17 @@ const update = async ( ); const networkParams = networkParamsResult.data; - /// build tx - const tx = new helios.Tx(); - /// take fund const minFee = 5_000_000n; const [selected] = helios.CoinSelection.selectLargestFirst( utxos, new helios.Value(minFee) ); - tx.addInputs(selected); /// redeemer const redeemer = mayFail(() => WithdrawOrUpdate()); if (!redeemer.ok) return Err(`Making Redeemer error: ${redeemer.error}`); - /// collect handle NFT to update - tx.addInput(handleUtxo, redeemer.data); - tx.attachScript(uplcProgram); - - /// add owner signature - tx.addSigner(datum.owner); - /// build new datum const newDatum = mayFail(() => buildDatum(newPayouts, newOwner)); if (!newDatum.ok) return Err(`Building New Datum error: ${newDatum.error}`); @@ -97,7 +86,14 @@ const update = async ( newDatum.data ); handleUpdateOutput.correctLovelace(networkParams); - tx.addOutput(handleUpdateOutput); + + /// build tx + const tx = new helios.Tx() + .addInputs(selected) + .addInput(handleUtxo, redeemer.data) /// collect handle nft + .attachScript(uplcProgram) /// attach spending validator + .addSigner(datum.owner) /// sign with owner + .addOutput(handleUpdateOutput); /// updated handle output /// finalize tx const txCompleteResult = await mayFailAsync(() => diff --git a/src/withdraw.ts b/src/withdraw.ts index 54131aa..065ed49 100644 --- a/src/withdraw.ts +++ b/src/withdraw.ts @@ -62,32 +62,28 @@ const withdraw = async ( ); const networkParams = networkParamsResult.data; - /// build tx - const tx = new helios.Tx(); - /// take fund const minFee = 5_000_000n; const [selected] = helios.CoinSelection.selectLargestFirst( utxos, new helios.Value(minFee) ); - tx.addInputs(selected); /// redeemer const redeemer = mayFail(() => WithdrawOrUpdate()); if (!redeemer.ok) return Err(`Making Redeemer error: ${redeemer.error}`); - /// collect handle NFT to withdraw - tx.addInput(handleUtxo, redeemer.data); - tx.attachScript(uplcProgram); - - /// add owner signature - tx.addSigner(datum.owner); - /// add handle withdraw output const handleWithdrawOutput = new helios.TxOutput(address, handleUtxo.value); handleWithdrawOutput.correctLovelace(networkParams); - tx.addOutput(handleWithdrawOutput); + + /// build tx + const tx = new helios.Tx() + .addInputs(selected) + .addInput(handleUtxo, redeemer.data) /// collect handle nft + .attachScript(uplcProgram) /// attach spending validator + .addSigner(datum.owner) /// sign with owner + .addOutput(handleWithdrawOutput); /// finalize tx const txCompleteResult = await mayFailAsync(() => From 3e4c3934000ac8509d53bce5eeeb332de12b1d93 Mon Sep 17 00:00:00 2001 From: Golddy Dev Date: Tue, 3 Sep 2024 01:32:46 +0800 Subject: [PATCH 20/20] fix withdraw tx --- src/buy.ts | 5 ++++- src/commands/update.ts | 5 ++++- src/update.ts | 4 ++-- src/withdraw.ts | 5 ++++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/buy.ts b/src/buy.ts index ed9c65a..e6e4145 100644 --- a/src/buy.ts +++ b/src/buy.ts @@ -104,7 +104,10 @@ const buy = async ( payoutOutputs.forEach((output) => output.correctLovelace(networkParams)); /// add handle buy output - const handleBuyOutput = new helios.TxOutput(address, handleUtxo.value); + const handleBuyOutput = new helios.TxOutput( + address, + new helios.Value(0n, handleUtxo.value.assets) + ); handleBuyOutput.correctLovelace(networkParams); /// build tx diff --git a/src/commands/update.ts b/src/commands/update.ts index 3c5a439..fb46a00 100644 --- a/src/commands/update.ts +++ b/src/commands/update.ts @@ -1,5 +1,6 @@ import program from "../cli"; import { loadConfig } from "../config"; +import { invariant } from "../helpers"; import { update } from "../update"; import { adaToLovelace } from "../utils"; @@ -29,6 +30,8 @@ const updateCommand = program const newCreatorAddress = helios.Address.fromBech32( newCreatorBech32Address ); + invariant(address.pubKeyHash, "Address is invalid"); + const txResult = await update( config.blockfrostApiKey, address, @@ -44,7 +47,7 @@ const updateCommand = program amountLovelace: adaToLovelace(Number(newPriceString) * 0.1), }, ], - address, + address.pubKeyHash, config.paramters ); diff --git a/src/update.ts b/src/update.ts index 9afc8c6..81a231c 100644 --- a/src/update.ts +++ b/src/update.ts @@ -13,7 +13,7 @@ const update = async ( txHash: string, txIndex: number, newPayouts: Payout[], - newOwner: helios.Address, + newOwner: helios.PubKeyHash, parameters: Parameters ): Promise> => { const network = getNetwork(blockfrostApiKey); @@ -82,7 +82,7 @@ const update = async ( /// add handle update output const handleUpdateOutput = new helios.TxOutput( helios.Address.fromHash(uplcProgram.validatorHash), - handleUtxo.value, + new helios.Value(0n, handleUtxo.value.assets), newDatum.data ); handleUpdateOutput.correctLovelace(networkParams); diff --git a/src/withdraw.ts b/src/withdraw.ts index 065ed49..ef880cd 100644 --- a/src/withdraw.ts +++ b/src/withdraw.ts @@ -74,7 +74,10 @@ const withdraw = async ( if (!redeemer.ok) return Err(`Making Redeemer error: ${redeemer.error}`); /// add handle withdraw output - const handleWithdrawOutput = new helios.TxOutput(address, handleUtxo.value); + const handleWithdrawOutput = new helios.TxOutput( + address, + new helios.Value(0n, handleUtxo.value.assets) + ); handleWithdrawOutput.correctLovelace(networkParams); /// build tx