diff --git a/.gitignore b/.gitignore index 4393e128592b03f9f47fc2b3e5884f7647d33d24..7a7ae29fccf46a3445219c25e9b7f37c4c3c591e 100644 --- a/.gitignore +++ b/.gitignore @@ -185,7 +185,7 @@ poetry.toml pyrightconfig.json ### VisualStudioCode ### -.vscode/* +.vscode/ # Local History for Visual Studio Code .history/ @@ -230,5 +230,7 @@ storage_root-node # Ignore lock files in examples /examples/ts/**/pnpm-lock.yaml +# Ignore directory holding browser extention binaries to verify external signers (like Hive Keychain) +/examples/ts/signature-extension/__tests__/extensions .DS_Store \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 442d22493f9e29f801f94bd5ba4d34673811be83..79b97924cca59e9bdbe255b18e5b8d9d57858459 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,7 +6,7 @@ stages: include: - project: 'hive/common-ci-configuration' - ref: 5806284d3c6feb2ce52bdb6077c20a9a578bb643 + ref: 590bfd88a491efba5a39571bc2c82ffbabda2ec8 file: - '/templates/npm_projects.gitlab-ci.yml' - '/templates/wasm_build.gitlab-ci.yml' @@ -16,7 +16,7 @@ variables: GIT_DEPTH: 0 GIT_STRATEGY: clone # only build steps needs to have access to the hive submodule - GIT_SUBMODULE_STRATEGY: none + GIT_SUBMODULE_STRATEGY: normal # uses registry.gitlab.syncad.com/hive/wax/ci-base-image:ubuntu22.04-3 CI_BASE_IMAGE_TAG: "@sha256:f263bfa8a0ea40a29d99d147601171fb6320c447abc8f3ab1e9082cd51a2254a" CI_BASE_IMAGE: "registry.gitlab.syncad.com/hive/wax/ci-base-image${CI_BASE_IMAGE_TAG}" @@ -79,6 +79,7 @@ wax_wasm_proto_tsc_generation: when: always paths: - "${DIST_DIR}/*.tgz" # Built package + - "${SOURCE_DIR}/packages/*/dist" - "${REPLACE_FILE_PATH}" # Modified README - "${CI_PROJECT_DIR}/ts/wasm/lib/proto" # For documentation generator - "${CI_PROJECT_DIR}/ts/wasm/lib/build_wasm" # For documentation generator @@ -273,6 +274,7 @@ test_wax_wasm_examples: variables: SOURCE_DIR: "${CI_PROJECT_DIR}/ts" PACKAGE_TGZ_PATH: "${BUILT_PACKAGE_PATH}" + GIT_SUBMODULE_STRATEGY: "normal" script: - cd "${SOURCE_DIR}" diff --git a/core/binary_view_helper.cpp b/core/binary_view_helper.cpp index 6133f54ef9c43b2134c1ce521f11e39f294d4495..e25d2804b4c959c32ef65edb05b20408b720646d 100644 --- a/core/binary_view_helper.cpp +++ b/core/binary_view_helper.cpp @@ -288,7 +288,7 @@ uint32_t static_variant_visitor::operator()( const T& v ) const return binary_view_visitor< T >::get_size( v ); } -binary_data generate_binary_transaction_metadata( const hive::protocol::signed_transaction& tx, bool use_hf26_serialization ) +binary_data generate_binary_transaction_metadata( const hive::protocol::signed_transaction& tx, bool use_hf26_serialization /*=true*/, bool strip_to_unsigned_transaction /*= false*/ ) { const auto serialization_type = use_hf26_serialization ? hive::protocol::transaction_serialization_type::hf26 : hive::protocol::transaction_serialization_type::legacy; @@ -296,7 +296,7 @@ binary_data generate_binary_transaction_metadata( const hive::protocol::signed_t hive::protocol::serialization_mode_controller::set_pack( serialization_type ); binary_data result; - result.binary = serialize_transaction( tx, use_hf26_serialization ); + result.binary = serialize_transaction( tx, use_hf26_serialization, strip_to_unsigned_transaction ); std::vector< binary_data_node > nodes; @@ -332,13 +332,19 @@ binary_data generate_binary_operation_metadata( const hive::protocol::operation& return result; } -std::string serialize_transaction( const hive::protocol::signed_transaction& tx, bool use_hf26_serialization ) +std::string serialize_transaction( const hive::protocol::signed_transaction& tx, bool use_hf26_serialization /*=true*/, bool strip_to_unsigned_transaction /*=false*/ ) { const auto serialization_type = use_hf26_serialization ? hive::protocol::transaction_serialization_type::hf26 : hive::protocol::transaction_serialization_type::legacy; hive::protocol::serialization_mode_controller::mode_guard guard( serialization_type ); hive::protocol::serialization_mode_controller::set_pack( serialization_type ); - return fc::to_hex( fc::raw::pack_to_vector( tx ) ); + std::vector<char> binForm; + if(strip_to_unsigned_transaction) + binForm = fc::raw::pack_to_vector( static_cast<const hive::protocol::transaction&>(tx) ); + else + binForm = fc::raw::pack_to_vector( tx ); + + return fc::to_hex( binForm ); } } // namespace cpp diff --git a/core/binary_view_helper.hpp b/core/binary_view_helper.hpp index a00adeb89396d67e4935f05ab205371f525ec296..a10913e22e98736a692731970de8cc4d864f7da9 100644 --- a/core/binary_view_helper.hpp +++ b/core/binary_view_helper.hpp @@ -6,8 +6,8 @@ #include <string> namespace cpp { -binary_data generate_binary_transaction_metadata( const hive::protocol::signed_transaction& tx, bool use_hf26_serialization = true ); +binary_data generate_binary_transaction_metadata( const hive::protocol::signed_transaction& tx, bool use_hf26_serialization = true, bool strip_to_unsigned_transaction = false ); binary_data generate_binary_operation_metadata( const hive::protocol::operation& op, bool use_hf26_serialization = true ); -std::string serialize_transaction( const hive::protocol::signed_transaction& tx, bool use_hf26_serialization = true ); +std::string serialize_transaction( const hive::protocol::signed_transaction& tx, bool use_hf26_serialization = true, bool strip_to_unsigned_transaction = false ); } // namespace cpp diff --git a/core/foundation.cpp b/core/foundation.cpp index d460527a86f820aaee4022daa400a2ca8e7477d6..c58c25f150b9771b109ce691f016bfc1d7c636ef 100644 --- a/core/foundation.cpp +++ b/core/foundation.cpp @@ -269,6 +269,46 @@ private_key_data foundation::cpp_generate_private_key(const std::string& account ); } +std::string foundation::cpp_convert_raw_private_key_to_wif(const std::string& hexData) +{ + return cpp::safe_exception_wrapper( + [&]() -> std::string { + FC_ASSERT(hexData.size() == 64 && "Expected hex string pointing 32 byte buffer"); + + fc::sha256 sharedSecret(hexData); + + return fc::ecc::private_key::regenerate(sharedSecret).key_to_wif(); + } + ); +} + +std::string foundation::cpp_convert_raw_public_key_to_wif(const std::string& hexData) +{ + return cpp::safe_exception_wrapper( + [&]() -> std::string { + if(hexData.size() == 2 * sizeof(fc::ecc::public_key_data)) + { + /// compressed form + fc::ecc::public_key_data keyData; + detail::convert_from_hex(hexData, keyData); + + return fc::ecc::public_key::to_base58_with_prefix(keyData, HIVE_ADDRESS_PREFIX); + + } + else + { + FC_ASSERT(hexData.size() == 2 * sizeof(fc::ecc::public_key_point_data), "Invalid size of raw public key buffer: ${s}", ("s", (hexData.size()))); + /// uncompressed form + fc::ecc::public_key_point_data keyData; + detail::convert_from_hex(hexData, keyData); + + fc::ecc::public_key key(keyData); + return key.to_base58_with_prefix(HIVE_ADDRESS_PREFIX); + } + } + ); +} + brain_key_data foundation::cpp_suggest_brain_key() { return cpp::safe_exception_wrapper( diff --git a/core/foundation.hpp b/core/foundation.hpp index e7c05541b926b2b9c5c5e534c6cceb158acd79dd..e2c17b5925c89834721104aa0c062ca6d569b663 100644 --- a/core/foundation.hpp +++ b/core/foundation.hpp @@ -15,8 +15,16 @@ public: result cpp_calculate_public_key(const std::string& wif); result cpp_generate_private_key(); - private_key_data cpp_generate_private_key(const std::string& account, const std::string& role, const std::string& password); + /** Allows to convert 32 bytes data buffer expressed as hex string (pointing private key secret) into private key encoded as WIF format. + */ + std::string cpp_convert_raw_private_key_to_wif(const std::string& hexData); + + /** Allows to convert raw public key form (expressed as hex string) into Hive WIF format (with prefix). + * \param hexData - depending on length compressed or uncompressed key format is chosen + */ + std::string cpp_convert_raw_public_key_to_wif(const std::string& hexData); + brain_key_data cpp_suggest_brain_key(); /** Returns map of hive::protocol constants in form: diff --git a/core/protobuf_protocol_impl.hpp b/core/protobuf_protocol_impl.hpp index 61a51ef300898e16429aad6e15650187f16bc780..e5084fa1cb3939c5ec6003a1569ba5502474de2a 100644 --- a/core/protobuf_protocol_impl.hpp +++ b/core/protobuf_protocol_impl.hpp @@ -19,7 +19,7 @@ public: std::vector<std::string> cpp_operation_get_impacted_accounts(const std::string& operation) const; std::vector<std::string> cpp_transaction_get_impacted_accounts(const std::string& transaction) const; - binary_data cpp_generate_binary_transaction_metadata(const std::string& transaction, bool use_hf26_serialization)const; + binary_data cpp_generate_binary_transaction_metadata(const std::string& transaction, bool use_hf26_serialization, bool strip_to_unsigned_transaction)const; binary_data cpp_generate_binary_operation_metadata(const std::string& operation, bool use_hf26_serialization)const; result cpp_validate_operation(const std::string& operation); @@ -28,7 +28,7 @@ public: result cpp_calculate_legacy_transaction_id(const std::string& transaction); result cpp_calculate_sig_digest(const std::string& transaction, const std::string& chain_id); result cpp_calculate_legacy_sig_digest(const std::string& transaction, const std::string& chain_id); - result cpp_serialize_transaction(const std::string& transaction); + result cpp_serialize_transaction(const std::string& transaction, bool strip_to_unsigned_transaction); result cpp_deserialize_transaction(const std::string& transaction); required_authority_collection_t cpp_collect_transaction_required_authorities(const std::string& transaction); diff --git a/core/protobuf_protocol_impl.inl b/core/protobuf_protocol_impl.inl index 40784363d9127e51d638f639e6b3ae9eabe744f8..d61093f0a835a6befa650af4ab45eb8980b08a16 100644 --- a/core/protobuf_protocol_impl.inl +++ b/core/protobuf_protocol_impl.inl @@ -480,13 +480,14 @@ std::vector<std::string> proto_protocol_impl<FoundationProvider>::cpp_transactio } template <class FoundationProvider> -binary_data proto_protocol_impl<FoundationProvider>::cpp_generate_binary_transaction_metadata(const std::string& transaction, bool use_hf26_serialization) const +binary_data proto_protocol_impl<FoundationProvider>::cpp_generate_binary_transaction_metadata(const std::string& transaction, bool use_hf26_serialization, bool strip_to_unsigned_transaction) const { protocol_impl<FoundationProvider> provider; return provider.cpp_generate_binary_transaction_metadata( cpp_proto_to_api_impl(transaction), - use_hf26_serialization + use_hf26_serialization, + strip_to_unsigned_transaction ); } @@ -585,13 +586,14 @@ typename proto_protocol_impl<FoundationProvider>::required_authority_collection_ } template <class FoundationProvider> -result proto_protocol_impl<FoundationProvider>::cpp_serialize_transaction(const std::string& transaction) +result proto_protocol_impl<FoundationProvider>::cpp_serialize_transaction(const std::string& transaction, bool strip_to_unsigned_transaction) { return method_wrapper([&](result& _result) { protocol_impl<FoundationProvider> provider; _result = provider.cpp_serialize_transaction( - cpp_proto_to_api_impl(transaction) + cpp_proto_to_api_impl(transaction), + strip_to_unsigned_transaction ); }); } diff --git a/core/protocol_impl.hpp b/core/protocol_impl.hpp index 83ba9ea5514ea306f0c07f1e0a7f8b5c152f86b7..8ea6d72b537268eeaa5a360d4fa57eaf73cefc82 100644 --- a/core/protocol_impl.hpp +++ b/core/protocol_impl.hpp @@ -38,7 +38,7 @@ public: std::vector<std::string> cpp_operation_get_impacted_accounts(const std::string& operation) const; std::vector<std::string> cpp_transaction_get_impacted_accounts(const std::string& transaction) const; - binary_data cpp_generate_binary_transaction_metadata(const std::string& transaction, bool use_hf26_serialization)const; + binary_data cpp_generate_binary_transaction_metadata(const std::string& transaction, bool use_hf26_serialization, bool strip_to_unsigned_transaction)const; binary_data cpp_generate_binary_operation_metadata(const std::string& operation, bool use_hf26_serialization)const; result cpp_validate_operation(const std::string& operation); @@ -59,8 +59,11 @@ public: /** Allows to perform binary serialization of specified transaction. * Uses HF26 serialization form. + * + * @param transaction - JSON form of transaction to serialize + * @param strip_to_unsigned_transaction - if true, then only unsigned part of transaction will be serialized (signature container is always stripped) */ - result cpp_serialize_transaction(const std::string& transaction); + result cpp_serialize_transaction(const std::string& transaction, bool strip_to_unsigned_transaction); /** Allows to restore a transaction object from HF26 binary serialization form. * Returns a JSON form of deserialized transaction. diff --git a/core/protocol_impl.inl b/core/protocol_impl.inl index f7c76b824a5ed64722d4ab9e9b53830cd96a5763..6c536720c43010fda0679136aaa1cb4adbb2ab73 100644 --- a/core/protocol_impl.inl +++ b/core/protocol_impl.inl @@ -71,13 +71,13 @@ std::vector<std::string> protocol_impl<FoundationProvider>::cpp_transaction_get_ template <class FoundationProvider> inline -binary_data protocol_impl<FoundationProvider>::cpp_generate_binary_transaction_metadata(const std::string& transaction, bool use_hf26_serialization) const +binary_data protocol_impl<FoundationProvider>::cpp_generate_binary_transaction_metadata(const std::string& transaction, bool use_hf26_serialization, bool strip_to_unsigned_transaction) const { fc::variant _v = fc::json::from_string(transaction, fc::json::format_validation_mode::full); hive::protocol::signed_transaction _transaction = _v.as<hive::protocol::signed_transaction>(); - return cpp::generate_binary_transaction_metadata(_transaction, use_hf26_serialization); + return cpp::generate_binary_transaction_metadata(_transaction, use_hf26_serialization, strip_to_unsigned_transaction); } template <class FoundationProvider> @@ -120,7 +120,8 @@ result protocol_impl<FoundationProvider>::cpp_calculate_transaction_id(const std { return method_wrapper([&](result& _result) { - _result.content = get_transaction(transaction).id(hive::protocol::transaction_serialization_type::hf26).str(); + const auto txId = get_transaction(transaction).id(hive::protocol::transaction_serialization_type::hf26); + _result.content = txId.str(); }); } @@ -162,13 +163,13 @@ result protocol_impl<FoundationProvider>::cpp_calculate_legacy_sig_digest(const template <class FoundationProvider> inline -result protocol_impl<FoundationProvider>::cpp_serialize_transaction(const std::string& transaction) +result protocol_impl<FoundationProvider>::cpp_serialize_transaction(const std::string& transaction, bool strip_to_unsigned_transaction) { return method_wrapper([&](result& _result) { const auto _transaction = get_transaction(transaction); - _result.content = serialize_transaction(_transaction); + _result.content = serialize_transaction(_transaction, true, strip_to_unsigned_transaction); }); } diff --git a/examples/ts/signature-extension/.npmrc b/examples/ts/signature-extension/.npmrc new file mode 100644 index 0000000000000000000000000000000000000000..c09005dcafaf54825a5384138afaedffb19ae8f5 --- /dev/null +++ b/examples/ts/signature-extension/.npmrc @@ -0,0 +1,2 @@ +# https://gitlab.syncad.com/hive group specification, offering aggregated package view: https://gitlab.syncad.com/groups/hive/-/packages +@hiveio:registry=https://gitlab.syncad.com/api/v4/groups/136/-/packages/npm/ diff --git a/examples/ts/signature-extension/.parcelrc b/examples/ts/signature-extension/.parcelrc new file mode 100644 index 0000000000000000000000000000000000000000..7c4c7db424f573add53a3a190dc03a3b72c55fb1 --- /dev/null +++ b/examples/ts/signature-extension/.parcelrc @@ -0,0 +1,6 @@ +{ + "extends": "@parcel/config-default", + "transformers": { + "*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"] + } +} \ No newline at end of file diff --git a/examples/ts/signature-extension/README.md b/examples/ts/signature-extension/README.md new file mode 100644 index 0000000000000000000000000000000000000000..541bcdda5f0fb92bba5d8d9d37955d3c47922458 --- /dev/null +++ b/examples/ts/signature-extension/README.md @@ -0,0 +1,15 @@ +# signature-extension + +> [!WARNING] +> This example will not be ran automatically on the CI as it requires direct user action, e.g. OAuth 3rd party app Hive blockchain user authorization + +This example presents different ways of implementing 3rd party apps authorization using wax + +To test this example: + +1. Install keychain/PeakVault extension +2. Configure wallets by adding an alternative node specific to mirrornet instance having chainID: 4200000000000000000000000000000000000000000000000000000000000000 and API endpoint: https://api.fake.openhive.network +3. Import `keychainsigner` posting key to your wallet (it is printed on the page) +4. Install dependencies: `pnpm install` +5. Run parcel: `pnpm test:manual` +6. Goto [http://localhost:1234](http://localhost:1234), sign the transaction and check logs diff --git a/examples/ts/signature-extension/__tests__/assets/fixture.ts b/examples/ts/signature-extension/__tests__/assets/fixture.ts new file mode 100644 index 0000000000000000000000000000000000000000..30e4aa430be9cd633276e08c50e8b1f7a3f7f708 --- /dev/null +++ b/examples/ts/signature-extension/__tests__/assets/fixture.ts @@ -0,0 +1,39 @@ +import { chromium, test as base, type BrowserContext } from "@playwright/test"; +import { dirname } from "path"; +import { fileURLToPath } from "url"; + +import { type TTestAccountAuthorityData, prepareTestingEnvironemnt } from "../../common-data"; + +export const test = base.extend<{ + context: BrowserContext, + extensionId: string + ,baseDirectoryPath: string + ,testedAccountAuthorityData: TTestAccountAuthorityData +}>({ + context: async ({}, use) => { + console.log('Launched browser'); + const browserContext = await chromium.launchPersistentContext(''); + + console.log('Before use browserContext'); + await use(browserContext); + + console.log('Attempting to close browserContext'); + await browserContext.close(); + }, + extensionId: async ({ context }, use) => { + let [background] = context.serviceWorkers(); + if (!background) + background = await context.waitForEvent('serviceworker'); + + const extensionId = background.url().split('/')[2]; + await use(extensionId); + }, + baseDirectoryPath: async ({}, use) => { + const __dirname = dirname(fileURLToPath(import.meta.url)); + await use(__dirname); + }, + testedAccountAuthorityData: async ({}, use) => { + const data = await prepareTestingEnvironemnt(); + await use(data); + } +}); diff --git a/examples/ts/signature-extension/__tests__/assets/settings.kc b/examples/ts/signature-extension/__tests__/assets/settings.kc new file mode 100644 index 0000000000000000000000000000000000000000..68bc778b6cda6648718cccd289abbb6252e65094 --- /dev/null +++ b/examples/ts/signature-extension/__tests__/assets/settings.kc @@ -0,0 +1 @@ +{"current_rpc":{"chainId":"4200000000000000000000000000000000000000000000000000000000000000","testnet":true,"uri":"https://api.fake.openhive.network"},"rpc":[{"chainId":"4200000000000000000000000000000000000000000000000000000000000000","testnet":true,"uri":"https://api.fake.openhive.network"}],"switchRpcAuto":false} \ No newline at end of file diff --git a/examples/ts/signature-extension/__tests__/index.spec.ts b/examples/ts/signature-extension/__tests__/index.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ab0592ea8231ac4453d2e8497a5ec90f440d497 --- /dev/null +++ b/examples/ts/signature-extension/__tests__/index.spec.ts @@ -0,0 +1,102 @@ +import { test } from "./assets/fixture"; +import { expect, Page } from "@playwright/test"; + +test.describe('Signature extension tests', () => { + test('Should be able to sign transction using key chain extension.', async ({ page, extensionId, context, baseDirectoryPath, testedAccountAuthorityData}) => { + page.setViewportSize({ width: 500, height: 700 }); + + //////////////// Import settings begin (containing mirrornet endpoint configuration) + + const settingFilePath = baseDirectoryPath + '/' + 'settings.kc'; + + console.log(`Attempting to import settings from: ${settingFilePath}`); + + await page.goto(`chrome-extension://${extensionId}/import-preferences.html`, { waitUntil: 'load' }); + + page.once('filechooser', async fileChooser => { + await fileChooser.setFiles(settingFilePath); + } + ); + + await page.getByRole('button', { name: 'Choose a file' }).click(); + + await page.getByRole('button', { name: 'Import' }).click(); + + //////////////// Import settings end + + await page.goto(`chrome-extension://${extensionId}/popup.html`, { waitUntil: 'load' }); + const input = page.getByPlaceholder('New Password'); + const confirm = page.getByPlaceholder('Confirm'); + await input.fill('Password123'); + await confirm.fill('Password123'); + const checkbox = page.locator('#accept-terms-and-condition-inner-input'); + await checkbox.click(); + + const button = page.getByTestId('signup-button'); + await button.click(); + const useButton = page.getByTestId('add-by-keys-button'); + await useButton.click(); + const usernameInput = page.getByPlaceholder('Username'); + await usernameInput.fill(testedAccountAuthorityData.accountName); + const privateKeyInput = page.getByPlaceholder('Private Key '); + await privateKeyInput.fill(testedAccountAuthorityData.privateKey); + + const submitButton = page.getByTestId('submit-button'); + await submitButton.click(); + const skip = page.getByText('Skip'); + + await skip.waitFor(); + await skip.click(); + + /// Regular keychain setup completed + + const testPage: Page = page; + + await testPage.goto('localhost:1234', { waitUntil: 'load' }); + + /// uncomment to allow debugging and recording while playwright performs actions + //await page.pause(); + + console.log("Acquiring a popupPromise"); + + const popupPromise = context.waitForEvent('page'); + + const keyChainButton = testPage.getByRole('button', {name: 'Use Keychain'}); + await keyChainButton.waitFor(); + + console.log("Attempting to press 'Use keychain'"); + + await keyChainButton.focus(); + await keyChainButton.click({delay: 750}); + + console.log("Awaiting popupPromise"); + + const popup = await popupPromise; + console.log("new popup detected"); + console.log("Looking for Confirm button"); + const popupSubmitButton = popup.getByRole('button', {name: 'Confirm'}); + await popupSubmitButton.waitFor(); + console.log("Attempting to click Confirm button"); + await popupSubmitButton.focus(); + await popupSubmitButton.click({delay: 750}); + + console.log("Attempting to wait for form close"); + await popup.waitForEvent('close'); + + console.log("waitForTimeout(500);"); + await testPage.waitForTimeout(500); + + console.log("waitForSelector"); + + const keyMatchState = await testPage.waitForSelector("#key-matching-result"); + const keyMatchText = await keyMatchState.textContent() as string; + + const result = await testPage.waitForSelector('#tx-result'); + const tx = JSON.parse(await result.textContent() as string); + + //await page.pause(); + + expect(tx.signatures).toHaveLength(1); + expect(keyMatchText).toBe('Decoded and signing key match. Remote endpoint accepted transaction authority. Transaction has been signed using: HF26 serialization form'); + }); +}); \ No newline at end of file diff --git a/examples/ts/signature-extension/common-data.ts b/examples/ts/signature-extension/common-data.ts new file mode 100644 index 0000000000000000000000000000000000000000..6f18b945feb62547f39945605e48c59a3a21201e --- /dev/null +++ b/examples/ts/signature-extension/common-data.ts @@ -0,0 +1,111 @@ +import { type account_create, createHiveChain, IHiveChainInterface, TAccountName, TPublicKey } from "@hiveio/wax"; +import createBeekeeper, {IBeekeeperUnlockedWallet} from "@hiveio/beekeeper"; + +const testAccountName = "keychainsigner"; +const testAccountPostingKey = "5J7cSrAhgnAWe2uQqTTPhb7BggUeKjuLS8AFPpn53Yv7mFYHo53"; + +export const voteData = { + voter: testAccountName, + author: "c0ff33a", + permlink: "ewxhnjbj", + weight: 2200 +}; + +export interface TTestAccountAuthorityData { + accountName: TAccountName; + publicKey: TPublicKey; + privateKey: string; + role: string; +}; + +export interface TTestEnvData extends TTestAccountAuthorityData { + accountName: TAccountName; + publicKey: TPublicKey; + privateKey: string; + role: string; + configuredChain: IHiveChainInterface; + preparedBeekeeperWallet: IBeekeeperUnlockedWallet; +}; + +const mirrornetSkeletonKey = '5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n'; + + +//owner: 5KYoVXJ9oPCQXXPXbyec5BABxappnnRNxZGvGDSujJ7caR6szCj +//active: 5JaodMcwGiuYd53Hf1gGE7AmXS9KrW5hTeTAe9HakjJ4F3Jsg2h +//posting: 5J7cSrAhgnAWe2uQqTTPhb7BggUeKjuLS8AFPpn53Yv7mFYHo53 +//memo: 5JsJ6rcbZSLM4MrvhCkWAY88Hn8Ci5nhNLapbpLXUemtUAwGHcd + +/// Intent of this script is automatically prepare testing account in case of mirrornet reset. +export const prepareTestingEnvironemnt = async (): Promise<TTestEnvData> => { + const chain = await createHiveChain({chainId: "4200000000000000000000000000000000000000000000000000000000000000", apiEndpoint: "https://api.fake.openhive.network"}); + + const beekeeperInstance = await createBeekeeper({inMemory: true}); + const session = beekeeperInstance.createSession("salt and pepper"); + + const {wallet} = await session.createWallet("temp-wallet", "somePass", true); + const mirrornetSkeletonPublicKey = await wallet.importKey(mirrornetSkeletonKey); + const testAccountPublicKey = await wallet.importKey(testAccountPostingKey); + + let accountData = await chain.api.database_api.find_accounts({accounts: [testAccountName], delayed_votes_active: true}); + + if(accountData.accounts.length === 0) { + console.log(`Account: ${testAccountName} not found. Attempting to create it...`) + + const ownerKeyData = chain.getPrivateKeyFromPassword(testAccountName, "owner", mirrornetSkeletonKey); + const activeKeyData = chain.getPrivateKeyFromPassword(testAccountName, "active", mirrornetSkeletonKey); + const postingKeyData = chain.getPrivateKeyFromPassword(testAccountName, "posting", mirrornetSkeletonKey); + const memoKeyData = chain.getPrivateKeyFromPassword(testAccountName, "memo", mirrornetSkeletonKey); + + console.log("Generated keys for account: ${testAccountName}:", ownerKeyData.wifPrivateKey, activeKeyData, postingKeyData, memoKeyData); + console.log("owner:", ownerKeyData.wifPrivateKey); + console.log("active:", activeKeyData.wifPrivateKey); + console.log("posting:", postingKeyData.wifPrivateKey); + console.log("memo:", memoKeyData.wifPrivateKey); + + const ownerAuthorityKeyAuths: Record<string, number> = {}; + ownerAuthorityKeyAuths[ownerKeyData.associatedPublicKey] = 1; + ownerAuthorityKeyAuths[mirrornetSkeletonPublicKey] = 1; + + const activeAuthorityKeyAuths: Record<string, number> = {}; + activeAuthorityKeyAuths[activeKeyData.associatedPublicKey] = 1; + + const postingAuthorityKeyAuths: Record<string, number> = {}; + postingAuthorityKeyAuths[postingKeyData.associatedPublicKey] = 1; + + const tx = await chain.createTransaction(); + + const operationBody: account_create = { + fee: chain.hiveCoins(3), + creator: "blocktrades", + new_account_name: testAccountName, + owner: {weight_threshold: 1, account_auths: {}, key_auths: ownerAuthorityKeyAuths}, + active: {weight_threshold: 1, account_auths: {}, key_auths: activeAuthorityKeyAuths}, + posting: {weight_threshold: 1, account_auths: {}, key_auths: postingAuthorityKeyAuths}, + memo_key: memoKeyData.associatedPublicKey, + json_metadata: '{"description": "Account created for Wax keychain signer extension testing purposes"}' + }; + + tx.pushOperation({account_create: operationBody}); + tx.sign(wallet, mirrornetSkeletonPublicKey); + + await chain.broadcast(tx); + + console.log(`Account: ${testAccountName} created successfully!`); + + await new Promise(resolve => setTimeout(resolve, 4000)); /// naive way to wait for transaction completed + + accountData = await chain.api.database_api.find_accounts({accounts: [testAccountName], delayed_votes_active: true}); + } + + console.log(`Received account info: ${JSON.stringify(accountData)}`); + + return { + accountName: testAccountName, + publicKey: testAccountPublicKey, + privateKey: testAccountPostingKey, + role: "posting", + configuredChain: chain, + preparedBeekeeperWallet: wallet + }; + +}; diff --git a/examples/ts/signature-extension/package.json b/examples/ts/signature-extension/package.json new file mode 100644 index 0000000000000000000000000000000000000000..196a4df0f7b74f945d527d8ca95d0a45ca3e25b2 --- /dev/null +++ b/examples/ts/signature-extension/package.json @@ -0,0 +1,26 @@ +{ + "name": "signature-extension", + "version": "1.0.0", + "type": "module", + "scripts": { + "build": "tsc", + "test": "../../../ts/npm-common-config/scripts/bash/npm-helpers/npm_download_browser_extensions.sh \"${HOME}/preinstalled_browser_extensions\" && ln -sf \"${HOME}/preinstalled_browser_extensions\" ./__tests__/extensions && playwright install chromium && playwright test --max-failures 1", + "test:manual": "parcel test/index.html" + }, + "dependencies": { + "@hiveio/wax": "file:../../../ts", + "@hiveio/wax-signers-keychain": "file:../../../ts/packages/signers-keychain", + "@hiveio/wax-signers-peakvault": "file:../../../ts/packages/signers-peakvault", + "@hiveio/beekeeper": "1.27.10-stable.250305202831" + }, + "devDependencies": { + "@parcel/config-default": "^2.13.3", + "@parcel/transformer-typescript-tsc": "^2.13.3", + "@playwright/test": "1.50.1", + "@types/node": "^22.13.9", + "buffer": "^5.5.0||^6.0.0", + "parcel": "^2.13.3", + "process": "^0.11.10" + }, + "packageManager": "pnpm@10.0.0+sha512.b8fef5494bd3fe4cbd4edabd0745df2ee5be3e4b0b8b08fa643aa3e4c6702ccc0f00d68fa8a8c9858a735a0032485a44990ed2810526c875e416f001b17df12b" +} diff --git a/examples/ts/signature-extension/playwright.config.ts b/examples/ts/signature-extension/playwright.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..3cb78ea291b09b0d58ff963b6817e001702c1037 --- /dev/null +++ b/examples/ts/signature-extension/playwright.config.ts @@ -0,0 +1,33 @@ +import { defineConfig, devices } from '@playwright/test'; + +import path, { dirname } from "path"; +import { fileURLToPath } from "url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const pathToExtension = path.join(__dirname, "./__tests__/extensions/Hive-Keychain"); + +console.log(`Effective extension directory: ${pathToExtension}`); + + +export default defineConfig({ + testDir: './__tests__', + + projects: [ + { + name: 'keychain signing tests', + use: { ...devices['Desktop Chrome'], channel: 'chromium', + launchOptions: { + args: [ + `--load-extension=${pathToExtension}` + ,`--disable-extensions-except=${pathToExtension}` + ], + ignoreDefaultArgs: ['--disable-component-extensions-with-background-pages'], + }, + }, + }, + ], + + webServer: { + command: 'npm run test:manual' + } +}); diff --git a/examples/ts/signature-extension/test/index.html b/examples/ts/signature-extension/test/index.html new file mode 100644 index 0000000000000000000000000000000000000000..29d00f36341a43c4270e27c6df4248d9439b4d3d --- /dev/null +++ b/examples/ts/signature-extension/test/index.html @@ -0,0 +1,108 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> +</head> +<body> + <h1>Signing example operating on official HIVE MIRRORNET instance, available at: https://api.fake.openhive.network</h1> + <h3>In order to successfully run this example, you need to properly configure wallets (i.e. Hive Keychain) you want to work with.</h3> + <h3>Wallets should have set above mirrornet instance node and 4200000000000000000000000000000000000000000000000000000000000000 as chainID.</h3> + <h3>Remember to unlock Peak Vault before using it...</h3> + + <button onclick="useKeychain()">Use Keychain</button> + <button onclick="usePeakVault()">Use Peak Vault</button> + <button onclick="useBeekeeper()">Use Beekeeper</button> + + <pre><code id="operating-private-key"></code></pre> + <pre><code id="tx-result"></code></pre> + <pre><code id="key-matching-result"></code></pre> + + <script type="module"> + import { createHiveChain } from "@hiveio/wax"; + import { prepareTestingEnvironemnt, voteData } from "../common-data"; + import KeychainProvider from "@hiveio/wax-signers-keychain"; + import PeakVaultProvider from "@hiveio/wax-signers-peakvault"; + + const txResult = document.getElementById('tx-result'); + const operatingPrivateKeyPlaceholder = document.getElementById('operating-private-key'); + const keyMatchingPlaceholder = document.getElementById('key-matching-result'); + + (async()=> { + const testEnv = await prepareTestingEnvironemnt(); + const accountName = testEnv.accountName; + const keychainProvider = KeychainProvider.for(accountName, testEnv.role); + const peakVaultProvider = PeakVaultProvider.for(accountName, testEnv.role); + const beekeeperProvider = testEnv.preparedBeekeeperWallet; + + operatingPrivateKeyPlaceholder.textContent = `${accountName}@${testEnv.role} private key to be imported to wallets: ${testEnv.privateKey}`; + + const chain = testEnv.configuredChain; + + const createTransaction = async () => { + txResult.textContent = 'Signing...'; + + const tx = await chain.createTransaction(); + tx.pushOperation({ + vote: voteData + }); + + console.log(tx.toApi()); + console.log(`Sig digest: ${tx.sigDigest}`); + console.log(`Legacy Sig digest: ${tx.legacy_sigDigest}`); + return tx; + }; + + const verifySignature = async (tx) => { + try { + const apiJson = tx.toApi(); + console.log('Transaction:', apiJson); + const hf26SerializationMatch = tx.signatureKeys[0] === testEnv.publicKey; + const legacySerializationMatch = tx.legacy_signatureKeys[0] === testEnv.publicKey; + + if(hf26SerializationMatch || legacySerializationMatch) { + const verifyAuthorityResult = await chain.api.database_api.verify_authority({trx: tx.toApiJson(), pack: legacySerializationMatch? 'legacy' : 'hf26'}); + + keyMatchingPlaceholder.textContent = `Decoded and signing key match. Remote endpoint ${verifyAuthorityResult.valid? "accepted" : "REJECTED"} transaction authority. Transaction has been signed using: ${hf26SerializationMatch? 'HF26' : 'Legacy'} serialization form`; + } + else + keyMatchingPlaceholder.textContent = `Error: Keys decoded from signature: ${tx.signatureKeys[0]}, ${tx.legacy_signatureKeys[0]} DO NOT MATCH signer key: ${testEnv.publicKey}`; + + txResult.textContent = apiJson; + } catch (error) { + console.error(error); + txResult.textContent = `Verify authority faiure. Error: ${error.message}`; + } + } + + const sign = async (provider) => { + try { + console.log("Atttempting to create & sign transaction..."); + const tx = await createTransaction(); + await tx.sign(provider); + await verifySignature(tx); + } catch (error) { + console.error(error); + txResult.textContent = `Error: ${error.message}`; + } + }; + + const beekeeperSign = async (provider) => { + try { + const tx = await createTransaction(); + await tx.sign(provider, testEnv.publicKey); + await verifySignature(tx); + } catch (error) { + console.error(error); + txResult.textContent = `Error: ${error.message}`; + } + }; + + + window.useKeychain = () => void sign(keychainProvider); + window.usePeakVault = () => void sign(peakVaultProvider); + window.useBeekeeper = () => void beekeeperSign(beekeeperProvider); + })(); + </script> +</body> +</html> diff --git a/examples/ts/signature-extension/tsconfig.json b/examples/ts/signature-extension/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..f5fe061f8d3b842c6efc6a6fa571b0f9b13dc861 --- /dev/null +++ b/examples/ts/signature-extension/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../ts/tsconfig.json", + "compilerOptions": { + "rootDir": ".", + "baseUrl": ".", + "outDir": "dist" + }, + "include": [ + "." + ] +} \ No newline at end of file diff --git a/python/cpp_python_bridge.pxd b/python/cpp_python_bridge.pxd index 45f7556dc2dd6054e96adcb48bd862610fcc8d9f..08c5064f87d789693e222fed2bfd096c23e05097 100644 --- a/python/cpp_python_bridge.pxd +++ b/python/cpp_python_bridge.pxd @@ -144,7 +144,7 @@ cdef extern from "cpython_interface.hpp" namespace "cpp": result cpp_calculate_legacy_transaction_id( string transaction ) result cpp_calculate_sig_digest( string transaction, string chain_id ) result cpp_calculate_legacy_sig_digest( string transaction, string chain_id ) - result cpp_serialize_transaction( string transaction ) + result cpp_serialize_transaction( string transaction, bool strip_to_unsigned_transaction ) result cpp_deserialize_transaction( string transaction ) result cpp_calculate_public_key( string wif ) result cpp_generate_private_key() @@ -189,7 +189,7 @@ cdef extern from "cpython_interface.hpp" namespace "cpp": result cpp_calculate_legacy_transaction_id( string transaction ) result cpp_calculate_sig_digest( string transaction, string chain_id ) result cpp_calculate_legacy_sig_digest( string transaction, string chain_id ) - result cpp_serialize_transaction( string transaction ) + result cpp_serialize_transaction( string transaction, bool strip_to_unsigned_transaction ) result cpp_deserialize_transaction( string transaction ) result cpp_proto_to_api( string operation_or_tx ) result cpp_proto_to_legacy_api( string operation_or_tx ) diff --git a/python/cpp_python_bridge.pyx b/python/cpp_python_bridge.pyx index f5045a378cdad4821d21fb92eee135e2596a7f6c..e32bc31a25c396e3f8e60e681df6db8853ad5025 100644 --- a/python/cpp_python_bridge.pyx +++ b/python/cpp_python_bridge.pyx @@ -28,6 +28,7 @@ from .wax_result import ( python_price, python_authority, python_authorities, + python_minimize_required_signatures_data, ) def return_python_result(foo): @@ -116,7 +117,7 @@ def get_public_key_from_signature(digest: bytes, signature: bytes) -> python_res @return_python_result def serialize_transaction(transaction: bytes) -> python_result: cdef protocol obj - response = obj.cpp_serialize_transaction(transaction) + response = obj.cpp_serialize_transaction(transaction, False) return response.value, response.content, response.exception_message @return_python_result @@ -326,7 +327,7 @@ def calculate_proto_legacy_sig_digest(transaction: bytes, chain_id: bytes) -> py @return_python_result def serialize_proto_transaction(transaction: bytes) -> python_result: cdef proto_protocol obj - response = obj.cpp_serialize_transaction( transaction ) + response = obj.cpp_serialize_transaction( transaction, False ) return response.value, response.content, response.exception_message @return_python_result diff --git a/python/tests/proto-protocol/test_proto_to_legacy_api.py b/python/tests/proto-protocol/test_proto_to_legacy_api.py index cdd3e376ae1c915e8feae64548ad5571a8587aca..4ae7f07afe583adb1669ef876589cde8da6bcd52 100644 --- a/python/tests/proto-protocol/test_proto_to_legacy_api.py +++ b/python/tests/proto-protocol/test_proto_to_legacy_api.py @@ -44,5 +44,5 @@ def test_op_proto_to_legacy_api(): b'var.is_object()\n' b'cpp_proto_to_legacy_api requires JSON object as an argument\n' b' {}\n' - b' protobuf_protocol_impl.inl:625 operator()' + b' protobuf_protocol_impl.inl:627 operator()' ) diff --git a/ts/README.md b/ts/README.md index 005a0ac874185f934aa6c52b68da7470d8ed0a22..e2e3993178d54cc271a1d839e2f0ff55715d2dc1 100644 --- a/ts/README.md +++ b/ts/README.md @@ -187,54 +187,6 @@ const manaTime = await chain.calculateManabarFullRegenerationTimeForAccount("ini console.info(manaTime); // Date ``` -#### Extend API interface and call custom endpoints - -In this example we will extend the base Wax endpoints and create our classes with validators -in order to use the [transaction_status_api.find_transaction](https://developers.hive.io/apidefinitions/#transaction_status_api.find_transaction) API: - -```ts -import { IsHexadecimal, IsDateString, IsString } from 'class-validator'; -import { createHiveChain, TWaxExtended } from '@hiveio/wax'; -const chain = await createHiveChain(); - -// https://developers.hive.io/apidefinitions/#transaction_status_api.find_transaction-parameter_json -// Create a request class with validators that will require a valid input from the end user -class FindTransactionRequest { - @IsHexadecimal() - public transaction_id!: string; - - @IsDateString() - public expiration!: string; -} - -// https://developers.hive.io/apidefinitions/#transaction_status_api.find_transaction-expected_response_json -// Create a response class with validators that will require a valid output from the remote API -class FindTransactionResponse { - @IsString() - public status!: 'unknown' | string; -} - -// Create the proper API structure -const ExtendedApi = { - transaction_status_api: { // API - find_transaction: { // Method - params: FindTransactionRequest, // params is our request - result: FindTransactionResponse // result is out response - } - } -}; - -const extended: TWaxExtended<typeof ExtendedApi> = chain.extend(ExtendedApi); - -// Call the transaction_status_api API using our extended interface -const result = await extended.api.transaction_status_api.find_transaction({ - transaction_id: "0000000000000000000000000000000000000000", - expiration: "2016-03-24T18:00:21" -}); - -console.info(result); // { status: 'unknown' } -``` - #### Extend API interface using interfaces only and call custom endpoints In this example we will extend the base Wax endpoints without creating any validators. @@ -275,42 +227,6 @@ const result = await extended.api.transaction_status_api.find_transaction({ console.info(result); // { status: 'unknown' } ``` -#### Extend REST API interface and call custom endpoints - -In this example we will extend REST API Wax endpoints and create our classes with validators -in order to use the [hafah_endpoints.get_transaction](https://api.syncad.com/?urls.primaryName=HAfAH#/Transactions/hafah_endpoints.get_transaction) API: - -```ts -import { IsHexadecimal } from 'class-validator'; -import { createHiveChain, TWaxRestExtended } from '@hiveio/wax'; -const chain = await createHiveChain(); - -class TransactionByIdRequest { - @IsHexadecimal() - public transactionId!: string; -} - -// Create the proper API structure -const ExtendedRestApi = { - 'hafah-api': { // API type - structure-like - pushed to the query path during call - transactions: { // method name - also pushed to the query path during call - byId: { // next query path to be added. It will be replaced though due to the urlPath property defined - params: TransactionByIdRequest, // params is our request - result: Number, // result is our response (Number is a NumberConstructor - we cannot use number as a type in this context, so we pass NumberConstructor as a value) - urlPath: "{transactionId}" // url that will replace `byId`. We have `{}` format syntax here, so it means data from `params` matching given property names will be replaced in braces - } - } - } -}; - -const extended: TWaxRestExtended<typeof ExtendedRestApi> = chain.extendRest(ExtendedRestApi); - -// Call the REST API using our extended interface -const result = await await extended.restApi['hafah-api'].transactions.byId({ transactionId: "954f6de36e6715d128fa8eb5a053fc254b05ded0" }); - -console.info(result); // URL response from "https://api.syncad.com/hafah-api/transactions/954f6de36e6715d128fa8eb5a053fc254b05ded0" -``` - #### Extend REST API interface using interfaces only and call custom endpoints In this example we will extend the REST API Wax endpoints without creating any validators. @@ -373,7 +289,7 @@ Tested on the latest Chromium To run the tests on your own, clone the wax repo and install the dependencies and then compile the project: -You should perform any development-related work in our devcontainers available in the [.devcontainer](.devcontainer) directory. +You should perform any development-related work in our devcontainers defined by the [.devcontainer](.devcontainer/devcontainer.json) file. If you do not wish to use docker, then you will have to install project dependencies on your own: `protobuf-compiler`, `docker.io`, `npm`, `pnpm`, `nodejs`, `jq` diff --git a/ts/npm-common-config b/ts/npm-common-config index 5806284d3c6feb2ce52bdb6077c20a9a578bb643..590bfd88a491efba5a39571bc2c82ffbabda2ec8 160000 --- a/ts/npm-common-config +++ b/ts/npm-common-config @@ -1 +1 @@ -Subproject commit 5806284d3c6feb2ce52bdb6077c20a9a578bb643 +Subproject commit 590bfd88a491efba5a39571bc2c82ffbabda2ec8 diff --git a/ts/package.json b/ts/package.json index 977083010d8a9091b64a79fc7c6db29d957f6ee5..fb86c6c14163fa369cf4e3d0b50dcd7477cd39c0 100644 --- a/ts/package.json +++ b/ts/package.json @@ -23,7 +23,8 @@ "examples:vue-webpack": "cd ../examples/ts/vue-webpack && pnpm install && pnpm run build && cd ../../../ts", "examples:vue-vite": "cd ../examples/ts/vue-vite && pnpm install && pnpm run test && pnpm run build && cd ../../../ts", "examples:react-vite": "cd ../examples/ts/react-vite && pnpm install && pnpm run test && pnpm run build && cd ../../../ts", - "examples:nuxt-app": "cd ../examples/ts/nuxt-app && pnpm install && pnpm run test && pnpm run build && cd ../../../ts" + "examples:nuxt-app": "cd ../examples/ts/nuxt-app && pnpm install && pnpm run test && pnpm run build && cd ../../../ts", + "examples:signature-extension": "cd ../examples/ts/signature-extension && pnpm install && pnpm run build && pnpm run test && cd ../../../ts" }, "exports": { ".": { @@ -71,8 +72,6 @@ "@types/express": "^5.0.0", "@types/express-http-proxy": "^1.6.6", "@types/node": "^22.10.6", - "class-transformer": "^0.5.1", - "class-validator": "^0.14.0", "cors": "^2.8.5", "express": "^4.21.2", "express-http-proxy": "^2.1.1", @@ -81,7 +80,7 @@ "npm-run-all": "^4.1.5", "playwright": "catalog:playwright-toolset", "protobufjs": "catalog:proto-toolset", - "reflect-metadata": "^0.1.13", + "reflect-metadata": "^0.2.2", "rimraf": "^6.0.1", "rollup": "catalog:rollup-toolset", "rollup-plugin-copy": "catalog:rollup-toolset", @@ -106,7 +105,7 @@ "path": [ "./wasm/dist/bundle" ], - "limit": "5500 kB", + "limit": "5400 kB", "brotli": false } ], diff --git a/ts/packages/README.md b/ts/packages/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9464f17021c6484756fc87a1da9745cd9813703f --- /dev/null +++ b/ts/packages/README.md @@ -0,0 +1,9 @@ +# Wax packages + +This Wax subdirectory is responsible for maintaining Wax "extensions", e.g. signers using the pnpm's workspaces strategy + +## Building + +1. Install dependencies using `pnpm install` - this will automatically install dependencies for all of the package directories from this directory. +2. Build all the packages using `pnpm run build` +3. Now you can either pack: `pnpm run pack` or publish: `pnpm publish -r`. Note: All of the packages will be saved under [`dist`](./dist) directory diff --git a/ts/packages/signers-keychain/README.md b/ts/packages/signers-keychain/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4d70a6a72c9ab80e38e818e952c32d420a005a57 --- /dev/null +++ b/ts/packages/signers-keychain/README.md @@ -0,0 +1,42 @@ +# @hiveio/wax-signers-keychain + +Wax signer library extending transaction signing possibilities by a 3rd party Web-only extension - Keychain + +## Prerequisites + +- Configured [@hiveio/wax](https://www.npmjs.com/package/@hiveio/wax) library. Wax Keychain signer is an extension the base Wax library, extending its signing possibilities by using 3rd party wallet +- Configured [Keychain browser extension](https://hive-keychain.com/) with imported keys + +## Example usage + +```ts +import { createHiveChain } from "@hiveio/wax"; +import KeychainProvider from "@hiveio/wax-signers-keychain"; + +const chain = await createHiveChain(); + +const provider = KeychainProvider.for("myaccount", "active"); + +// Create a transaction using the Wax Hive chain instance +const tx = await chain.createTransaction(); + +// Perform some operations, e.g. push the vote operation: +tx.pushOperation({ + vote: { + voter: "alice", + author: "bob", + permlink: "example-post", + weight: 10000 + } +}); + +// Wait for the keychain to sign the transaction +await tx.sign(provider); + +// broadcast the transaction +await chain.broadcast(tx); +``` + +## License + +See license in [LICENSE.md](LICENSE.md) file diff --git a/ts/packages/signers-keychain/package.json b/ts/packages/signers-keychain/package.json new file mode 100644 index 0000000000000000000000000000000000000000..78b822ea1128c363e74e2f3014f8854181d9ba48 --- /dev/null +++ b/ts/packages/signers-keychain/package.json @@ -0,0 +1,40 @@ +{ + "name": "@hiveio/wax-signers-keychain", + "version": "0.0.0-Run-Prepack", + "description": "Wax signer library extending transaction signing possibilities by a 3rd party Web-only extension - Keychain", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "type": "module", + "private": false, + "scripts": { + "build": "tsc", + "prepack": "jq --argfile source ../../package.json '.version = $source.version | .publishConfig.registry = $source.publishConfig.registry | .publishConfig.tag = $source.publishConfig.tag' package.json > package.json.tmp && mv package.json.tmp package.json" + }, + "devDependencies": { + "typescript": "catalog:typescript-toolset" + }, + "dependencies": { + "@hiveio/wax": "workspace:../..", + "keychain-sdk": "^0.8.5" + }, + "files": [ + "dist/index.d.ts", + "dist/index.js", + "README.md", + "LICENSE.md" + ], + "license": "SEE LICENSE IN LICENSE.md", + "keywords": [ + "wax", + "blockchain", + "hive" + ], + "repository": { + "type": "git", + "url": "https://gitlab.syncad.com/hive/wax.git" + }, + "publishConfig": { + "registry": "https://RegistryPlaceholder", + "tag": "DistTagPlaceholder" + } +} \ No newline at end of file diff --git a/ts/packages/signers-keychain/src/index.ts b/ts/packages/signers-keychain/src/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..b997ac21bf5d997c1d458b0d8f39f0061cc63bf1 --- /dev/null +++ b/ts/packages/signers-keychain/src/index.ts @@ -0,0 +1,68 @@ +import type { IOnlineSignatureProvider, ITransaction, TAccountName, TRole } from "@hiveio/wax"; + +import { KeychainKeyTypes, KeychainSDK } from "keychain-sdk"; + +const mapRoles: Record<TRole, KeychainKeyTypes | undefined> = { + active: KeychainKeyTypes.active, + posting: KeychainKeyTypes.posting, + owner: undefined, + memo: KeychainKeyTypes.memo +}; + +// We do not extend from WaxError to avoid runtime dependencies, such as: /vite or /web - without it we can import only types +export class WaxKeychainProviderError extends Error {} + +/** + * Wax transaction signature provider using the Keychain SDK. + * + * @example + * ``` + * const provider = KeychainProvider.for("myaccount", "active"); + * + * // Create a transaction using the Wax Hive chain instance + * const tx = await chain.createTransaction(); + * + * // Perform some operations, e.g. pushing operations... + * + * // Sign the transaction + * await tx.sign(provider); + * + * // broadcast + * await chain.broadcast(tx); + * ``` + */ +class KeychainProvider implements IOnlineSignatureProvider { + private readonly role: KeychainKeyTypes; + + private static keychain: KeychainSDK; + + private constructor( + private readonly accountName: TAccountName, + role: TRole + ) { + if (!mapRoles[role]) + throw new Error(`Role ${role} is not supported by the Wax signature provider: ${KeychainProvider.name}`); + + if(!KeychainProvider.keychain) + KeychainProvider.keychain = new KeychainSDK(window); + + this.role = mapRoles[role]; + } + + public static for(accountName: TAccountName, role: TRole): KeychainProvider { + return new KeychainProvider(accountName, role); + } + + public async signTransaction(transaction: ITransaction): Promise<void> { + const data = await KeychainProvider.keychain.signTx({ + method: this.role, + username: this.accountName, + tx: JSON.parse(transaction.toLegacyApi()) + }); + + for(const sig of data.result.signatures) + transaction.sign(sig); + } +} + +export default KeychainProvider; diff --git a/ts/packages/signers-keychain/tsconfig.json b/ts/packages/signers-keychain/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..25ef87095e9b8b92046b3cc99f25155cc9e81fcc --- /dev/null +++ b/ts/packages/signers-keychain/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../npm-common-config/ts-common/tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "baseUrl": ".", + "outDir": "./dist", + "incremental": true, + "tsBuildInfoFile": "./dist/.tsbuildinfo", + "skipLibCheck": true + }, + "include": [ + "./src" + ] +} \ No newline at end of file diff --git a/ts/packages/signers-peakvault/README.md b/ts/packages/signers-peakvault/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c740df95f5dcfbddcb956825e41291093cb3d9d3 --- /dev/null +++ b/ts/packages/signers-peakvault/README.md @@ -0,0 +1,42 @@ +# @hiveio/wax-signers-peakvault + +Wax signer library extending transaction signing possibilities by a 3rd party Web-only extension - Peak Vault + +## Prerequisites + +- Configured [@hiveio/wax](https://www.npmjs.com/package/@hiveio/wax) library. Wax Peak Vault signer is an extension the base Wax library, extending its signing possibilities by using 3rd party wallet +- Configured [Peak Vault browser extension](https://vault.peakd.com/peakvault/releases.html) with imported keys + +## Example usage + +```ts +import { createHiveChain } from "@hiveio/wax"; +import PeakVaultProvider from "@hiveio/wax-signers-peakvault"; + +const chain = await createHiveChain(); + +const provider = PeakVaultProvider.for("myaccount", "active"); + +// Create a transaction using the Wax Hive chain instance +const tx = await chain.createTransaction(); + +// Perform some operations, e.g. push the vote operation: +tx.pushOperation({ + vote: { + voter: "alice", + author: "bob", + permlink: "example-post", + weight: 10000 + } +}); + +// Wait for the keychain to sign the transaction +await tx.sign(provider); + +// broadcast the transaction +await chain.broadcast(tx); +``` + +## License + +See license in [LICENSE.md](LICENSE.md) file diff --git a/ts/packages/signers-peakvault/package.json b/ts/packages/signers-peakvault/package.json new file mode 100644 index 0000000000000000000000000000000000000000..50b7028aa416cee53719dbe6abaad0123c9b2d6c --- /dev/null +++ b/ts/packages/signers-peakvault/package.json @@ -0,0 +1,41 @@ +{ + "name": "@hiveio/wax-signers-peakvault", + "version": "0.0.0-Run-Prepack", + "description": "Wax signer library extending transaction signing possibilities by a 3rd party Web-only extension - Peak Vault", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "type": "module", + "private": false, + "scripts": { + "build": "tsc", + "prepack": "jq --argfile source ../../package.json '.version = $source.version | .publishConfig.registry = $source.publishConfig.registry | .publishConfig.tag = $source.publishConfig.tag' package.json > package.json.tmp && mv package.json.tmp package.json" + + }, + "devDependencies": { + "typescript": "catalog:typescript-toolset" + }, + "dependencies": { + "@hiveio/wax": "workspace:../..", + "@peakd/hive-wallet-sdk": "^0.2.3" + }, + "files": [ + "dist/index.d.ts", + "dist/index.js", + "README.md", + "LICENSE.md" + ], + "license": "SEE LICENSE IN LICENSE.md", + "keywords": [ + "wax", + "blockchain", + "hive" + ], + "repository": { + "type": "git", + "url": "https://gitlab.syncad.com/hive/wax.git" + }, + "publishConfig": { + "registry": "https://RegistryPlaceholder", + "tag": "DistTagPlaceholder" + } +} \ No newline at end of file diff --git a/ts/packages/signers-peakvault/src/index.ts b/ts/packages/signers-peakvault/src/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..f9588a2310c7606914debae5ae40121013e9f0b6 --- /dev/null +++ b/ts/packages/signers-peakvault/src/index.ts @@ -0,0 +1,69 @@ +import type { IOnlineSignatureProvider, ITransaction, TAccountName, TRole } from "@hiveio/wax"; + +import { getWallet } from '@peakd/hive-wallet-sdk' + +// @peakd/hive-wallet-sdk fails to provide this type import +type KeyRole = Parameters<typeof PeakVaultProvider['peakVaultWallet']['signTx']>[2]; + +const mapRoles: Record<TRole, KeyRole | undefined> = { + active: 'active', + posting: 'posting', + owner: undefined, + memo: 'memo' +}; + +const PEAKVAULT_WALLET_ID: Parameters<typeof getWallet>[0] = 'peakvault'; + +// We do not extend from WaxError to avoid runtime dependencies, such as: /vite or /web - without it we can import only types +export class WaxPeakVaultProviderError extends Error {} + +/** + * Wax transaction signature provider using the Peak Vault. + * + * @example + * ``` + * const provider = PeakVaultProvider.for("myaccount", "active"); + * + * // Create a transaction using the Wax Hive chain instance + * const tx = await chain.createTransaction(); + * + * // Perform some operations, e.g. pushing operations... + * + * // Sign the transaction + * await tx.sign(provider); + * + * // broadcast + * await chain.broadcast(tx); + * ``` + */ +class PeakVaultProvider implements IOnlineSignatureProvider { + private readonly role: KeyRole; + + private static peakVaultWallet: Awaited<ReturnType<typeof getWallet>>; + + private constructor( + private readonly accountName: TAccountName, + role: TRole + ) { + if (!mapRoles[role]) + throw new Error(`Role ${role} is not supported by the Wax signature provider: ${PeakVaultProvider.name}`); + + this.role = mapRoles[role]; + } + + public static for(accountName: TAccountName, role: TRole): PeakVaultProvider { + return new PeakVaultProvider(accountName, role); + } + + public async signTransaction(transaction: ITransaction): Promise<void> { + if (!PeakVaultProvider.peakVaultWallet) + PeakVaultProvider.peakVaultWallet = await getWallet(PEAKVAULT_WALLET_ID); + + const data = await PeakVaultProvider.peakVaultWallet.signTx(this.accountName, JSON.parse(transaction.toLegacyApi()), this.role); + + for(const sig of data.result.signatures) + transaction.sign(sig); + } +} + +export default PeakVaultProvider; diff --git a/ts/packages/signers-peakvault/tsconfig.json b/ts/packages/signers-peakvault/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..25ef87095e9b8b92046b3cc99f25155cc9e81fcc --- /dev/null +++ b/ts/packages/signers-peakvault/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../npm-common-config/ts-common/tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "baseUrl": ".", + "outDir": "./dist", + "incremental": true, + "tsBuildInfoFile": "./dist/.tsbuildinfo", + "skipLibCheck": true + }, + "include": [ + "./src" + ] +} \ No newline at end of file diff --git a/ts/pnpm-lock.yaml b/ts/pnpm-lock.yaml index 392e10a266680b557b45c35bd57409da431956ab..62c7e65a1c055b025a2cc265ad1dda8746d58b8b 100644 --- a/ts/pnpm-lock.yaml +++ b/ts/pnpm-lock.yaml @@ -8,7 +8,7 @@ catalogs: husky: husky: specifier: 9.1.5 - version: 8.0.3 + version: 9.1.5 playwright-toolset: '@playwright/test': specifier: 1.50.1 @@ -121,12 +121,6 @@ importers: '@types/node': specifier: ^22.10.6 version: 22.10.7 - class-transformer: - specifier: ^0.5.1 - version: 0.5.1 - class-validator: - specifier: ^0.14.0 - version: 0.14.0 cors: specifier: ^2.8.5 version: 2.8.5 @@ -141,7 +135,7 @@ importers: version: 14.1.1 husky: specifier: catalog:husky - version: 8.0.3 + version: 9.1.5 npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -152,8 +146,8 @@ importers: specifier: catalog:proto-toolset version: 7.2.5 reflect-metadata: - specifier: ^0.1.13 - version: 0.1.13 + specifier: ^0.2.2 + version: 0.2.2 rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -194,6 +188,32 @@ importers: specifier: catalog:typescript-toolset version: 5.7.3 + packages/signers-keychain: + dependencies: + '@hiveio/wax': + specifier: workspace:../.. + version: link:../.. + keychain-sdk: + specifier: ^0.8.5 + version: 0.8.5 + devDependencies: + typescript: + specifier: catalog:typescript-toolset + version: 5.7.3 + + packages/signers-peakvault: + dependencies: + '@hiveio/wax': + specifier: workspace:../.. + version: link:../.. + '@peakd/hive-wallet-sdk': + specifier: ^0.2.3 + version: 0.2.3 + devDependencies: + typescript: + specifier: catalog:typescript-toolset + version: 5.7.3 + packages: '@babel/code-frame@7.26.2': @@ -204,6 +224,17 @@ packages: resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + + '@dabh/diagnostics@2.0.3': + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + + '@ecency/bytebuffer@6.0.0': + resolution: {integrity: sha512-rGPjzD7a7cPtMHjpJEtLMt/RmqX8XK25tN5qjuu9iaDMK/Ril86CecU5DN/TXEMUQMY1p6b2cVvKBLTdFMr2DA==} + engines: {node: '>=6'} + '@esbuild/aix-ppc64@0.23.1': resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} engines: {node: '>=18'} @@ -355,6 +386,9 @@ packages: resolution: {integrity: sha1-mPx0QrDh3NSPSOYGyR1SUyi3lyA=, tarball: https://gitlab.syncad.com/api/v4/projects/198/packages/npm/@hiveio/beekeeper/-/@hiveio/beekeeper-1.27.10-stable.250305202831.tgz} engines: {node: ^20.11 || >= 21.2} + '@hiveio/dhive@1.3.2': + resolution: {integrity: sha512-kJjp3TbpIlODxjJX4BWwvOf+cMxT8CFH/mNQ40RRjR2LP0a4baSWae1G+U/q/NtgjsIQz6Ja40tvnw6KF12I+g==, tarball: https://registry.npmjs.org/@hiveio/dhive/-/dhive-1.3.2.tgz} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -380,6 +414,18 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@noble/ciphers@1.2.1': + resolution: {integrity: sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.8.1': + resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.7.1': + resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -392,6 +438,9 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@peakd/hive-wallet-sdk@0.2.3': + resolution: {integrity: sha512-vuhGhlEJKD4CLhE7tGtJH/52HjIj/2Ms5aH8MUB80G9kz9O/oPUQbISMTsycyvKIhBZ4I/bc4Y3My+FRkQg6nQ==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -604,6 +653,9 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + '@types/node@18.19.80': + resolution: {integrity: sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ==} + '@types/node@22.10.7': resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==} @@ -622,12 +674,12 @@ packages: '@types/serve-static@1.15.7': resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@types/validator@13.11.6': - resolution: {integrity: sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==} - accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -675,20 +727,51 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} + assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + async@2.6.4: resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + axios@1.8.2: + resolution: {integrity: sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base-x@3.0.11: + resolution: {integrity: sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==} + + base-x@5.0.1: + resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} + basic-auth@2.0.1: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} + bigi@1.4.2: + resolution: {integrity: sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==} + + bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + + bip66@1.1.5: + resolution: {integrity: sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==} + + bn.js@4.12.1: + resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} + body-parser@1.20.3: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -703,9 +786,24 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + + bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + + bs58@6.0.0: + resolution: {integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + bytes-iec@3.1.1: resolution: {integrity: sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==} engines: {node: '>= 0.8'} @@ -746,11 +844,9 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} - class-transformer@0.5.1: - resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} - - class-validator@0.14.0: - resolution: {integrity: sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==} + cipher-base@1.0.6: + resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} + engines: {node: '>= 0.10'} color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -765,9 +861,22 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + colorette@1.4.0: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} + colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -792,6 +901,12 @@ packages: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} + core-js@3.41.0: + resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==} + + core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + cors@2.8.5: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} @@ -800,6 +915,15 @@ packages: resolution: {integrity: sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==} engines: {node: '>= 0.4.0'} + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + + cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + cross-spawn@6.0.6: resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} engines: {node: '>=4.8'} @@ -808,6 +932,9 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + data-view-buffer@1.0.1: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} engines: {node: '>= 0.4'} @@ -848,6 +975,10 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -868,6 +999,10 @@ packages: dprint-node@1.0.8: resolution: {integrity: sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==} + drbg.js@1.0.1: + resolution: {integrity: sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g==} + engines: {node: '>=0.10'} + dunder-proto@1.0.0: resolution: {integrity: sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==} engines: {node: '>= 0.4'} @@ -875,15 +1010,24 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ecurve@1.0.6: + resolution: {integrity: sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w==} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -923,6 +1067,10 @@ packages: resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + es-to-primitive@1.3.0: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} @@ -956,6 +1104,9 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + express-http-proxy@2.1.1: resolution: {integrity: sha512-4aRQRqDQU7qNPV5av0/hLcyc0guB9UP71nCYrQEYml7YphTo8tmWf3nDZWdTJMMjFikyz9xKXaURor7Chygdwg==} engines: {node: '>=6.0.0'} @@ -964,6 +1115,10 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} + extsprintf@1.4.1: + resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==} + engines: {'0': node >=0.6.0} + fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -979,6 +1134,15 @@ packages: picomatch: optional: true + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + + file-stream-rotator@0.6.1: + resolution: {integrity: sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==} + + file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -987,6 +1151,9 @@ packages: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + follow-redirects@1.15.3: resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} engines: {node: '>=4.0'} @@ -996,6 +1163,15 @@ packages: debug: optional: true + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -1003,6 +1179,10 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -1122,6 +1302,13 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} + hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -1130,6 +1317,15 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + hive-keychain-commons@1.5.1: + resolution: {integrity: sha512-P5/lPS/1MduZ1IrgdGGGlVa/lslxnklutB3FIE9UXWi8YpIunEc9EkUw0grJ2pmQCZlsEF9RCD/nEIXNZybCqA==} + + hive-tx@6.0.6: + resolution: {integrity: sha512-DCxcXOR+u/BAN2+gqePg3jwcU6PHH8uoGLlKmjfbcyGUJdeP37ZlNpXo8JcDv5ER2nPqobgbxR7SD0Bdmw4IvQ==} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -1150,9 +1346,12 @@ packages: engines: {node: '>=12'} hasBin: true - husky@8.0.3: - resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} - engines: {node: '>=14'} + https@1.0.0: + resolution: {integrity: sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==} + + husky@9.1.5: + resolution: {integrity: sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag==} + engines: {node: '>=18'} hasBin: true iconv-lite@0.4.24: @@ -1189,6 +1388,9 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -1274,6 +1476,10 @@ packages: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + is-string@1.1.1: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} @@ -1318,14 +1524,23 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + jsbi@3.2.5: + resolution: {integrity: sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==} + + jsbi@4.3.0: + resolution: {integrity: sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==} + json-parse-better-errors@1.0.2: resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - libphonenumber-js@1.10.49: - resolution: {integrity: sha512-gvLtyC3tIuqfPzjvYLH9BmVdqzGDiSi4VjtWe2fAgSdBf0yt8yPmbNnRIHNbR5IdtVkm0ayGuzwQKTWmU0hdjQ==} + keychain-sdk@0.8.5: + resolution: {integrity: sha512-8VLIgoCs1oBTmQ0EIPNV74oJIUF5xZ1EdTUADFxLPlYfdEXVj5f/JcZx2TZufR5v0FzNLaibcxqCg4DCaP6IIw==} + + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} @@ -1341,6 +1556,14 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + logform@2.7.0: + resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} + engines: {node: '>= 12.0.0'} + + long@3.2.0: + resolution: {integrity: sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==} + engines: {node: '>=0.6'} + long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} @@ -1365,6 +1588,9 @@ packages: resolution: {integrity: sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==} engines: {node: '>= 0.4'} + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} @@ -1404,6 +1630,12 @@ packages: engines: {node: '>=4'} hasBin: true + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + minimatch@10.0.1: resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} engines: {node: 20 || >=22} @@ -1426,12 +1658,18 @@ packages: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true + moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nan@2.22.2: + resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} + nanospinner@1.2.2: resolution: {integrity: sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==} @@ -1442,6 +1680,22 @@ packages: nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + node-addon-api@5.1.0: + resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -1454,6 +1708,10 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + object-hash@2.2.0: + resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} + engines: {node: '>= 6'} + object-inspect@1.13.2: resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} engines: {node: '>= 0.4'} @@ -1477,6 +1735,9 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true @@ -1572,6 +1833,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} @@ -1595,12 +1859,16 @@ packages: resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} engines: {node: '>=4'} + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + readdirp@4.1.1: resolution: {integrity: sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==} engines: {node: '>= 14.18.0'} - reflect-metadata@0.1.13: - resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} reflect.getprototypeof@1.0.8: resolution: {integrity: sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ==} @@ -1629,6 +1897,9 @@ packages: engines: {node: 20 || >=22} hasBin: true + ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + rollup-plugin-copy@3.5.0: resolution: {integrity: sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==} engines: {node: '>=8.3'} @@ -1662,9 +1933,21 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + secp256k1@3.8.1: + resolution: {integrity: sha512-tArjQw2P0RTdY7QmkNehgp6TVvQXq6ulIhxv8gaH6YubKG/wxxAoNKcbuXjDhybbc+b2Ihc7e0xxiGN744UIiQ==} + engines: {node: '>=4.0.0'} + + secp256k1@5.0.1: + resolution: {integrity: sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA==} + engines: {node: '>=18.0.0'} + secure-compare@3.0.1: resolution: {integrity: sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==} @@ -1691,6 +1974,10 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -1735,6 +2022,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + size-limit@11.1.6: resolution: {integrity: sha512-S5ux2IB8rU26xwVgMskmknGMFkieaIAqDLuwgKiypk6oa4lFsie8yFPrzRFV+yrLDY2GddjXuCaVk5PveVOHiQ==} engines: {node: ^18.0.0 || >=20.0.0} @@ -1763,6 +2053,9 @@ packages: spdx-license-ids@3.0.20: resolution: {integrity: sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==} + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -1791,6 +2084,9 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -1820,6 +2116,9 @@ packages: engines: {node: '>=10'} hasBin: true + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + tinyglobby@0.2.10: resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} engines: {node: '>=12.0.0'} @@ -1832,6 +2131,13 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + ts-poet@6.9.0: resolution: {integrity: sha512-roe6W6MeZmCjRmppyfOURklO5tQFQ6Sg7swURKkwYJvV7dbGCrK28um5+51iW3twdPRKtwarqFAVMU6G1mvnuQ==} @@ -1900,6 +2206,9 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} @@ -1918,25 +2227,41 @@ packages: url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - validator@13.11.0: - resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} - engines: {node: '>= 0.10'} - vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + verror@1.10.1: + resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} + engines: {node: '>=0.6.0'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -1962,6 +2287,20 @@ packages: engines: {node: '>= 8'} hasBin: true + winston-daily-rotate-file@4.7.1: + resolution: {integrity: sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==} + engines: {node: '>=8'} + peerDependencies: + winston: ^3 + + winston-transport@4.9.0: + resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} + engines: {node: '>= 12.0.0'} + + winston@3.17.0: + resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==} + engines: {node: '>= 12.0.0'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -1990,6 +2329,18 @@ snapshots: '@babel/helper-validator-identifier@7.25.9': optional: true + '@colors/colors@1.6.0': {} + + '@dabh/diagnostics@2.0.3': + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + + '@ecency/bytebuffer@6.0.0': + dependencies: + long: 3.2.0 + '@esbuild/aix-ppc64@0.23.1': optional: true @@ -2070,6 +2421,24 @@ snapshots: '@hiveio/beekeeper@1.27.10-stable.250305202831': {} + '@hiveio/dhive@1.3.2': + dependencies: + '@ecency/bytebuffer': 6.0.0 + bigi: 1.4.2 + bs58: 4.0.1 + core-js: 3.41.0 + cross-fetch: 3.2.0 + ecurve: 1.0.6 + https: 1.0.0 + jsbi: 3.2.5 + node-fetch: 2.7.0 + ripemd160: 2.0.2 + secp256k1: 3.8.1 + verror: 1.10.1 + whatwg-fetch: 3.6.20 + transitivePeerDependencies: + - encoding + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -2101,6 +2470,14 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@noble/ciphers@1.2.1': {} + + '@noble/curves@1.8.1': + dependencies: + '@noble/hashes': 1.7.1 + + '@noble/hashes@1.7.1': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2113,6 +2490,8 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.0 + '@peakd/hive-wallet-sdk@0.2.3': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -2297,6 +2676,10 @@ snapshots: '@types/minimatch@5.1.2': {} + '@types/node@18.19.80': + dependencies: + undici-types: 5.26.5 + '@types/node@22.10.7': dependencies: undici-types: 6.20.0 @@ -2318,9 +2701,9 @@ snapshots: '@types/node': 22.10.7 '@types/send': 0.17.4 - '@types/unist@3.0.3': {} + '@types/triple-beam@1.3.5': {} - '@types/validator@13.11.6': {} + '@types/unist@3.0.3': {} accepts@1.3.8: dependencies: @@ -2364,20 +2747,52 @@ snapshots: get-intrinsic: 1.2.6 is-array-buffer: 3.0.5 + assert-plus@1.0.0: {} + async@2.6.4: dependencies: lodash: 4.17.21 + async@3.2.6: {} + + asynckit@0.4.0: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 + axios@1.8.2: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + balanced-match@1.0.2: {} + base-x@3.0.11: + dependencies: + safe-buffer: 5.2.1 + + base-x@5.0.1: {} + basic-auth@2.0.1: dependencies: safe-buffer: 5.1.2 + bigi@1.4.2: {} + + bindings@1.5.0: + dependencies: + file-uri-to-path: 1.0.0 + + bip66@1.1.5: + dependencies: + safe-buffer: 5.2.1 + + bn.js@4.12.1: {} + body-parser@1.20.3: dependencies: bytes: 3.1.2 @@ -2408,8 +2823,29 @@ snapshots: dependencies: fill-range: 7.1.1 + brorand@1.1.0: {} + + browserify-aes@1.2.0: + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.6 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + bs58@4.0.1: + dependencies: + base-x: 3.0.11 + + bs58@6.0.0: + dependencies: + base-x: 5.0.1 + buffer-from@1.1.2: {} + buffer-xor@1.0.3: {} + bytes-iec@3.1.1: {} bytes@3.1.2: {} @@ -2456,13 +2892,10 @@ snapshots: dependencies: readdirp: 4.1.1 - class-transformer@0.5.1: {} - - class-validator@0.14.0: + cipher-base@1.0.6: dependencies: - '@types/validator': 13.11.6 - libphonenumber-js: 1.10.49 - validator: 13.11.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 color-convert@1.9.3: dependencies: @@ -2476,8 +2909,27 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + colorette@1.4.0: {} + colorspace@1.1.4: + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + commander@2.20.3: {} commondir@1.0.1: {} @@ -2494,6 +2946,10 @@ snapshots: cookie@0.7.1: {} + core-js@3.41.0: {} + + core-util-is@1.0.2: {} + cors@2.8.5: dependencies: object-assign: 4.1.1 @@ -2501,6 +2957,29 @@ snapshots: corser@2.0.1: {} + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.6 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.6 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + + cross-fetch@3.2.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + cross-spawn@6.0.6: dependencies: nice-try: 1.0.5 @@ -2515,6 +2994,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crypto-js@4.2.0: {} + data-view-buffer@1.0.1: dependencies: call-bind: 1.0.8 @@ -2555,6 +3036,8 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 + delayed-stream@1.0.0: {} + depd@2.0.0: {} destroy@1.2.0: {} @@ -2569,6 +3052,12 @@ snapshots: dependencies: detect-libc: 1.0.3 + drbg.js@1.0.1: + dependencies: + browserify-aes: 1.2.0 + create-hash: 1.2.0 + create-hmac: 1.1.7 + dunder-proto@1.0.0: dependencies: call-bind-apply-helpers: 1.0.1 @@ -2577,12 +3066,29 @@ snapshots: eastasianwidth@0.2.0: {} + ecurve@1.0.6: + dependencies: + bigi: 1.4.2 + safe-buffer: 5.2.1 + ee-first@1.1.1: {} + elliptic@6.6.1: + dependencies: + bn.js: 4.12.1 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} + enabled@2.0.0: {} + encodeurl@1.0.2: {} encodeurl@2.0.0: {} @@ -2662,6 +3168,13 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.2.6 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + es-to-primitive@1.3.0: dependencies: is-callable: 1.2.7 @@ -2709,6 +3222,11 @@ snapshots: events@3.3.0: {} + evp_bytestokey@1.0.3: + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + express-http-proxy@2.1.1: dependencies: debug: 3.2.7 @@ -2753,6 +3271,8 @@ snapshots: transitivePeerDependencies: - supports-color + extsprintf@1.4.1: {} + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2769,6 +3289,14 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fecha@4.2.3: {} + + file-stream-rotator@0.6.1: + dependencies: + moment: 2.30.1 + + file-uri-to-path@1.0.0: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -2785,8 +3313,12 @@ snapshots: transitivePeerDependencies: - supports-color + fn.name@1.1.0: {} + follow-redirects@1.15.3: {} + follow-redirects@1.15.9: {} + for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -2796,6 +3328,13 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + forwarded@0.2.0: {} fresh@0.5.2: {} @@ -2936,12 +3475,54 @@ snapshots: dependencies: has-symbols: 1.1.0 + hash-base@3.1.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + hasown@2.0.2: dependencies: function-bind: 1.1.2 he@1.2.0: {} + hive-keychain-commons@1.5.1: + dependencies: + '@hiveio/dhive': 1.3.2 + bs58: 4.0.1 + crypto-js: 4.2.0 + hive-tx: 6.0.6 + jsbi: 4.3.0 + moment: 2.30.1 + secp256k1: 5.0.1 + winston: 3.17.0 + winston-daily-rotate-file: 4.7.1(winston@3.17.0) + transitivePeerDependencies: + - debug + - encoding + + hive-tx@6.0.6: + dependencies: + '@noble/ciphers': 1.2.1 + '@noble/curves': 1.8.1 + '@noble/hashes': 1.7.1 + axios: 1.8.2 + bs58: 6.0.0 + transitivePeerDependencies: + - debug + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + hosted-git-info@2.8.9: {} html-encoding-sniffer@3.0.0: @@ -2983,7 +3564,9 @@ snapshots: - debug - supports-color - husky@8.0.3: {} + https@1.0.0: {} + + husky@9.1.5: {} iconv-lite@0.4.24: dependencies: @@ -3018,6 +3601,8 @@ snapshots: is-arrayish@0.2.1: {} + is-arrayish@0.3.2: {} + is-async-function@2.0.0: dependencies: has-tostringtag: 1.0.2 @@ -3096,6 +3681,8 @@ snapshots: dependencies: call-bind: 1.0.8 + is-stream@2.0.1: {} + is-string@1.1.1: dependencies: call-bound: 1.0.3 @@ -3141,13 +3728,27 @@ snapshots: js-tokens@4.0.0: optional: true + jsbi@3.2.5: {} + + jsbi@4.3.0: {} + json-parse-better-errors@1.0.2: {} jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 - libphonenumber-js@1.10.49: {} + keychain-sdk@0.8.5: + dependencies: + '@types/node': 18.19.80 + axios: 1.8.2 + hive-keychain-commons: 1.5.1 + uuid: 9.0.1 + transitivePeerDependencies: + - debug + - encoding + + kuler@2.0.0: {} lilconfig@3.1.3: {} @@ -3164,6 +3765,17 @@ snapshots: lodash@4.17.21: {} + logform@2.7.0: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.5.0 + triple-beam: 1.4.1 + + long@3.2.0: {} + long@5.2.3: {} lru-cache@10.4.3: {} @@ -3187,6 +3799,12 @@ snapshots: math-intrinsics@1.0.0: {} + md5.js@1.3.5: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + mdurl@2.0.0: {} media-typer@0.3.0: {} @@ -3212,6 +3830,10 @@ snapshots: mime@1.6.0: {} + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + minimatch@10.0.1: dependencies: brace-expansion: 2.0.1 @@ -3232,10 +3854,14 @@ snapshots: dependencies: minimist: 1.2.8 + moment@2.30.1: {} + ms@2.0.0: {} ms@2.1.3: {} + nan@2.22.2: {} + nanospinner@1.2.2: dependencies: picocolors: 1.1.1 @@ -3244,6 +3870,14 @@ snapshots: nice-try@1.0.5: {} + node-addon-api@5.1.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-gyp-build@4.8.4: {} + normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 @@ -3265,6 +3899,8 @@ snapshots: object-assign@4.1.1: {} + object-hash@2.2.0: {} + object-inspect@1.13.2: {} object-inspect@1.13.3: {} @@ -3286,6 +3922,10 @@ snapshots: dependencies: wrappy: 1.0.2 + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + opener@1.5.2: {} package-json-from-dist@1.0.1: {} @@ -3371,6 +4011,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} + punycode.js@2.3.1: {} qs@6.13.0: @@ -3394,9 +4036,15 @@ snapshots: normalize-package-data: 2.5.0 path-type: 3.0.0 + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + readdirp@4.1.1: {} - reflect-metadata@0.1.13: {} + reflect-metadata@0.2.2: {} reflect.getprototypeof@1.0.8: dependencies: @@ -3433,6 +4081,11 @@ snapshots: glob: 11.0.1 package-json-from-dist: 1.0.1 + ripemd160@2.0.2: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + rollup-plugin-copy@3.5.0: dependencies: '@types/fs-extra': 8.1.5 @@ -3493,8 +4146,27 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 + safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} + secp256k1@3.8.1: + dependencies: + bindings: 1.5.0 + bip66: 1.1.5 + bn.js: 4.12.1 + create-hash: 1.2.0 + drbg.js: 1.0.1 + elliptic: 6.6.1 + nan: 2.22.2 + safe-buffer: 5.2.1 + + secp256k1@5.0.1: + dependencies: + elliptic: 6.6.1 + node-addon-api: 5.1.0 + node-gyp-build: 4.8.4 + secure-compare@3.0.1: {} semver@5.7.2: {} @@ -3544,6 +4216,11 @@ snapshots: setprototypeof@1.2.0: {} + sha.js@2.4.11: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 @@ -3595,6 +4272,10 @@ snapshots: signal-exit@4.1.0: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + size-limit@11.1.6: dependencies: bytes-iec: 3.1.1 @@ -3628,6 +4309,8 @@ snapshots: spdx-license-ids@3.0.20: {} + stack-trace@0.0.10: {} + statuses@2.0.1: {} string-width@4.2.3: @@ -3672,6 +4355,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -3699,6 +4386,8 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + text-hex@1.0.0: {} + tinyglobby@0.2.10: dependencies: fdir: 6.4.3(picomatch@4.0.2) @@ -3710,6 +4399,10 @@ snapshots: toidentifier@1.0.1: {} + tr46@0.0.3: {} + + triple-beam@1.4.1: {} + ts-poet@6.9.0: dependencies: dprint-node: 1.0.8 @@ -3801,6 +4494,8 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + undici-types@5.26.5: {} + undici-types@6.20.0: {} union@0.5.0: @@ -3813,21 +4508,38 @@ snapshots: url-join@4.0.1: {} + util-deprecate@1.0.2: {} + utils-merge@1.0.1: {} + uuid@9.0.1: {} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - validator@13.11.0: {} - vary@1.1.2: {} + verror@1.10.1: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.4.1 + + webidl-conversions@3.0.1: {} + whatwg-encoding@2.0.0: dependencies: iconv-lite: 0.6.3 + whatwg-fetch@3.6.20: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -3875,6 +4587,34 @@ snapshots: dependencies: isexe: 2.0.0 + winston-daily-rotate-file@4.7.1(winston@3.17.0): + dependencies: + file-stream-rotator: 0.6.1 + object-hash: 2.2.0 + triple-beam: 1.4.1 + winston: 3.17.0 + winston-transport: 4.9.0 + + winston-transport@4.9.0: + dependencies: + logform: 2.7.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + + winston@3.17.0: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.6 + is-stream: 2.0.1 + logform: 2.7.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.5.0 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.9.0 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 diff --git a/ts/rollup.config.js b/ts/rollup.config.js index b10d298979691c80800b1ce9fa24278e7e88677d..4a85aca9e5618ef4a3ed72eb8140278acacedaf5 100644 --- a/ts/rollup.config.js +++ b/ts/rollup.config.js @@ -21,10 +21,6 @@ export default [ }), replace({ values: { - // Make sure we do not include `process` in the code: - 'process': null, - 'process.env': null, - 'process.env.REFLECT_METADATA_USE_MAP_POLYFILL': null, // Bundled dependency - reflect-metadata - uses this - we do not need it // Hardcode package name and version for later use in the code: 'process.env.npm_package_name': `"${process.env.npm_package_name}"`, 'process.env.npm_package_version': `"${process.env.npm_package_version}"` diff --git a/ts/wasm/__tests__/assets/data.encryption-operations.ts b/ts/wasm/__tests__/assets/data.encryption-operations.ts index 0fec627c3698b7b8844f89d816fb66c005f7b905..6e48aac9be739d5ad3e55dc1373dbd748f5b5d8a 100644 --- a/ts/wasm/__tests__/assets/data.encryption-operations.ts +++ b/ts/wasm/__tests__/assets/data.encryption-operations.ts @@ -1,4 +1,4 @@ -import type { IEncryptingTransaction, transaction } from '../../dist/bundle'; +import type { IEncryptingTransaction, ITransaction, transaction } from '../../dist/bundle'; import { createHiveChain } from '../../dist/bundle/node.js'; import { TPublicKey } from '@hiveio/beekeeper'; import "./globals.js"; @@ -8,7 +8,7 @@ const chain = await createHiveChain(); export const utilFunctionTest = async ( { beekeeper, chain, wax }: Pick<IWaxGlobals, 'beekeeper' | 'chain' | 'wax'>, - txOperationsLambda: (tx: IEncryptingTransaction, encryptionKeys: [TPublicKey] | [TPublicKey, TPublicKey]) => void, + txOperationsLambda: (tx: ITransaction & IEncryptingTransaction<ITransaction>, encryptionKeys: [TPublicKey] | [TPublicKey, TPublicKey]) => void, nonEncryptedOperationIndices: number[] = [], otherEncryptionKey: boolean = false ): Promise<transaction> => { diff --git a/ts/wasm/__tests__/detailed/encrypted_operations.ts b/ts/wasm/__tests__/detailed/encrypted_operations.ts index eb040116b641c6f4520dd95eeea3aaf26a29841b..3430c7648a5358042508020c0d1cb8eb448ba570 100644 --- a/ts/wasm/__tests__/detailed/encrypted_operations.ts +++ b/ts/wasm/__tests__/detailed/encrypted_operations.ts @@ -2,8 +2,6 @@ import { expect } from '@playwright/test'; import { test } from '../assets/jest-helper'; -import type { IEncryptingTransaction } from '../../dist/bundle'; - import { utilFunctionTest, commentOp, @@ -19,7 +17,7 @@ import { test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with comment operation', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, commentOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(commentOp); }); }, utilFunctionTest, commentOp); @@ -29,7 +27,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with transfer operation', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, transferOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(transferOp); }); }, utilFunctionTest, transferOp); @@ -39,7 +37,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with custom json operation', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, customJsonOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(customJsonOp); }); }, utilFunctionTest, customJsonOp); @@ -49,7 +47,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with transfer to savings operation', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, transferToSavingsOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(transferToSavingsOp); }); }, utilFunctionTest, transferToSavingsOp); @@ -59,7 +57,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with transfer from savings operation', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, transferFromSavingsOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(transferFromSavingsOp); }); }, utilFunctionTest, transferFromSavingsOp); @@ -69,7 +67,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with recurrent transfer operation', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, recurrentTransferOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(recurrentTransferOp); }); }, utilFunctionTest, recurrentTransferOp); @@ -79,7 +77,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with different operations', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, recurrentTransferOp, convertOp, transferToSavingsOp, voteOp, commentOp, transferOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(recurrentTransferOp).pushOperation(convertOp).pushOperation(transferToSavingsOp).pushOperation(voteOp).pushOperation(commentOp).pushOperation(transferOp); }, [1, 3]); }, utilFunctionTest, recurrentTransferOp, convertOp, transferToSavingsOp, voteOp, commentOp, transferOp); @@ -89,7 +87,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with comment operation with different keys', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, commentOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(commentOp); }, [], true); }, utilFunctionTest, commentOp); @@ -99,7 +97,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with recurrent transfer operation with different keys', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, recurrentTransferOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(recurrentTransferOp); }, [], true); }, utilFunctionTest, recurrentTransferOp); @@ -109,7 +107,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with transfer to savings operation with different keys', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, transferToSavingsOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(transferToSavingsOp); }, [], true); }, utilFunctionTest, transferToSavingsOp); @@ -119,7 +117,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt transaction with different operations with different keys', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, recurrentTransferOp, convertOp, transferToSavingsOp, voteOp, commentOp, transferOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction, encryptionKeys) => { + return await utilFunctionTest(globals, (tx, encryptionKeys) => { tx .pushOperation(recurrentTransferOp) .stopEncrypt() @@ -139,7 +137,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt some specific operations in transaction', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, recurrentTransferOp, convertOp, transferToSavingsOp, voteOp, commentOp, transferOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction, encryptionKeys) => { + return await utilFunctionTest(globals, (tx, encryptionKeys) => { tx .pushOperation(recurrentTransferOp) .stopEncrypt() @@ -160,7 +158,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to encrypt some specific operations in transaction with a barren keys pair at the end', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, recurrentTransferOp, convertOp, transferToSavingsOp, voteOp, commentOp, transferOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction, encryptionKeys) => { + return await utilFunctionTest(globals, (tx, encryptionKeys) => { tx .pushOperation(recurrentTransferOp) .stopEncrypt() diff --git a/ts/wasm/__tests__/detailed/formatters.ts b/ts/wasm/__tests__/detailed/formatters.ts index 2e5ec8abf2cd3f0016b4d3ea0f16faf80eddbb3c..7a3a2a22cb46c1f2d2704e36e4ebaaed44ea78b9 100644 --- a/ts/wasm/__tests__/detailed/formatters.ts +++ b/ts/wasm/__tests__/detailed/formatters.ts @@ -283,7 +283,7 @@ test.describe('Wax object interface formatters tests', () => { test('Should be able to retrieve account from the API and format it using default formatter from the hive chain interface', async({ waxTest }) => { const retVal = await waxTest(async({ chain }) => { - const response = await chain.api.database_api.find_accounts({ accounts: [ "initminer" ] }); + const response = await chain.api.database_api.find_accounts({ accounts: [ "initminer" ], delayed_votes_active: true }); return chain.formatter.extend({ asset: { displayAsNai: false, appendTokenName: true, formatAmount: true, locales: "en-US" } }).format(response.accounts[0]); }); diff --git a/ts/wasm/__tests__/detailed/hive_base.ts b/ts/wasm/__tests__/detailed/hive_base.ts index b8802ab26a418c1816eeef87ae7dbee3f17da85b..83cb1881ca96d1339dd751ce04e862cc776e3de0 100644 --- a/ts/wasm/__tests__/detailed/hive_base.ts +++ b/ts/wasm/__tests__/detailed/hive_base.ts @@ -840,6 +840,30 @@ test.describe('Wax object interface foundation tests', () => { expect(retVal.wifPrivateKey).toHaveLength(51); }); + test('Should be able to convert between raw private key -> WIF formats', async ({ waxTest }) => { + const retVal = await waxTest(async({ base }) => { + return base.convertRawPrivateKeyToWif('48a9c812cafcd35eb761501768ba7e2eb9a238853548556c2c38431f51d63030'); + }); + + expect(retVal).toBe('5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n'); + }); + + test('Should be able to convert between raw compressed public key -> WIF formats', async ({ waxTest }) => { + const retVal = await waxTest(({ base }) => { + return base.convertRawPublicKeyToWif('02be643d4c424ac7cf2f3cf51dd048773cbdcee30b111adb30d89c27668c501705'); + }); + + expect(retVal).toBe('STM6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4'); + }); + + test('Should be able to convert between raw uncompressed public key -> WIF formats', async ({ waxTest }) => { + const retVal = await waxTest(({ base }) => { + return base.convertRawPublicKeyToWif('04be643d4c424ac7cf2f3cf51dd048773cbdcee30b111adb30d89c27668c5017051a9cc2866c479818522ffd2b4a3d7a5a64d1b98c968f8f6ea2ef6745a637eb92'); + }); + + expect(retVal).toBe('STM6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4'); + }); + test('Should be able to estimate hive collateral', async ({ waxTest }) => { const retVal = await waxTest(async({ base }) => { return base.estimateHiveCollateral(201, 1000, 197, 1000, 100000); diff --git a/ts/wasm/__tests__/detailed/hive_chain.ts b/ts/wasm/__tests__/detailed/hive_chain.ts index e88ad440c93d594baf4c70fbd8f79e62e608fe34..cb1c45306649812d95ba49d756acfd1c35a597c4 100644 --- a/ts/wasm/__tests__/detailed/hive_chain.ts +++ b/ts/wasm/__tests__/detailed/hive_chain.ts @@ -2,7 +2,6 @@ import { expect } from '@playwright/test'; import { test } from '../assets/jest-helper'; import { protoVoteOp, recoverAccountTransaction, requiredActiveAuthorityTransaction, requiredOwnerAuthorityTransaction, signatureTransaction } from "../assets/data.proto-protocol"; -import { IsArray, IsObject, IsString } from 'class-validator'; const HIVE_BLOCK_INTERVAL = 3 * 1000; // 3 seconds @@ -33,75 +32,6 @@ test.describe('Wax object interface chain tests', () => { expect(retVal.digest).toBe('205c79e3d17211882b1a2ba8640ff208413d68cabdca892cf47e9a6ad46e63a1'); }); - test('Should be able to transmit article transaction using hive chain interface', async ({ waxTest }) => { - const retVal = await waxTest(async({ beekeeper, chain, wax }) => { - // Create wallet: - const session = beekeeper.createSession("salt"); - const { wallet } = await session.createWallet("w0"); - await wallet.importKey('5JkFnXrLM2ap9t3AmAxBJvQHF7xSKtnTrCTginQCkhzU5S7ecPT'); - - const tx = chain.createTransactionWithTaPoS("04c1c7a566fc0da66aee465714acee7346b48ac2", "2023-08-01T15:38:48"); - - tx.pushOperation(new wax.BlogPostOperation({ - author: "mee", - body: "how r u", - category: "test", - title: "about you", - permlink: "permlink1", - percentHbd: 0, - maxAcceptedPayout: chain.hbdSatoshis(0) - })); - - tx.sign(wallet, "STM5RqVBAVNp5ufMCetQtvLGLJo7unX9nyCBMMrTXRWQ9i1Zzzizh"); - - console.log(tx.toApi()); - - return new wax.BroadcastTransactionRequest(tx); - }); - - retVal.trx.signatures.splice(0, 1); // We do not want to test signing here which will change due to json_metadata app version and name values - - expect(retVal).toStrictEqual({ - max_block_age: -1, - trx: { - operations: [ - { - type: "comment_operation", - value: { - parent_author: "", - parent_permlink: "test", - author: "mee", - permlink: "permlink1", - title: "about you", - body: "how r u", - json_metadata: `{\"format\":\"markdown+html\",\"app\":\"${process.env.npm_package_name}/${process.env.npm_package_version}\"}` - } - }, - { - type: "comment_options_operation", - value: { - author: "mee", - permlink: "permlink1", - max_accepted_payout: { - amount: "0", - precision: 3, - nai: "@@000000013" - }, - percent_hbd: 0, - allow_votes: true, - allow_curation_rewards: true - } - } - ], - extensions: [], - signatures: [], - ref_block_num: 51109, - ref_block_prefix: 2785934438, - expiration: '2023-08-01T15:38:48' - } - }); - }); - test('Should be able to perform example API call', async ({ waxTest }) => { const retVal = await waxTest(async({ chain }) => { // https://developers.hive.io/apidefinitions/#account_by_key_api.get_key_references @@ -169,47 +99,6 @@ test.describe('Wax object interface chain tests', () => { expect(retVal).toStrictEqual({ args: {}, ret: [] }); }); - test('Should be able to extend hive chain and validate properties interface by custom definitions', async ({}, testInfo) => { - class MyRequest { - @IsString() - method!: string; - } - class MyResponse { - @IsObject() - args!: {}; - @IsArray() - ret!: []; - } - - const { chain } = await createWaxTestFor('node', testInfo.outputDir); - const extended = chain.extend({ - jsonrpc: { - get_signature: { - params: MyRequest, - result: MyResponse - } - } - }); - - await expect(async() => { - await extended.api.jsonrpc.get_signature(new MyRequest()); - }).rejects.toBeInstanceOf(Array); // Array<ValidationError> - - await expect(async() => { - const req = new MyRequest(); - (req.method as any) = 10; // Force invalid type on the method - - await extended.api.jsonrpc.get_signature(req); // This should throw after validating - }).rejects.toBeInstanceOf(Array); // Array<ValidationError> - - const result = await extended.api.jsonrpc.get_signature({ method: "jsonrpc.get_methods" }); - - const expectedResult = new MyResponse(); - expectedResult.args = {}; - expectedResult.ret = []; - expect(result).toStrictEqual(expectedResult); - }); - test('Should be able to extend hive chain interface by custom definitions using interfaces only', async ({ waxTest }) => { const retVal = await waxTest(async({ chain }) => { interface IMyRequest { @@ -237,58 +126,6 @@ test.describe('Wax object interface chain tests', () => { expect(retVal).toStrictEqual({ args: {}, ret: [] }); }); - test('Should throw when creating broadcast transaction request from unsigned transaction', async ({ waxTest }) => { - const retVal = await waxTest(async({ chain, wax }, protoVoteOp) => { - const tx = chain.createTransactionWithTaPoS("04c1c7a566fc0da66aee465714acee7346b48ac2", "2023-08-01T15:38:48"); - tx.pushOperation(protoVoteOp).transaction; - - try { - new wax.BroadcastTransactionRequest(tx); - return false; - } catch { - return true; - } - }, protoVoteOp); - - expect(retVal).toBeTruthy(); - }); - - test('Should be able to transmit protobuf transaction using hive chain interface', async ({ waxTest }) => { - const retVal = await waxTest(async({ beekeeper, chain, wax }, protoVoteOp) => { - // Create wallet: - const session = beekeeper.createSession("salt"); - const { wallet } = await session.createWallet("w0"); - await wallet.importKey('5JkFnXrLM2ap9t3AmAxBJvQHF7xSKtnTrCTginQCkhzU5S7ecPT'); - - const tx = chain.createTransactionWithTaPoS("04c1c7a566fc0da66aee465714acee7346b48ac2", "2023-08-01T15:38:48"); - tx.pushOperation(protoVoteOp).sign(wallet, "STM5RqVBAVNp5ufMCetQtvLGLJo7unX9nyCBMMrTXRWQ9i1Zzzizh"); - - return new wax.BroadcastTransactionRequest(tx); - }, protoVoteOp); - - expect(retVal).toStrictEqual({ - max_block_age: -1, - trx: { - operations: [ { - type: "vote_operation", - value: { - author: "c0ff33a", - permlink: "ewxhnjbj", - voter: "otom", - weight: 2200, - } - } ], - extensions: [], - signatures: [ - "1f7f0c3e89e6ccef1ae156a96fb4255e619ca3a73ef3be46746b4b40a66cc4252070eb313cc6308bbee39a0a9fc38ef99137ead3c9b003584c0a1b8f5ca2ff8707" - ], - ref_block_num: 51109, - ref_block_prefix: 2785934438, - expiration: '2023-08-01T15:38:48' - } - }); - }); - test('Should be able to calculate current manabar value using hive chain interface', async ({ waxTest }) => { const retVal = await waxTest(async({ chain }) => { const { current, max, percent } = chain.calculateCurrentManabarValue( @@ -313,7 +150,7 @@ test.describe('Wax object interface chain tests', () => { test('Should be able to parse user manabar from API using hive chain interface', async ({ waxTest }) => { const retVal = await waxTest(async({ chain }) => { const { accounts: [ account ] } = await chain.api.database_api.find_accounts({ - accounts: [ "initminer" ] + accounts: [ "initminer" ], delayed_votes_active: true }); const dgpo = await chain.api.database_api.get_dynamic_global_properties({}); diff --git a/ts/wasm/__tests__/detailed/hive_chain_custom_opts.ts b/ts/wasm/__tests__/detailed/hive_chain_custom_opts.ts index 28f6dfedbe7faee20aebea71d7301425dfedae92..786d088dadd167c8fae59aa5c6ea7549a1c36124 100644 --- a/ts/wasm/__tests__/detailed/hive_chain_custom_opts.ts +++ b/ts/wasm/__tests__/detailed/hive_chain_custom_opts.ts @@ -106,7 +106,7 @@ test.describe('Wax object interface chain tests (using custom options)', () => { test('Should be able to find accounts from hive chain interafce', async({ waxTest }) => { const retVal = await waxTest(async({ chain }) => { - return (await chain.api.database_api.find_accounts({ accounts: ['thatcryptodave'] })).accounts[0]; + return (await chain.api.database_api.find_accounts({ accounts: ['thatcryptodave'], delayed_votes_active: true })).accounts[0]; }); expect(retVal).toHaveProperty('active'); diff --git a/ts/wasm/__tests__/detailed/mock_base.ts b/ts/wasm/__tests__/detailed/mock_base.ts index 9d9527de7b8fa69474a98694b15d931e94ad215b..730b65174efbdaf9a597db973d6291434aa4bc51 100644 --- a/ts/wasm/__tests__/detailed/mock_base.ts +++ b/ts/wasm/__tests__/detailed/mock_base.ts @@ -16,7 +16,7 @@ test.describe('Wax base mock tests', () => { test('Should be able to find account based on mock interface', async ({ waxTest }) => { const retVal = await waxTest(async({ chain }) => { - const foundAccount = await chain.api.database_api.find_accounts({ accounts: ['steem'] }); + const foundAccount = await chain.api.database_api.find_accounts({ accounts: ['steem'], delayed_votes_active: true }); return foundAccount; }); @@ -26,7 +26,7 @@ test.describe('Wax base mock tests', () => { test('Should be able to find NONEXISTING account based on mock interface', async ({ waxTest }) => { const retVal = await waxTest(async({ chain }, accountData) => { - const foundAccount = await chain.api.database_api.find_accounts({ accounts: ['0steem'] }); /// Intentionally use invalid name in Hive + const foundAccount = await chain.api.database_api.find_accounts({ accounts: ['0steem'], delayed_votes_active: true }); /// Intentionally use invalid name in Hive console.log(JSON.stringify(foundAccount)); diff --git a/ts/wasm/__tests__/detailed/non_encrypted_operations.ts b/ts/wasm/__tests__/detailed/non_encrypted_operations.ts index ca6996db027ee8d7ccf3b2bc0cd56496891bbbf2..3f8f2c5fb69868f49e409c1e40899ab79ed78f07 100644 --- a/ts/wasm/__tests__/detailed/non_encrypted_operations.ts +++ b/ts/wasm/__tests__/detailed/non_encrypted_operations.ts @@ -2,8 +2,6 @@ import { expect } from '@playwright/test'; import { test } from '../assets/jest-helper'; -import type { IEncryptingTransaction } from '../../dist/bundle'; - import { accountCreateOp, accountCreateWithDelegationOp, @@ -46,7 +44,7 @@ import { test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with vote operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, voteOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(voteOp); }); }, utilFunctionTest, voteOp); @@ -56,7 +54,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with transfer to vesting operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, transferToVestingOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(transferToVestingOp); }); }, utilFunctionTest, transferToVestingOp); @@ -66,7 +64,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with withdraw vesting operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, withdrawVestingOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(withdrawVestingOp); }); }, utilFunctionTest, withdrawVestingOp); @@ -76,7 +74,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with limit order create operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, limitOrderCreateOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(limitOrderCreateOp); }); }, utilFunctionTest, limitOrderCreateOp); @@ -86,7 +84,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with limit order cancel operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, limitOrderCancelOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(limitOrderCancelOp); }); }, utilFunctionTest, limitOrderCancelOp); @@ -96,7 +94,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with feed publish operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, feedPublishOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(feedPublishOp); }); }, utilFunctionTest, feedPublishOp); @@ -106,7 +104,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with convert operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, convertOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(convertOp); }); }, utilFunctionTest, convertOp); @@ -116,7 +114,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with account create operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, accountCreateOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(accountCreateOp); }); }, utilFunctionTest, accountCreateOp); @@ -126,7 +124,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with account update operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, accountUpdateOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(accountUpdateOp); }); }, utilFunctionTest, accountUpdateOp); @@ -136,7 +134,7 @@ test.describe('Wax encrypted operations tests', () => { // XXX // test('Should be able to pass through encryption on transaction with witness update operation which does not support encryption', async () => { - // const retVal = await utilFunctionTest((tx: IEncryptingTransaction) => { + // const retVal = await utilFunctionTest(tx => { // tx.pushOperation(witnessUpdateOp); // }); @@ -145,7 +143,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with account witness vote operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, accountWitnessVoteOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(accountWitnessVoteOp); }); }, utilFunctionTest, accountWitnessVoteOp); @@ -155,7 +153,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with account witness proxy operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, accountWitnessProxyOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(accountWitnessProxyOp); }); }, utilFunctionTest, accountWitnessProxyOp); @@ -165,7 +163,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with witness block approve operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, witnessBlockApproveOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(witnessBlockApproveOp); }); }, utilFunctionTest, witnessBlockApproveOp); @@ -175,7 +173,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with delete comment operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, deleteCommentOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(deleteCommentOp); }); }, utilFunctionTest, deleteCommentOp); @@ -185,7 +183,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with comment options operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, commentOptionsOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(commentOptionsOp); }); }, utilFunctionTest, commentOptionsOp); @@ -195,7 +193,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with set withdraw vesting route operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, setWithdrawVestingRouteOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(setWithdrawVestingRouteOp); }); }, utilFunctionTest, setWithdrawVestingRouteOp); @@ -205,7 +203,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with limit order create 2 operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, limitOrderCreate2Op) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(limitOrderCreate2Op); }); }, utilFunctionTest, limitOrderCreate2Op); @@ -215,7 +213,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with claim account operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, claimAccountOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(claimAccountOp); }); }, utilFunctionTest, claimAccountOp); @@ -225,7 +223,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with create claimed account operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, createClaimedAccountOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(createClaimedAccountOp); }); }, utilFunctionTest, createClaimedAccountOp); @@ -235,7 +233,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with request account recovery operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, requestAccountRecoveryOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(requestAccountRecoveryOp); }); }, utilFunctionTest, requestAccountRecoveryOp); @@ -245,7 +243,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with change recovery account operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, changeRecoveryAccountOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(changeRecoveryAccountOp); }); }, utilFunctionTest, changeRecoveryAccountOp); @@ -255,7 +253,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with escrow transfer operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, escrowTransferOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(escrowTransferOp); }); }, utilFunctionTest, escrowTransferOp); @@ -265,7 +263,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with escrow dispute operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, escrowDisputeOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(escrowDisputeOp); }); }, utilFunctionTest, escrowDisputeOp); @@ -275,7 +273,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with escrow release operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, escrowReleaseOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(escrowReleaseOp); }); }, utilFunctionTest, escrowReleaseOp); @@ -285,7 +283,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with escrow approve operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, escrowApproveOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(escrowApproveOp); }); }, utilFunctionTest, escrowApproveOp); @@ -295,7 +293,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with cancel transfer from savings operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, cancelTransferFromSavingsOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(cancelTransferFromSavingsOp); }); }, utilFunctionTest, cancelTransferFromSavingsOp); @@ -305,7 +303,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with decline voting rights operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, declineVotingRightsOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(declineVotingRightsOp); }); }, utilFunctionTest, declineVotingRightsOp); @@ -315,7 +313,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with claim reward balance operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, claimRewardBalanceOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(claimRewardBalanceOp); }); }, utilFunctionTest, claimRewardBalanceOp); @@ -325,7 +323,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with delegate vesting shares operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, delegatedVestingSharesOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(delegatedVestingSharesOp); }); }, utilFunctionTest, delegateVestingSharesOp); @@ -335,7 +333,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with account create with delegation operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, accountCreateWithDelegationOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(accountCreateWithDelegationOp); }); }, utilFunctionTest, accountCreateWithDelegationOp); @@ -345,7 +343,7 @@ test.describe('Wax encrypted operations tests', () => { // XXX // test('Should be able to pass through encryption on transaction with witness set properties operation which does not support encryption', async () => { - // const retVal = await utilFunctionTest((tx: IEncryptingTransaction) => { + // const retVal = await utilFunctionTest(tx => { // tx.pushOperation(witnessSetPropertiesOp); // }); @@ -354,7 +352,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with account update 2 operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, accountUpdate2Op) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(accountUpdate2Op); }); }, utilFunctionTest, accountUpdate2Op); @@ -364,7 +362,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with create proposal operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, createProposalOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(createProposalOp); }); }, utilFunctionTest, createProposalOp); @@ -374,7 +372,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with update proposal votes operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, updateProposalVotesOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(updateProposalVotesOp); }); }, utilFunctionTest, updateProposalVotesOp); @@ -384,7 +382,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with remove proposal operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, removeProposalOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(removeProposalOp); }); }, utilFunctionTest, removeProposalOp); @@ -394,7 +392,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with update proposal operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, updateProposalOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(updateProposalOp); }); }, utilFunctionTest, updateProposalOp); @@ -404,7 +402,7 @@ test.describe('Wax encrypted operations tests', () => { test('Should be able to pass through encryption on transaction with collateralized converts operation which does not support encryption', async ({ waxTest }) => { const retVal = await waxTest(async (globals, utilFunctionTest, collateralizedConvertOp) => { - return await utilFunctionTest(globals, (tx: IEncryptingTransaction) => { + return await utilFunctionTest(globals, tx => { tx.pushOperation(collateralizedConvertOp); }); }, utilFunctionTest, collateralizedConvertOp); diff --git a/ts/wasm/__tests__/detailed/proto-protocol.ts b/ts/wasm/__tests__/detailed/proto-protocol.ts index db74bde543ecc974c3611fc9c88aacce1e95f5b0..c61e166af922a760dac46dbde8d68efca44283b8 100644 --- a/ts/wasm/__tests__/detailed/proto-protocol.ts +++ b/ts/wasm/__tests__/detailed/proto-protocol.ts @@ -33,7 +33,7 @@ test.describe('WASM Proto Protocol', () => { test('Should be able to serialize the transaction', async ({ wasmTest }) => { const retVal = await wasmTest(({ proto_protocol }, transaction) => { - return proto_protocol.cpp_serialize_transaction(transaction); + return proto_protocol.cpp_serialize_transaction(transaction, false); }, protoTx); expect(retVal.exception_message).toHaveLength(0); diff --git a/ts/wasm/__tests__/detailed/protocol.ts b/ts/wasm/__tests__/detailed/protocol.ts index cf2691faad878fc744a17cfd07ec0159dbd8eeee..639c6c7807e7c13062deebab31c5e261542e9760 100644 --- a/ts/wasm/__tests__/detailed/protocol.ts +++ b/ts/wasm/__tests__/detailed/protocol.ts @@ -33,9 +33,34 @@ test.describe('WASM Protocol', () => { expect(retVal.exception_message).toHaveLength(0); }); + + test('Should be able to convert between raw private key -> WIF formats', async ({ wasmTest }) => { + const retVal = await wasmTest(({ protocol }) => { + return protocol.cpp_convert_raw_private_key_to_wif('48a9c812cafcd35eb761501768ba7e2eb9a238853548556c2c38431f51d63030'); + }); + + expect(retVal).toBe('5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n'); + }); + + test('Should be able to convert between raw compressed public key -> WIF formats', async ({ wasmTest }) => { + const retVal = await wasmTest(({ protocol }) => { + return protocol.cpp_convert_raw_public_key_to_wif('02be643d4c424ac7cf2f3cf51dd048773cbdcee30b111adb30d89c27668c501705'); + }); + + expect(retVal).toBe('STM6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4'); + }); + + test('Should be able to convert between raw uncompressed public key -> WIF formats', async ({ wasmTest }) => { + const retVal = await wasmTest(({ protocol }) => { + return protocol.cpp_convert_raw_public_key_to_wif('04be643d4c424ac7cf2f3cf51dd048773cbdcee30b111adb30d89c27668c5017051a9cc2866c479818522ffd2b4a3d7a5a64d1b98c968f8f6ea2ef6745a637eb92'); + }); + + expect(retVal).toBe('STM6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4'); + }); + test('Should be able to generate binary metadata information - tx with vote operation', async ({ wasmTest }) => { const retVal = await wasmTest.dynamic(({ protocol }, transaction, parseChildrenFn) => { - const values = protocol.cpp_generate_binary_transaction_metadata(transaction, true); + const values = protocol.cpp_generate_binary_transaction_metadata(transaction, true, false); const parseBinaryChildren = eval(parseChildrenFn); @@ -50,7 +75,7 @@ test.describe('WASM Protocol', () => { }); test('Should be able to generate binary metadata information using hf26 pack type - tx with transfer', async ({ wasmTest }) => { const retVal = await wasmTest.dynamic(({ protocol }, transaction, parseChildrenFn) => { - const values = protocol.cpp_generate_binary_transaction_metadata(transaction, true); + const values = protocol.cpp_generate_binary_transaction_metadata(transaction, true, false); const parseBinaryChildren = eval(parseChildrenFn); @@ -66,7 +91,7 @@ test.describe('WASM Protocol', () => { test('Should be able to generate binary metadata information using legacy pack type - tx with transfer', async ({ wasmTest }) => { const retVal = await wasmTest.dynamic(({ protocol }, transaction, parseChildrenFn) => { - const values = protocol.cpp_generate_binary_transaction_metadata(transaction, false); + const values = protocol.cpp_generate_binary_transaction_metadata(transaction, false, false); const parseBinaryChildren = eval(parseChildrenFn); @@ -168,13 +193,24 @@ test.describe('WASM Protocol', () => { test('Should be able to serialize the transaction', async ({ wasmTest }) => { const retVal = await wasmTest(({ protocol }, transaction) => { - return protocol.cpp_serialize_transaction(transaction); + return protocol.cpp_serialize_transaction(transaction, false); }, transaction); expect(retVal.exception_message).toHaveLength(0); expect(retVal.content).toBe("ff86c404c24b152fb7610100046f746f6d076330666633336108657778686e6a626a98080000"); }); + test('Should be able to serialize the (stripped) transaction', async ({ wasmTest }) => { + const retVal = await wasmTest(({ protocol }, transaction) => { + /// Even transaction is unsigned, we can strip the signature container to preserve original binary form + // of the transaction i.e. specific to calculate its id + return protocol.cpp_serialize_transaction(transaction, true); + }, transaction); + + expect(retVal.exception_message).toHaveLength(0); + expect(retVal.content).toBe("ff86c404c24b152fb7610100046f746f6d076330666633336108657778686e6a626a980800"); + }); + test('Should be able to calculate sig digest of the transaction', async ({ wasmTest }) => { const retVal = await wasmTest(({ protocol }, transaction) => { return protocol.cpp_calculate_sig_digest(transaction, "beeab0de00000000000000000000000000000000000000000000000000000000"); diff --git a/ts/wasm/__tests__/detailed/protocol_benchmarks.ts b/ts/wasm/__tests__/detailed/protocol_benchmarks.ts index ff42b0a5054633a8703b8911da0271d121f165a0..ede49df46fccdb3589ea859ac5292a5757571b21 100644 --- a/ts/wasm/__tests__/detailed/protocol_benchmarks.ts +++ b/ts/wasm/__tests__/detailed/protocol_benchmarks.ts @@ -111,7 +111,7 @@ test.describe('WASM Protocol benchmarks', () => { utilFunctionTest('Serialize transaction', 7_500, () => { for(let i = 0; i < 7_500; ++i) - noDiscard += (protocol.cpp_serialize_transaction(transaction).content as string).length % 10 + i; + noDiscard += (protocol.cpp_serialize_transaction(transaction, false).content as string).length % 10 + i; return noDiscard; }); diff --git a/ts/wasm/lib/detailed/api/account_by_key_api/get_key_references.ts b/ts/wasm/lib/detailed/api/account_by_key_api/get_key_references.ts index ae1edce8935d92a3ed618305afc9723a60a3a67e..ecdec6cf5c99b4289b8b00c21575678e246d8fc4 100644 --- a/ts/wasm/lib/detailed/api/account_by_key_api/get_key_references.ts +++ b/ts/wasm/lib/detailed/api/account_by_key_api/get_key_references.ts @@ -1,14 +1,9 @@ -import type { TPublicKey } from "@hiveio/beekeeper"; -import { IsString, Validate } from "class-validator"; +import type { TPublicKey } from "../../interfaces"; -import { IsPublicKey } from "../../decorators/is_public_key.js"; - -export class GetKeyReferencesRequest { - @Validate(IsPublicKey, { each: true }) - public keys!: Array<TPublicKey>; +export interface GetKeyReferencesRequest { + keys: Array<TPublicKey>; } -export class GetKeyReferencesResponse { - @Validate(IsString.bind({ each: true }), { each: true }) - public accounts!: string[][]; +export interface GetKeyReferencesResponse { + accounts: string[][]; } diff --git a/ts/wasm/lib/detailed/api/block_api/get_block.ts b/ts/wasm/lib/detailed/api/block_api/get_block.ts index cc02ae4eaa1bfd7262454cc0074c8986b4f4b5ef..4e4d80e7024e44f965b5df4025e1cf5d174bdb6a 100644 --- a/ts/wasm/lib/detailed/api/block_api/get_block.ts +++ b/ts/wasm/lib/detailed/api/block_api/get_block.ts @@ -1,17 +1,9 @@ -import { IsNumber, IsOptional, Min, ValidateNested } from "class-validator"; -import { Type } from "class-transformer"; +import type { ApiBlock } from "../types/block.js"; -import { ApiBlock } from "../types/block.js"; - -export class GetBlockRequest { - @IsNumber() - @Min(0) - public block_num!: number; +export interface GetBlockRequest { + block_num: number; } -export class GetBlockResponse { - @ValidateNested() - @IsOptional() - @Type(() => ApiBlock) - public block?: ApiBlock; +export interface GetBlockResponse { + block?: ApiBlock; } diff --git a/ts/wasm/lib/detailed/api/block_api/get_block_header.ts b/ts/wasm/lib/detailed/api/block_api/get_block_header.ts index a0b0ab5ce0b7ddccd2cb8ef5a488e42ee06a2b74..11d526222b98b9d826372171dbde70342a846f70 100644 --- a/ts/wasm/lib/detailed/api/block_api/get_block_header.ts +++ b/ts/wasm/lib/detailed/api/block_api/get_block_header.ts @@ -1,16 +1,9 @@ -import { IsNumber, Min, ValidateNested } from "class-validator"; -import { Type } from "class-transformer"; +import type { ApiBlockHeader } from "../types/block.js"; -import { ApiBlockHeader } from "../types/block.js"; - -export class GetBlockHeaderRequest { - @IsNumber() - @Min(0) - public block_num!: number; +export interface GetBlockHeaderRequest { + block_num: number; } -export class GetBlockHeaderResponse { - @ValidateNested() - @Type(() => ApiBlockHeader) - public header!: ApiBlockHeader; +export interface GetBlockHeaderResponse { + header: ApiBlockHeader; } diff --git a/ts/wasm/lib/detailed/api/block_api/get_block_range.ts b/ts/wasm/lib/detailed/api/block_api/get_block_range.ts index 4ba02bf211342337b141a4c9e91e1e3e64f999b2..f34ea116f889b08e7a83b278acf9c1c76072c325 100644 --- a/ts/wasm/lib/detailed/api/block_api/get_block_range.ts +++ b/ts/wasm/lib/detailed/api/block_api/get_block_range.ts @@ -1,21 +1,10 @@ -import { IsNumber, Max, Min, ValidateNested } from "class-validator"; -import { Type } from "class-transformer"; +import type { ApiBlock } from "../types/block.js"; -import { ApiBlock } from "../types/block.js"; - -export class GetBlockRangeRequest { - @IsNumber() - @Min(0) - public starting_block_num!: number; - - @IsNumber() - @Min(0) - @Max(1000) - public count!: number; +export interface GetBlockRangeRequest { + starting_block_num: number; + count: number; } -export class GetBlockRangeResponse { - @ValidateNested({ each: true }) - @Type(() => ApiBlock) - public blocks!: Array<ApiBlock>; +export interface GetBlockRangeResponse { + blocks: Array<ApiBlock>; } diff --git a/ts/wasm/lib/detailed/api/database_api/find_accounts.ts b/ts/wasm/lib/detailed/api/database_api/find_accounts.ts index e19dbc92402463a16b8487eee4d4328f15c82607..53ddbb5fadb00172c109f1a1a2ca4479d8a239a9 100644 --- a/ts/wasm/lib/detailed/api/database_api/find_accounts.ts +++ b/ts/wasm/lib/detailed/api/database_api/find_accounts.ts @@ -1,19 +1,10 @@ -import { Type } from "class-transformer"; -import { IsBoolean, IsOptional, IsString, ValidateNested } from "class-validator"; - import { ApiAccount } from "../types/index.js"; -export class FindAccountsRequest { - @IsString({ each: true }) - public accounts!: string[]; - - @IsOptional() - @IsBoolean() - public delayed_votes_active?: boolean = true; +export interface FindAccountsRequest { + accounts: string[]; + delayed_votes_active: boolean; } -export class FindAccountsResponse { - @Type(() => ApiAccount) - @ValidateNested({ each: true }) - public accounts!: Array<ApiAccount>; +export interface FindAccountsResponse { + accounts: Array<ApiAccount>; } diff --git a/ts/wasm/lib/detailed/api/database_api/find_witnesses.ts b/ts/wasm/lib/detailed/api/database_api/find_witnesses.ts index 96e3780cc64cd45aa05de41b7a49eec37b37c97c..a8c1984ea4b4823226763f33fdd06ed8d218668f 100644 --- a/ts/wasm/lib/detailed/api/database_api/find_witnesses.ts +++ b/ts/wasm/lib/detailed/api/database_api/find_witnesses.ts @@ -1,19 +1,10 @@ -import { Type } from "class-transformer"; -import { IsBoolean, IsOptional, IsString, ValidateNested } from "class-validator"; +import type { ApiWitness } from "../types/index.js"; -import { ApiWitness} from "../types/index.js"; - -export class FindWitnessesRequest { - @IsString({ each: true }) - public owners!: string[]; - - @IsOptional() - @IsBoolean() - public delayed_votes_active?: boolean = true; +export interface FindWitnessesRequest { + owners: string[]; + delayed_votes_active: boolean; } -export class FindWitnessesResponse { - @Type(() => ApiWitness) - @ValidateNested({ each: true }) - public witnesses!: Array<ApiWitness>; +export interface FindWitnessesResponse { + witnesses: Array<ApiWitness>; } diff --git a/ts/wasm/lib/detailed/api/database_api/get_dynamic_global_properties.ts b/ts/wasm/lib/detailed/api/database_api/get_dynamic_global_properties.ts index 23bff8470e1b45d0d44acc5e60466bb824b994f3..d98e4af4b1e015e829c62790a0aa12ea44806b16 100644 --- a/ts/wasm/lib/detailed/api/database_api/get_dynamic_global_properties.ts +++ b/ts/wasm/lib/detailed/api/database_api/get_dynamic_global_properties.ts @@ -1,172 +1,55 @@ -import { IsDateString, IsHexadecimal, IsNumber, IsOptional, IsString, Validate, ValidateNested } from "class-validator"; -import { Type } from "class-transformer"; - -import { NaiAsset } from "../types/asset.js"; -import { IsNumberOrStringNumber } from "../../decorators/is_number_or_number_string.js"; - -export class GetDynamicGlobalPropertiesRequest {} - -export class GetDynamicGlobalPropertiesResponse { - @IsNumber() - public id!: number; - - @IsNumber() - public head_block_number!: number; - - @IsHexadecimal() - public head_block_id!: string; - - @IsDateString() - public time!: string; - - @IsString() - public current_witness!: string; - - @Validate(IsNumberOrStringNumber) - public total_pow!: string | number; - - @IsNumber() - public num_pow_witnesses!: number; - - @Type(() => NaiAsset) - @ValidateNested() - public virtual_supply!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public current_supply!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public confidential_supply!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public init_hbd_supply!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public current_hbd_supply!: NaiAsset; - - @IsNumber() - public current_remove_threshold!: number; - - @Type(() => NaiAsset) - @ValidateNested() - public confidential_hbd_supply!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public total_vesting_fund_hive!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public total_vesting_shares!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public total_reward_fund_hive!: NaiAsset; - - @IsString() - public total_reward_shares2!: string; - - @Type(() => NaiAsset) - @ValidateNested() - public pending_rewarded_vesting_shares!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public pending_rewarded_vesting_hive!: NaiAsset; - - @IsNumber() - public hbd_interest_rate!: number; - - @IsNumber() - public hbd_print_rate!: number; - - @IsNumber() - public maximum_block_size!: number; - - @Validate(IsNumberOrStringNumber) - public mid_voting_seconds!: number | string; - - @IsNumber() - public min_recurrent_transfers_recurrence!: number; - - @IsNumber() - @IsOptional() - public required_actions_partition_percent?: number; - - @IsNumber() - public current_aslot!: number; - - @IsString() - public recent_slots_filled!: string; - - @IsNumber() - public participation_count!: number; - - @IsNumber() - public last_irreversible_block_num!: number; - - @IsNumber() - public max_consecutive_recurrent_transfer_failures!: number; - - @IsNumber() - public max_open_recurrent_transfers!: number; - - @IsNumber() - public max_recurrent_transfer_end_date!: number; - - @IsOptional() - @IsNumber() - public target_votes_per_period?: number; - - @IsNumber() - public delegation_return_period!: number; - - @IsNumber() - public reverse_auction_seconds!: number; - - @IsNumber() - public available_account_subsidies!: number; - - @IsNumber() - public hbd_stop_percent!: number; - - @IsNumber() - public hbd_start_percent!: number; - - @IsDateString() - public next_daily_maintenance_time!: string; - - @IsDateString() - public next_maintenance_time!: string; - - @IsDateString() - public last_budget_time!: string; - - @IsNumber() - public content_reward_percent!: number; - - @IsNumber() - public vesting_reward_percent!: number; - - @IsOptional() - @IsNumber() - public sps_fund_percent?: number; - - @Type(() => NaiAsset) - @ValidateNested() - public sps_interval_ledger!: NaiAsset; - - @IsNumber() - public downvote_pool_percent!: number; - - @Validate(IsNumberOrStringNumber) - public early_voting_seconds!: number | string; - - @Type(() => NaiAsset) - @ValidateNested() - public smt_creation_fee!: NaiAsset; +import type { NaiAsset } from "../types/asset.js"; + +export interface GetDynamicGlobalPropertiesRequest {} + +export interface GetDynamicGlobalPropertiesResponse { + id: number; + head_block_number: number; + head_block_id: string; + time: string; + current_witness: string; + total_pow: string | number; + num_pow_witnesses: number; + virtual_supply: NaiAsset; + current_supply: NaiAsset; + confidential_supply: NaiAsset; + init_hbd_supply: NaiAsset; + current_hbd_supply: NaiAsset; + current_remove_threshold: number; + confidential_hbd_supply: NaiAsset; + total_vesting_fund_hive: NaiAsset; + total_vesting_shares: NaiAsset; + total_reward_fund_hive: NaiAsset; + total_reward_shares2: string; + pending_rewarded_vesting_shares: NaiAsset; + pending_rewarded_vesting_hive: NaiAsset; + hbd_interest_rate: number; + hbd_print_rate: number; + maximum_block_size: number; + mid_voting_seconds: number | string; + min_recurrent_transfers_recurrence: number; + required_actions_partition_percent?: number; + current_aslot: number; + recent_slots_filled: string; + participation_count: number; + last_irreversible_block_num: number; + max_consecutive_recurrent_transfer_failures: number; + max_open_recurrent_transfers: number; + max_recurrent_transfer_end_date: number; + target_votes_per_period?: number; + delegation_return_period: number; + reverse_auction_seconds: number; + available_account_subsidies: number; + hbd_stop_percent: number; + hbd_start_percent: number; + next_daily_maintenance_time: string; + next_maintenance_time: string; + last_budget_time: string; + content_reward_percent: number; + vesting_reward_percent: number; + sps_fund_percent?: number; + sps_interval_ledger: NaiAsset; + downvote_pool_percent: number; + early_voting_seconds: number | string; + smt_creation_fee: NaiAsset; } diff --git a/ts/wasm/lib/detailed/api/database_api/index.ts b/ts/wasm/lib/detailed/api/database_api/index.ts index 46ac88e6548949942fd0fbdac27ec3bc363dbb05..4d575a1867a98c1f007d9ac082301f7fcb58b0e1 100644 --- a/ts/wasm/lib/detailed/api/database_api/index.ts +++ b/ts/wasm/lib/detailed/api/database_api/index.ts @@ -1,3 +1,4 @@ export * from './find_accounts.js'; +export * from './find_witnesses.js'; export * from './get_dynamic_global_properties.js'; export * from './verify_authority.js'; \ No newline at end of file diff --git a/ts/wasm/lib/detailed/api/database_api/verify_authority.ts b/ts/wasm/lib/detailed/api/database_api/verify_authority.ts index 2eba71ae41e78df983340c48d7465836bab4c221..9fa88dd75f0e67898b4577662a7b51930433dc75 100644 --- a/ts/wasm/lib/detailed/api/database_api/verify_authority.ts +++ b/ts/wasm/lib/detailed/api/database_api/verify_authority.ts @@ -1,17 +1,10 @@ -import { Type } from "class-transformer"; -import { IsBoolean, ValidateNested, IsEnum } from "class-validator"; import { TTransactionPackType, ApiTransaction } from "../types" -export class VerifyAuthorityRequest { - @ValidateNested() - @Type(() => ApiTransaction) - public trx!: ApiTransaction; - - @IsEnum(TTransactionPackType) - public pack: TTransactionPackType = TTransactionPackType.HF_26; +export interface VerifyAuthorityRequest { + trx: ApiTransaction; + pack: TTransactionPackType; }; -export class VerifyAuthorityResponse { - @IsBoolean() - public valid: boolean = false; +export interface VerifyAuthorityResponse { + valid: boolean; }; diff --git a/ts/wasm/lib/detailed/api/network_broadcast_api/broadcast_transaction.ts b/ts/wasm/lib/detailed/api/network_broadcast_api/broadcast_transaction.ts index d282a24ad07c0eb5582f3d8e2a64626d3ed302fb..d26df915a14789d4897f8579e6eaafba44ce44c1 100644 --- a/ts/wasm/lib/detailed/api/network_broadcast_api/broadcast_transaction.ts +++ b/ts/wasm/lib/detailed/api/network_broadcast_api/broadcast_transaction.ts @@ -1,28 +1,8 @@ -import { Type } from "class-transformer" -import { IsNumber, ValidateNested } from "class-validator" - -import type { ITransaction } from "../../interfaces"; - import { ApiTransaction } from "../types/transaction.js"; -import { WaxError } from "../../errors.js"; - -export class BroadcastTransactionRequest { - public constructor(trx?: ITransaction) { - if(typeof trx === 'undefined') - return; - - if(!trx.isSigned()) - throw new WaxError('Transaction requires at least one signature.'); - - this.trx = Object.assign(new ApiTransaction(), JSON.parse(trx.toApi())); - } - - @ValidateNested() - @Type(() => ApiTransaction) - public trx!: ApiTransaction; - @IsNumber() - public max_block_age: number = -1; +export interface BroadcastTransactionRequest { + trx: ApiTransaction; + max_block_age: number; } -export class BroadcastTransactionResponse {} +export interface BroadcastTransactionResponse {} diff --git a/ts/wasm/lib/detailed/api/rc_api/find_rc_accounts.ts b/ts/wasm/lib/detailed/api/rc_api/find_rc_accounts.ts index a157691d6ed7364c0f63b4a5d90f661de4146d6c..357f8941cb10e4d0768954261ee0e5071e1e5458 100644 --- a/ts/wasm/lib/detailed/api/rc_api/find_rc_accounts.ts +++ b/ts/wasm/lib/detailed/api/rc_api/find_rc_accounts.ts @@ -1,32 +1,16 @@ -import { Type } from "class-transformer"; -import { IsString, Validate, ValidateNested } from "class-validator"; - import { ApiManabar, NaiAsset } from "../types/index.js"; -import { IsNumberOrStringNumber } from "../../decorators/is_number_or_number_string.js"; -export class FindRcAccountsRequest { - @IsString({ each: true }) - public accounts!: string[]; +export interface FindRcAccountsRequest { + accounts: string[]; } -export class RcAccount { - @IsString() - public account!: string; - - @Type(() => ApiManabar) - @ValidateNested() - public rc_manabar!: ApiManabar; - - @Type(() => NaiAsset) - @ValidateNested() - public max_rc_creation_adjustment!: NaiAsset; - - @Validate(IsNumberOrStringNumber) - public max_rc!: string | number; +export interface RcAccount { + account: string; + rc_manabar: ApiManabar; + max_rc_creation_adjustment: NaiAsset; + max_rc: string | number; } -export class FindRcAccountsResponse { - @Type(() => RcAccount) - @ValidateNested({ each: true }) - public rc_accounts!: Array<RcAccount>; +export interface FindRcAccountsResponse { + rc_accounts: Array<RcAccount>; } diff --git a/ts/wasm/lib/detailed/api/types/account.ts b/ts/wasm/lib/detailed/api/types/account.ts index 4a82ac0901f331ab34fd05f1359676ef0aa3cb1c..8f5a5f389db08b47e175dc4637cc4ac8157b55ea 100644 --- a/ts/wasm/lib/detailed/api/types/account.ts +++ b/ts/wasm/lib/detailed/api/types/account.ts @@ -1,263 +1,93 @@ -import type { TPublicKey } from "@hiveio/beekeeper"; -import { Type } from "class-transformer"; -import { IsArray, IsBoolean, IsDateString, IsNumber, IsNumberString, IsString, Validate, ValidateNested } from "class-validator"; - import { NaiAsset } from "./asset.js"; -import { IsNumberOrStringNumber } from "../../decorators/is_number_or_number_string.js"; -import { IsPublicKey } from "../../decorators/is_public_key.js"; -import { IsAuth } from "../../decorators/is_auth.js"; - -export class ApiAccountAuth { - @IsString() - public "0"!: string; +import type { TPublicKey } from "../../interfaces"; - @IsNumber() - public "1"!: number; +export interface ApiAccountAuth { + "0": string; + "1": number; } -export class ApiKeyAuth { - @Validate(IsPublicKey) - public "0"!: TPublicKey; - - @IsNumber() - public "1"!: number; +export interface ApiKeyAuth { + "0": TPublicKey; + "1": number; } -export class ApiDelayedVote { - @IsDateString() - public time!: string; - - @Validate(IsNumberOrStringNumber) - public val!: number | string; +export interface ApiDelayedVote { + time: string; + val: number | string; } -export class ApiAuthority { - @IsNumber() - public weight_threshold!: number; - - @IsArray() - @Type(() => ApiAccountAuth) - @Validate(IsAuth) - public account_auths!: Array<ApiAccountAuth>; - - @IsArray() - @Type(() => ApiKeyAuth) - @Validate(IsAuth) - public key_auths!: Array<ApiKeyAuth>; +export interface ApiAuthority { + weight_threshold: number; + account_auths: Array<ApiAccountAuth>; + key_auths: Array<ApiKeyAuth>; } -export class ApiManabar { - @Validate(IsNumberOrStringNumber) - public current_mana!: string | number; - - @IsNumber() - public last_update_time!: number; +export interface ApiManabar { + current_mana: string | number; + last_update_time: number; } -export class ApiAccount { - @IsNumber() - public id!: number; - - @IsString() - public name!: string; - - @Type(() => ApiAuthority) - @ValidateNested() - public owner!: ApiAuthority; - - @Type(() => ApiAuthority) - @ValidateNested() - public active!: ApiAuthority; - - @Type(() => ApiAuthority) - @ValidateNested() - public posting!: ApiAuthority; - - @Validate(IsPublicKey) - public memo_key!: TPublicKey; - - @IsString() - public json_metadata!: string; - - @IsString() - public posting_json_metadata!: string; - - @IsString() - public proxy!: string; - - @IsDateString() - public previous_owner_update!: string; - - @IsDateString() - public last_owner_update!: string; - - @IsDateString() - public last_account_update!: string; - - @IsDateString() - public created!: string; - - @IsBoolean() - public mined!: boolean; - - @IsString() - public recovery_account!: string; - - @IsDateString() - public last_account_recovery!: string; - - @IsString() - public reset_account!: string; - - @IsNumber() - public comment_count!: number; - - @IsNumber() - public lifetime_vote_count!: number; - - @IsNumber() - public post_count!: number; - - @IsBoolean() - public can_vote!: boolean; - - @Type(() => ApiManabar) - @ValidateNested() - public voting_manabar!: ApiManabar; - - @Type(() => ApiManabar) - @ValidateNested() - public downvote_manabar!: ApiManabar; - - @Type(() => NaiAsset) - @ValidateNested() - public balance!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public savings_balance!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public hbd_balance!: NaiAsset; - - @IsNumberString() - public hbd_seconds!: string; - - @IsDateString() - public hbd_seconds_last_update!: string; - - @IsDateString() - public hbd_last_interest_payment!: string; - - @Type(() => NaiAsset) - @ValidateNested() - public savings_hbd_balance!: NaiAsset; - - @IsNumberString() - public savings_hbd_seconds!: string; - - @IsDateString() - public savings_hbd_seconds_last_update!: string; - - @IsDateString() - public savings_hbd_last_interest_payment!: string; - - @IsNumber() - public savings_withdraw_requests!: number; - - @Type(() => NaiAsset) - @ValidateNested() - public reward_hbd_balance!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public reward_hive_balance!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public reward_vesting_balance!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public reward_vesting_hive!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public vesting_shares!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public delegated_vesting_shares!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public received_vesting_shares!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public vesting_withdraw_rate!: NaiAsset; - - @Type(() => NaiAsset) - @ValidateNested() - public post_voting_power!: NaiAsset; - - @IsDateString() - public next_vesting_withdrawal!: string; - - @Validate(IsNumberOrStringNumber) - public withdrawn!: number | string; - - @Validate(IsNumberOrStringNumber) - public to_withdraw!: number | string; - - @IsNumber() - public withdraw_routes!: number; - - @IsNumber() - public pending_transfers!: number; - - @Validate(IsNumberOrStringNumber) - public curation_rewards!: number | string; - - @Validate(IsNumberOrStringNumber) - public posting_rewards!: number | string; - - @Validate(IsNumberOrStringNumber, { each: true }) - public proxied_vsf_votes!: Array<string | number>; - - @IsNumber() - public witnesses_voted_for!: number; - - @IsDateString() - public last_post!: string; - - @IsDateString() - public last_root_post!: string; - - @IsDateString() - public last_post_edit!: string; - - @IsDateString() - public last_vote_time!: string; - - @IsNumber() - public post_bandwidth!: number; - - @Validate(IsNumberOrStringNumber) - public pending_claimed_accounts!: number | string; - - @IsNumber() - public open_recurrent_transfers!: number; - - @IsBoolean() - public is_smt!: boolean; - - @IsArray() - @Type(() => ApiDelayedVote) - @ValidateNested({ each: true }) - public delayed_votes!: ApiDelayedVote[]; - - @IsDateString() - public governance_vote_expiration_ts!: string; +export interface ApiAccount { + id: number; + name: string; + owner: ApiAuthority; + active: ApiAuthority; + posting: ApiAuthority; + memo_key: TPublicKey; + json_metadata: string; + posting_json_metadata: string; + proxy: string; + previous_owner_update: string; + last_owner_update: string; + last_account_update: string; + created: string; + mined: boolean; + recovery_account: string; + last_account_recovery: string; + reset_account: string; + comment_count: number; + lifetime_vote_count: number; + post_count: number; + can_vote: boolean; + voting_manabar: ApiManabar; + downvote_manabar: ApiManabar; + balance: NaiAsset; + savings_balance: NaiAsset; + hbd_balance: NaiAsset; + hbd_seconds: string; + hbd_seconds_last_update: string; + hbd_last_interest_payment: string; + savings_hbd_balance: NaiAsset; + savings_hbd_seconds: string; + savings_hbd_seconds_last_update: string; + savings_hbd_last_interest_payment: string; + savings_withdraw_requests: number; + reward_hbd_balance: NaiAsset; + reward_hive_balance: NaiAsset; + reward_vesting_balance: NaiAsset; + reward_vesting_hive: NaiAsset; + vesting_shares: NaiAsset; + delegated_vesting_shares: NaiAsset; + received_vesting_shares: NaiAsset; + vesting_withdraw_rate: NaiAsset; + post_voting_power: NaiAsset; + next_vesting_withdrawal: string; + withdrawn: number | string; + to_withdraw: number | string; + withdraw_routes: number; + pending_transfers: number; + curation_rewards: number | string; + posting_rewards: number | string; + proxied_vsf_votes: Array<string | number>; + witnesses_voted_for: number; + last_post: string; + last_root_post: string; + last_post_edit: string; + last_vote_time: string; + post_bandwidth: number; + pending_claimed_accounts: number | string; + open_recurrent_transfers: number; + is_smt: boolean; + delayed_votes: ApiDelayedVote[]; + governance_vote_expiration_ts: string; } diff --git a/ts/wasm/lib/detailed/api/types/asset.ts b/ts/wasm/lib/detailed/api/types/asset.ts index a38fa58d316bc37434b7dd92a6e479f1a789e7b1..a701acc068c0a3be6499c432fa5876558b0b8e95 100644 --- a/ts/wasm/lib/detailed/api/types/asset.ts +++ b/ts/wasm/lib/detailed/api/types/asset.ts @@ -1,14 +1,5 @@ -import { IsNumber, IsString, Validate } from "class-validator"; - -import { IsNaiString } from "../../decorators/is_nai_string.js"; - -export class NaiAsset { - @IsString() - public amount!: string; - - @IsNumber() - public precision!: number; - - @Validate(IsNaiString) - public nai!: string; +export interface NaiAsset { + amount: string; + precision: number; + nai: string; } diff --git a/ts/wasm/lib/detailed/api/types/block.ts b/ts/wasm/lib/detailed/api/types/block.ts index 17d7ec2ad4d670319f631c57aff12c72f70b6bc4..b89a3ab553c4d00feb4f4a40a4f229aba64f87b1 100644 --- a/ts/wasm/lib/detailed/api/types/block.ts +++ b/ts/wasm/lib/detailed/api/types/block.ts @@ -1,40 +1,17 @@ -import { Type } from "class-transformer"; -import { IsDateString, IsHexadecimal, IsObject, IsString, Validate, ValidateNested } from "class-validator"; - import { ApiTransaction } from "./transaction.js"; -import { IsPublicKey } from "../../decorators/is_public_key.js"; - -export class ApiBlockHeader { - @IsHexadecimal() - public previous!: string; - - @IsDateString() - public timestamp!: string; - - @IsString() - public witness!: string; - - @IsHexadecimal() - public transaction_merkle_root!: string; - @IsObject({ each: true }) - public extensions: object[] = []; +export interface ApiBlockHeader { + previous: string; + timestamp: string; + witness: string; + transaction_merkle_root: string; + extensions: object[]; } -export class ApiBlock extends ApiBlockHeader { - @IsHexadecimal() - public witness_signature!: string; - - @ValidateNested({ each: true }) - @Type(() => ApiTransaction) - public transactions: Array<ApiTransaction> = []; - - @IsHexadecimal() - public block_id!: string; - - @Validate(IsPublicKey) - public signing_key!: string; - - @IsHexadecimal({ each: true }) - public transaction_ids: string[] = []; +export interface ApiBlock extends ApiBlockHeader { + witness_signature: string; + transactions: Array<ApiTransaction>; + block_id: string; + signing_key: string; + transaction_ids: string[]; } diff --git a/ts/wasm/lib/detailed/api/types/transaction.ts b/ts/wasm/lib/detailed/api/types/transaction.ts index 017380c7719a333d364321781bdc4e4690aa6c91..a30714af10d15117958dfb4c229f49156af374be 100644 --- a/ts/wasm/lib/detailed/api/types/transaction.ts +++ b/ts/wasm/lib/detailed/api/types/transaction.ts @@ -1,58 +1,13 @@ -import { type ITransaction } from "../../interfaces.js"; -import { Type, plainToInstance } from "class-transformer"; -import { Min, Max, IsDateString, IsInt, IsObject, IsString, ValidateNested } from "class-validator"; - -export class ApiOperation { - @IsString() - public type!: string; - - @IsObject() - public value!: object; +export interface ApiOperation { + type: string; + value: object; } -export class ApiTransaction { - /** - * Constructs new ApiTransaction object - * - * @param {?object} apiTransaction optional API object either from the remote Node or {@link ITransaction.toApiJson} - * - * @example - * ```ts - * new ApiTransaction(transactionBuilder.toApiJson()); - * ``` - */ - public constructor(apiTransaction?: object) { - if(apiTransaction !== undefined) { - const { operations, ...otherTransactionData } = apiTransaction as any; - - Object.assign(this, otherTransactionData); - - if(Array.isArray(operations)) - for(const op of operations) - this.operations.push(plainToInstance(ApiOperation, op)); - } - } - - @IsInt() - @Min(0) // Should be set to min/max. uint16 value - @Max(65535) - public ref_block_num!: number; - - @IsInt() - @Min(0) - @Max(4294967295) - public ref_block_prefix!: number; - - @IsDateString() - public expiration!: string; - - @ValidateNested({ each: true }) - @Type(() => ApiOperation) - public operations: Array<ApiOperation> = []; - - @IsObject({ each: true }) - public extensions: object[] = []; - - @IsString({ each: true }) - public signatures: string[] = []; +export interface ApiTransaction { + ref_block_num: number; + ref_block_prefix: number; + expiration: string; + operations: Array<ApiOperation>; + extensions: object[]; + signatures: string[]; } diff --git a/ts/wasm/lib/detailed/api/types/witness.ts b/ts/wasm/lib/detailed/api/types/witness.ts index a93c7c70adbbd7e9442faebeecf76af140d67b17..e175360864b53ab70591cabb03efdce8d1bf46b2 100644 --- a/ts/wasm/lib/detailed/api/types/witness.ts +++ b/ts/wasm/lib/detailed/api/types/witness.ts @@ -1,18 +1,12 @@ -import { IsDateString, IsNumber, IsString, Validate } from "class-validator"; -import { IsPublicKey } from "../../decorators/is_public_key"; -import { TPublicKey } from "@hiveio/beekeeper"; - -export class ApiWitness { - @IsNumber() - public id!: number; - - @IsString() - public owner!: string; - - @IsDateString() - public created!: string; - - @Validate(IsPublicKey) - public signing_key!: TPublicKey; +import type { TPublicKey } from "../../interfaces"; + +export interface ApiWitness { + id: number; + owner: string; + created: string; + signing_key: TPublicKey; + total_missed: number; + last_confirmed_block_num: number; + runningVersion: string; }; diff --git a/ts/wasm/lib/detailed/base_api.ts b/ts/wasm/lib/detailed/base_api.ts index ee9826488d6e1734ba57f76ad87adb7dd012f099..a51f6f300e193dcef4ca129dfdaf5885aae754b0 100644 --- a/ts/wasm/lib/detailed/base_api.ts +++ b/ts/wasm/lib/detailed/base_api.ts @@ -1,6 +1,4 @@ -import type { IBeekeeperUnlockedWallet, TPublicKey } from "@hiveio/beekeeper"; - -import type { IBinaryViewArrayNode, IBinaryViewNode, IBinaryViewOutputData, IBrainKeyData, IHiveAssetData, IManabarData, IPrivateKeyData, ITransaction, IWaxBaseInterface, TBlockHash, THexString, TNaiAssetConvertible, TNaiAssetSource, TTimestamp } from "./interfaces"; +import type { IBinaryViewArrayNode, IBinaryViewNode, IBinaryViewOutputData, IBrainKeyData, IHiveAssetData, IManabarData, IPrivateKeyData, ITransaction, IWaxBaseInterface, TBlockHash, THexString, TNaiAssetConvertible, TNaiAssetSource, TPublicKey, TTimestamp } from "./interfaces"; import type { binary_data_node, json_price, MainModule, proto_protocol, protocol, result, VectorBinaryDataNode, VectorString, witness_set_properties_data, wax_authorities } from "../build_wasm/wax.common"; import type { IChainConfig } from "../build_wasm/config"; import type { ApiOperation, NaiAsset } from "./api"; @@ -18,10 +16,9 @@ import Long from "long"; import { WaxFormatter } from "./formatters/waxify.js"; import { isNaiAsset } from "./util/asset_util.js"; -import { plainToInstance } from "class-transformer"; -import { validateSync } from "class-validator"; import type { AccountAuthorityUpdateOperation } from "./complex_operations"; // only for TypeDoc purposes :-( +import { ISignatureProvider } from "./extensions/signatures"; const PERCENT_VALUE_DOUBLE_PRECISION = 100; export const ONE_HUNDRED_PERCENT = 100 * PERCENT_VALUE_DOUBLE_PRECISION; @@ -181,15 +178,10 @@ export class WaxBaseApi implements IWaxBaseInterface { return props; } - public convertTransactionToBinaryForm(transaction: ApiTransaction): THexString { - const validationErrors = validateSync(plainToInstance(ApiTransaction, transaction)); - - if(validationErrors.length > 0) - throw new WaxError(`Transaction validation failed: ${validationErrors.join(", ")}`); - + public convertTransactionToBinaryForm(transaction: ApiTransaction, stripToUnsignedTransaction: boolean = false): THexString { const tx = this.createTransactionFromJson(transaction); - const conversionResult = safeWasmCall(() => this.proto.cpp_serialize_transaction(tx.toString())); + const conversionResult = safeWasmCall(() => this.proto.cpp_serialize_transaction(tx.toString(), stripToUnsignedTransaction)); return this.extract(conversionResult); } @@ -197,11 +189,6 @@ export class WaxBaseApi implements IWaxBaseInterface { public convertTransactionFromBinaryForm(transaction: THexString): ApiTransaction { const conversionResult = safeWasmCall(() => this.protocol.cpp_deserialize_transaction(transaction)); - const validationErrors = validateSync(plainToInstance(ApiTransaction, JSON.parse(this.extract(conversionResult)))); - - if(validationErrors.length > 0) - throw new WaxError(`Transaction validation failed: ${validationErrors.join(", ")}`); - return JSON.parse(this.extract(conversionResult)); } @@ -358,7 +345,7 @@ export class WaxBaseApi implements IWaxBaseInterface { return this.extract(publicKey); } - public encrypt(wallet: IBeekeeperUnlockedWallet, content: string, mainEncryptionKey: TPublicKey, otherEncryptionKey?: TPublicKey, nonce?: number): string { + public encrypt(wallet: ISignatureProvider, content: string, mainEncryptionKey: TPublicKey, otherEncryptionKey?: TPublicKey, nonce?: number): string { const encrypted = wallet.encryptData(content, mainEncryptionKey, otherEncryptionKey, nonce); return safeWasmCall(() => this.proto.cpp_crypto_memo_dump_string({ @@ -388,7 +375,7 @@ export class WaxBaseApi implements IWaxBaseInterface { return this.cachedConfig; } - public decrypt(wallet: IBeekeeperUnlockedWallet, encrypted: string): string { + public decrypt(wallet: ISignatureProvider, encrypted: string): string { const data = safeWasmCall(() => this.proto.cpp_crypto_memo_from_string(encrypted)); return wallet.decryptData(data.content as string, data.from as string, data.to as string); @@ -501,6 +488,16 @@ export class WaxBaseApi implements IWaxBaseInterface { }; } + public convertRawPrivateKeyToWif(rawPrivateKey: THexString): string { + const wif = safeWasmCall(() => this.proto.cpp_convert_raw_private_key_to_wif(rawPrivateKey)); + return wif; + } + + public convertRawPublicKeyToWif(rawPublicKey: THexString): string { + const wif = safeWasmCall(() => this.proto.cpp_convert_raw_public_key_to_wif(rawPublicKey)); + return wif; + } + public calculateAccountHp(vests: TNaiAssetSource, totalVestingFundHive: TNaiAssetSource, totalVestingShares: TNaiAssetSource): NaiAsset { const vestsAsset = this.createAssetWithRequiredSymbol(EAssetName.VESTS, vests); const totalVestingFundHiveAsset = this.createAssetWithRequiredSymbol(EAssetName.HIVE, totalVestingFundHive); diff --git a/ts/wasm/lib/detailed/chain_api.ts b/ts/wasm/lib/detailed/chain_api.ts index d7f78d9080417d30379178fc9f375ba00a3395c3..7f0a4450787191cb0d788da46bce7c5d97a4ceaa 100644 --- a/ts/wasm/lib/detailed/chain_api.ts +++ b/ts/wasm/lib/detailed/chain_api.ts @@ -1,7 +1,6 @@ -import type { IBeekeeperUnlockedWallet } from "@hiveio/beekeeper"; import type { IHiveChainInterface, IManabarData, ITransaction, IOnlineTransaction, TTimestamp, TPublicKey, TWaxExtended, TBlockHash, TWaxRestExtended, TDeepWaxApiRequestPartial } from "./interfaces"; import type { MainModule, MapStringUInt16, wax_authority, wax_authorities } from "../build_wasm/wax.common"; -import { ApiAuthority, ApiWitness, BroadcastTransactionRequest, type ApiAccount, type ApiManabar, type ApiTransaction, type RcAccount } from "./api"; +import { ApiAuthority, ApiWitness, type ApiAccount, type ApiManabar, type ApiTransaction, type RcAccount } from "./api"; import { WaxError } from "./errors.js"; import { safeWasmCall } from './util/wasm_errors.js'; @@ -15,6 +14,7 @@ import Long from "long"; import { ApiCaller, TRequestInterceptor, TResponseInterceptor } from "./util/api_caller"; import { TAccountName } from "./hive_apps_operations"; +import { ISignatureProvider } from "./extensions/signatures"; export enum EManabarType { UPVOTE = 0, @@ -94,10 +94,10 @@ export class HiveChainApi extends WaxBaseApi implements IHiveChainInterface { if ("performOnChainVerification" in transaction) await transaction.performOnChainVerification(); - const request = new BroadcastTransactionRequest(); - request.trx = toBroadcast as ApiTransaction; - - await this.api.network_broadcast_api.broadcast_transaction(request); + await this.api.network_broadcast_api.broadcast_transaction({ + max_block_age: -1, + trx: toBroadcast as ApiTransaction + }); } public withProxy(requestInterceptor: TRequestInterceptor, responseInterceptor: TResponseInterceptor): HiveChainApi { @@ -166,7 +166,7 @@ export class HiveChainApi extends WaxBaseApi implements IHiveChainInterface { } private async findAccountsNoThrow(...accountNames: string[]): Promise<Array<ApiAccount>> { - const { accounts } = await this.api.database_api.find_accounts({ accounts: accountNames }); + const { accounts } = await this.api.database_api.find_accounts({ accounts: accountNames, delayed_votes_active: true }); return accounts; } @@ -182,7 +182,7 @@ export class HiveChainApi extends WaxBaseApi implements IHiveChainInterface { } private async findWitnessAccountsNoThrow(...witnessNames: string[]): Promise<Array<ApiWitness>> { - const { witnesses } = await this.api.database_api.find_witnesses({ owners: witnessNames }); + const { witnesses } = await this.api.database_api.find_witnesses({ owners: witnessNames, delayed_votes_active: true }); return witnesses; } @@ -258,7 +258,7 @@ export class HiveChainApi extends WaxBaseApi implements IHiveChainInterface { return retVal; } - public async encryptForAccounts(wallet: IBeekeeperUnlockedWallet, content: string, fromAccount: string, toAccount: string): Promise<string> { + public async encryptForAccounts(wallet: ISignatureProvider, content: string, fromAccount: string, toAccount: string): Promise<string> { let from: string, to: string; ([ { memo_key: from }, { memo_key: to } ] = await this.findAccounts(...[... new Set([ fromAccount, toAccount ])])); diff --git a/ts/wasm/lib/detailed/chain_api_data.ts b/ts/wasm/lib/detailed/chain_api_data.ts index 1cbbd86503e51ab13f2c92896d31a32d554bffa8..7f632625fa54add1cf283e1e13b510127a4b7b68 100644 --- a/ts/wasm/lib/detailed/chain_api_data.ts +++ b/ts/wasm/lib/detailed/chain_api_data.ts @@ -13,7 +13,7 @@ import { OperationTypeCountsRequest, OperationTypeCountsResponse } from "./rest- import { GetWitnessesByNameRequest, SingleWitnessResponse } from "./rest-api/hafbe/witnesses/by-name.js"; import { GetAllWitnessesRequest } from "./rest-api/hafbe/witnesses/all.js"; -export const HiveRestApiTypes = { +export type HiveRestApiTypes = { 'hafbe-api': { witnesses: { params: GetAllWitnessesRequest, @@ -34,7 +34,22 @@ export const HiveRestApiTypes = { } }; -export const HiveApiTypes = { +export const HiveRestApiTypes = { + 'hafbe-api': { + witnesses: { + responseArray: true, + accountName: { + urlPath: "{accountName}" + } + }, + operationTypeCounts: { + responseArray: true, + urlPath: 'operation-type-counts' + } + } +} as HiveRestApiTypes; + +export type HiveApiTypes = { account_by_key_api: { get_key_references: { params: GetKeyReferencesRequest, @@ -86,3 +101,5 @@ export const HiveApiTypes = { } } }; + +export const HiveApiTypes = {} as HiveApiTypes; diff --git a/ts/wasm/lib/detailed/complex_operations/account_update.ts b/ts/wasm/lib/detailed/complex_operations/account_update.ts index 9b6f16074cce81031116818ef7f51d2f1a655436..3aaf52b72d90356b908795d42e7fa87d6eef1789 100644 --- a/ts/wasm/lib/detailed/complex_operations/account_update.ts +++ b/ts/wasm/lib/detailed/complex_operations/account_update.ts @@ -6,12 +6,14 @@ import { HiveAccountCategory } from "./role_classes/categories/hive_authority/in import { RoleCategoryBase } from "./role_classes/role_category_base.js"; import { WaxError } from "../errors.js"; +export type { THiveRoles, HiveAccountCategory, HiveRoleAuthorityDefinition, HiveRoleMemoKeyDefinition } from "./role_classes/categories/hive_authority/index.js"; + // Here are all of the role categories. They are automatically parsed. Add new categories here -const AuthorityRoleCategories = [ +export const AuthorityRoleCategories = [ HiveAccountCategory ] as const satisfies Readonly<Array<(new () => RoleCategoryBase<any>)>>; -type UnionToIntersection<U> = +export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; diff --git a/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/hive_role_authority_definition.ts b/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/hive_role_authority_definition.ts index e90ea2a435f761bb300163a761f726123a28d1fa..eb7b0fb2b98e7439636c4e189999d82f66fab0d7 100644 --- a/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/hive_role_authority_definition.ts +++ b/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/hive_role_authority_definition.ts @@ -1,8 +1,9 @@ -import type { TPublicKey } from "@hiveio/beekeeper"; import { authority } from "../../../../protocol.js"; import { TAccountName } from "../../../../hive_apps_operations/index.js"; import { WaxError } from "../../../../errors.js"; import { LevelBase } from "../../level_base.js"; +import type { TPublicKey } from "../../../../interfaces"; +import { structuredClone } from "../../../../shims/structuredclone.js"; export class HiveRoleAuthorityDefinition<TRole extends string> extends LevelBase<TRole> { public constructor( @@ -108,7 +109,6 @@ export class HiveRoleAuthorityDefinition<TRole extends string> extends LevelBase * Adds an account or key to the currently selected role with specified weight. * If the account or key already exists, its weight is updated. * - * @note If you want to change the role, you need to call {@link withRole} method first. * @param {TPublicKey | TAccountName} accountOrKey Account or key to be added to the currently selected role. * @param {?number} weight Account or key weight in the authority. Default is 1. * @returns itself @@ -124,7 +124,6 @@ export class HiveRoleAuthorityDefinition<TRole extends string> extends LevelBase /** * Replaces the account or key with a new one in the currently selected role or changes the weight of the existing account or key. * - * @note If you want to change the role, you need to call {@link withRole} method first. * @param {TPublicKey | TAccountName} accountOrKey Account or key to be added to the currently selected role. * @param {number} weight Account or key weight in the authority. * @param {(TPublicKey | TAccountName)} newKeyOrAccount Account or key to replace the old one. If not provided, the account or key is not replaced, but weight is changed. diff --git a/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/hive_role_memo_key.ts b/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/hive_role_memo_key.ts index b325a6195f23cb676bef3688c34835e6a40f1786..325bb0bb98be42d5f0a0a39c41f812a0191f8d76 100644 --- a/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/hive_role_memo_key.ts +++ b/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/hive_role_memo_key.ts @@ -1,6 +1,6 @@ -import type { TPublicKey } from "@hiveio/beekeeper"; import { WaxError } from "../../../../errors.js"; import { LevelBase } from "../../level_base.js"; +import type { TPublicKey } from "../../../../interfaces"; export class HiveRoleMemoKeyDefinition extends LevelBase<"memo"> { public constructor() { diff --git a/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/index.ts b/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/index.ts index 65a26099acd1d08559f404af24acb6e0386b9249..6b1596a973afb2abf056584b507a64fa9c0bdc7a 100644 --- a/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/index.ts +++ b/ts/wasm/lib/detailed/complex_operations/role_classes/categories/hive_authority/index.ts @@ -8,6 +8,8 @@ import { WaxError } from "../../../../errors.js"; import { HiveRoleAuthorityDefinition } from "./hive_role_authority_definition.js"; import { HiveRoleMemoKeyDefinition } from "./hive_role_memo_key.js"; +export type { HiveRoleAuthorityDefinition, HiveRoleMemoKeyDefinition } ; + export type THiveRoles = { active: HiveRoleAuthorityDefinition<"active">; owner: HiveRoleAuthorityDefinition<"owner">; @@ -34,7 +36,7 @@ export class HiveAccountCategory extends RoleCategoryBase<THiveRoles> { this.HIVE_MAX_AUTHORITY_MEMBERSHIP = Number.parseInt(chain.config.HIVE_MAX_AUTHORITY_MEMBERSHIP); - const { accounts: [chainAccount] } = await chain.api.database_api.find_accounts({ accounts: [account] }); + const { accounts: [chainAccount] } = await chain.api.database_api.find_accounts({ accounts: [account], delayed_votes_active: true }); const checkOwnerTimeDiff = (time: string): boolean => { // owner_update_limit_mgr.cpp return Date.now() - new Date(`${time}Z`).getTime() > Number.parseInt(chain.config.HIVE_OWNER_UPDATE_LIMIT) / 1000; diff --git a/ts/wasm/lib/detailed/complex_operations/witness_set_properties.ts b/ts/wasm/lib/detailed/complex_operations/witness_set_properties.ts index f8989f9ebff1dc4422b6cb98eb8c9516de21adb0..c130ed9929457e60ebf6e06bd7d3a6fda52edadd 100644 --- a/ts/wasm/lib/detailed/complex_operations/witness_set_properties.ts +++ b/ts/wasm/lib/detailed/complex_operations/witness_set_properties.ts @@ -1,12 +1,12 @@ import { asset, operation, witness_set_properties } from "../protocol.js"; import { OperationBase, IOperationSink } from "../operation_base.js"; import { type witness_set_properties_data } from "../../build_wasm/wax.common.js"; -import { type TPublicKey } from "@hiveio/beekeeper"; import { EAssetName, type WaxBaseApi } from '../base_api.js'; import type Long from "long"; import { TAccountName } from "../hive_apps_operations/index.js"; +import type { TPublicKey } from "../interfaces"; -type TInternalAsset = asset | Long | string | BigInt | number; +export type TInternalAsset = asset | Long | string | BigInt | number; export interface IWitnessSetPropertiesData { /** diff --git a/ts/wasm/lib/detailed/decorators/formatters.ts b/ts/wasm/lib/detailed/decorators/formatters.ts index 57e8939401b2bb64113db9a19a94d5955809cac6..a0b2c019cb5c381eb74868a0d6681fa7ac96ffdd 100644 --- a/ts/wasm/lib/detailed/decorators/formatters.ts +++ b/ts/wasm/lib/detailed/decorators/formatters.ts @@ -1,3 +1,5 @@ +import { defineMetadata } from "reflect-metadata/no-conflict"; + export interface IWaxFormatterDecoratorOptions<T = any> { /** * Property to match. If not specified defaults to the formatter method name @@ -61,14 +63,14 @@ export const WaxFormattable = (options?: IWaxFormatterDecoratorOptions | string) const requireDefined = (options as IWaxFormatterDecoratorOptions | undefined)?.requireDefined as boolean | undefined ?? false; const matchInstanceOf = (options as IWaxFormatterDecoratorOptions | undefined)?.matchInstanceOf as { new(...args: any[]): any } | undefined; - Reflect.defineMetadata("wax:formatter:prop", matchProperty ?? propertyKey, target, propertyKey); - Reflect.defineMetadata("wax:formatter:explicitprop", typeof matchProperty === "string", target, propertyKey); - Reflect.defineMetadata("wax:formatter:requiredefined", requireDefined, target, propertyKey); + defineMetadata("wax:formatter:prop", matchProperty ?? propertyKey, target, propertyKey); + defineMetadata("wax:formatter:explicitprop", typeof matchProperty === "string", target, propertyKey); + defineMetadata("wax:formatter:requiredefined", requireDefined, target, propertyKey); if(typeof matchValue !== "undefined") - Reflect.defineMetadata("wax:formatter:propvalue", matchValue, target, propertyKey); + defineMetadata("wax:formatter:propvalue", matchValue, target, propertyKey); if(typeof matchInstanceOf !== "undefined") - Reflect.defineMetadata("wax:formatter:instanceof", matchInstanceOf, target, propertyKey); + defineMetadata("wax:formatter:instanceof", matchInstanceOf, target, propertyKey); }; }; diff --git a/ts/wasm/lib/detailed/decorators/is_auth.ts b/ts/wasm/lib/detailed/decorators/is_auth.ts deleted file mode 100644 index 5eeeb655aab985b391984bee625626a6c5e1d75d..0000000000000000000000000000000000000000 --- a/ts/wasm/lib/detailed/decorators/is_auth.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, registerDecorator } from 'class-validator'; - -@ValidatorConstraint({ name: "isAuth", async: false }) -export class IsAuthValidator implements ValidatorConstraintInterface { - public validate(value: any, _args: ValidationArguments) { - const isAuth = (what: any) => { - return typeof what === "object" && typeof what[0] === "string" && typeof what[1] === "number"; - }; - - if (Array.isArray(value)) - return value.some(isAuth); - - return isAuth(value); - } - - public defaultMessage(_args: ValidationArguments) { - return "The value must be a valid authority object."; - } -} - -export const IsAuth = () => { - return (object: Record<string, any>, propertyName: string) => { - registerDecorator({ - name: 'isAuth', - target: object.constructor, - propertyName: propertyName, - constraints: [], - validator: IsAuthValidator - }); - }; -} diff --git a/ts/wasm/lib/detailed/decorators/is_nai_string.ts b/ts/wasm/lib/detailed/decorators/is_nai_string.ts deleted file mode 100644 index bfbccc1414433978f983492c8f8b6cc4805a3bb9..0000000000000000000000000000000000000000 --- a/ts/wasm/lib/detailed/decorators/is_nai_string.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, registerDecorator } from 'class-validator'; - -@ValidatorConstraint({ name: "isNaiString", async: false }) -export class IsNaiStringValidator implements ValidatorConstraintInterface { - public validate(value: any, _args: ValidationArguments) { - if (typeof value !== "string") - return false; - - return /@@\d{9}/.test(value); - } - - public defaultMessage(_args: ValidationArguments) { - return "The value must be a valid nai asset string - start with '@@' and ends with a number."; - } -} - -export const IsNaiString = () => { - return (object: Record<string, any>, propertyName: string) => { - registerDecorator({ - name: 'isNaiString', - target: object.constructor, - propertyName: propertyName, - constraints: [], - validator: IsNaiStringValidator - }); - }; -} diff --git a/ts/wasm/lib/detailed/decorators/is_number_or_number_string.ts b/ts/wasm/lib/detailed/decorators/is_number_or_number_string.ts deleted file mode 100644 index d05e168346d651203b9afa9fbe2244f7d98734e0..0000000000000000000000000000000000000000 --- a/ts/wasm/lib/detailed/decorators/is_number_or_number_string.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, registerDecorator } from 'class-validator'; - -@ValidatorConstraint({ name: "isNumberOrNumberString", async: false }) -export class IsNumberOrStringNumberValidator implements ValidatorConstraintInterface { - public validate(value: any, _args: ValidationArguments) { - return typeof value === 'number' || (typeof value === 'string' && !Number.isNaN(Number.parseFloat(value))); - } - - public defaultMessage(_args: ValidationArguments) { - return "The value must be a valid number or number string."; - } -} - -export const IsNumberOrStringNumber = () => { - return (object: Record<string, any>, propertyName: string) => { - registerDecorator({ - name: 'isNumberOrNumberString', - target: object.constructor, - propertyName: propertyName, - constraints: [], - validator: IsNumberOrStringNumberValidator - }); - }; -} diff --git a/ts/wasm/lib/detailed/decorators/is_public_key.ts b/ts/wasm/lib/detailed/decorators/is_public_key.ts index ff2908eda3497263c535702fb62cd756e23c7428..0a8f916e280c6b0c9c85ca1bba5d8089cea98e67 100644 --- a/ts/wasm/lib/detailed/decorators/is_public_key.ts +++ b/ts/wasm/lib/detailed/decorators/is_public_key.ts @@ -1,5 +1,3 @@ -import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, registerDecorator } from 'class-validator'; - export const isPublicKey = (value: string) => { if (typeof value !== "string") return false; @@ -12,25 +10,3 @@ export const isPublicKey = (value: string) => { return base58Regex.test(value.slice(3)); }; -@ValidatorConstraint({ name: "isPublicKey", async: false }) -export class IsPublicKeyValidator implements ValidatorConstraintInterface { - public validate(value: any, _args: ValidationArguments) { - return isPublicKey(value); - } - - public defaultMessage(_args: ValidationArguments) { - return "The value must be a valid public key - start with 'STM' and be base58 encoded."; - } -} - -export const IsPublicKey = () => { - return (object: Record<string, any>, propertyName: string) => { - registerDecorator({ - name: 'isPublicKey', - target: object.constructor, - propertyName: propertyName, - constraints: [], - validator: IsPublicKeyValidator - }); - }; -} diff --git a/ts/wasm/lib/detailed/extensions/signatures/index.ts b/ts/wasm/lib/detailed/extensions/signatures/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..70b5c6af27aeb7025dc0ecbf83583bd31b071aa4 --- /dev/null +++ b/ts/wasm/lib/detailed/extensions/signatures/index.ts @@ -0,0 +1,45 @@ +import type { TPublicKey, TSignature, THexString, ITransaction } from "../../interfaces"; + +export interface ISignatureProvider { + /** + * Signs a transaction by signing a digest of the transaction + * + * @param {TPublicKey} publicKey public key in WIF format to match the private key in the underlying container. It will be used to sign the provided data + * @param {THexString} sigDigest digest of a transaction in hex format + * + * @returns {TSignature} signed data in hex format + */ + signDigest(publicKey: TPublicKey, sigDigest: THexString): TSignature; + /** + * Encrypts given data for a specific entity and returns the encrypted message + * + * @param {string} content Content to be encrypted + * @param {TPublicKey} key public key to find the private key in the underlying container and encrypt the data + * @param {?TPublicKey} anotherKey other public key to find the private key in the underlying container and encrypt the data (optional - use if the message is to encrypt for somebody else) + * @param {?number} nonce optional nonce to be explicitly specified for encryption + * + * @returns {string} base58 encrypted buffer + */ + encryptData(content: string, key: TPublicKey, anotherKey?: TPublicKey, nonce?: number): string; + /** + * Decrypts given data from a specific entity and returns the decrypted message + * + * @param {string} content Base58 content to be decrypted + * @param {TPublicKey} key public key to find the private key in the underlying container and decrypt the data + * @param {?TPublicKey} anotherKey other public key to find the private key in the underlying container and decrypt the data (optional - use if the message was encrypted for somebody else) + * + * @returns {string} decrypted buffer + */ + decryptData(content: string, key: TPublicKey, anotherKey?: TPublicKey): string; +}; + +export interface IOnlineSignatureProvider { + /** + * Signs a transaction by signing a digest of the transaction + * + * @param {ITransaction} transaction transaction to be signed + * + * @returns {Promise<void>} signed data in hex format + */ + signTransaction(transaction: ITransaction): Promise<void>; +}; diff --git a/ts/wasm/lib/detailed/formatters/base.ts b/ts/wasm/lib/detailed/formatters/base.ts index 4f689f12a7753a358fb0b192ccfb0b9d26ba66db..1b69dd663fb4730ebb1a3841c23d31e18282e03d 100644 --- a/ts/wasm/lib/detailed/formatters/base.ts +++ b/ts/wasm/lib/detailed/formatters/base.ts @@ -1,4 +1,5 @@ import { DeepPartial, DeepReadonly, IWaxFormatter, IWaxFormatterOptions } from "./types"; +import { structuredClone } from "../shims/structuredclone.js"; export const DEFAULT_FORMATTER_OPTIONS: IWaxFormatterOptions = { asset: { diff --git a/ts/wasm/lib/detailed/formatters/types.ts b/ts/wasm/lib/detailed/formatters/types.ts index 2f8d98725e6dc7e5377aa82e31df5d6e359e8a23..d7ae5c8511cf7baffed84e301c5c7c7c2b3aa718 100644 --- a/ts/wasm/lib/detailed/formatters/types.ts +++ b/ts/wasm/lib/detailed/formatters/types.ts @@ -13,9 +13,9 @@ export type DeepReadonly<T> = T extends object ? DeepReadonlyObject<T> : T; -interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {} +export interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {} -type DeepReadonlyObject<T> = { +export type DeepReadonlyObject<T> = { readonly [P in keyof T]: DeepReadonly<T[P]>; }; diff --git a/ts/wasm/lib/detailed/formatters/waxify.ts b/ts/wasm/lib/detailed/formatters/waxify.ts index 601d9138d2f31c9696b4e478cb49e070fa25d42e..a7be8f530f0f342f6441e2b79f5b2f715ec06b2f 100644 --- a/ts/wasm/lib/detailed/formatters/waxify.ts +++ b/ts/wasm/lib/detailed/formatters/waxify.ts @@ -4,6 +4,8 @@ import type { IWaxBaseInterface } from "../interfaces"; import { WaxFormatterBase } from "./base"; import { DefaultFormatters } from "./default_formatters"; import Long from "long"; +import { getMetadata } from "reflect-metadata/no-conflict"; +import { structuredClone } from "../shims/structuredclone.js"; export interface IMatchersData { matchValues: Map<string, TFormatFunction>; @@ -100,11 +102,11 @@ export class WaxFormatter extends WaxFormatterBase implements IWaxExtendableForm const formatter = new formatterConstructor(this.wax); for(const key of Object.getOwnPropertyNames(formatterConstructor.prototype)) { - const matchedProperty = Reflect.getMetadata("wax:formatter:prop", formatter, key) as string | undefined; - const explicitProp = Reflect.getMetadata("wax:formatter:explicitprop", formatter, key) as boolean | undefined; - const requireDefined = Reflect.getMetadata("wax:formatter:requiredefined", formatter, key) as boolean; - const matchedPropertyValue = Reflect.getMetadata("wax:formatter:propvalue", formatter, key) as any | undefined; - const matchInstanceOf = Reflect.getMetadata("wax:formatter:instanceof", formatter, key) as { new(...args: any[]): any } | undefined; + const matchedProperty = getMetadata("wax:formatter:prop", formatter, key) as string | undefined; + const explicitProp = getMetadata("wax:formatter:explicitprop", formatter, key) as boolean | undefined; + const requireDefined = getMetadata("wax:formatter:requiredefined", formatter, key) as boolean; + const matchedPropertyValue = getMetadata("wax:formatter:propvalue", formatter, key) as any | undefined; + const matchInstanceOf = getMetadata("wax:formatter:instanceof", formatter, key) as { new(...args: any[]): any } | undefined; if(!explicitProp && typeof matchInstanceOf === "function") { // Match only by the instance if requested const pred = newFormatter.instances.find(obj => obj.matchInstanceOf === matchInstanceOf); diff --git a/ts/wasm/lib/detailed/healthchecker/healthchecker.ts b/ts/wasm/lib/detailed/healthchecker/healthchecker.ts index 1f7385247235d9b8895394264d03639a1faad2cb..501a06cd126593569eb7ddc2b32cf6ae78409768 100644 --- a/ts/wasm/lib/detailed/healthchecker/healthchecker.ts +++ b/ts/wasm/lib/detailed/healthchecker/healthchecker.ts @@ -29,7 +29,7 @@ export type TScoredEndpoint = IScoredEndpointDown | IScoredEndpointUp; export type TCalculateScoresFunction = (data: Readonly<Array<[string, Array<THiveEndpointData>]>>) => Array<TScoredEndpoint>; -interface IHealthCheckerEvents { +export interface IHealthCheckerEvents { 'newbest': (endpoint: TScoredEndpoint) => void | Promise<void>; 'newup': (endpoint: TScoredEndpoint) => void | Promise<void>; 'newdown': (endpoint: TScoredEndpoint) => void | Promise<void>; @@ -128,7 +128,7 @@ export class HealthChecker extends EventEmitter { * Creates a new HealthChecker instance. * * @param {?Readonly<Array<string>>} defaultEndpoints default endpoints for checkers. - * If `undefined` (default) uses {@link DefaultEndpoints} for json rpc or {@link DefaultRestApiEndpoints} for rest api + * If `undefined` (default) uses {@link DefaultJsonRpcEndpoints} for json rpc or {@link DefaultRestApiEndpoints} for rest api * * @example * ```ts @@ -178,7 +178,7 @@ export class HealthChecker extends EventEmitter { * Registers the checker to the healthcheck intervals * * @param {TFn} endpointToCheck Function to check (e.g. `chain.api.block_api.get_block`) - * @param {Parameters<TFn>[0]} toSend param to {@link endpointToCheck} + * @param {Parameters<TFn>[0]} toSend param to endpointToCheck * @param {(data: Awaited<ReturnType<TFn>>) => (true | string)} validator optional validator for fields. Return true to pass validation and string to fail with given message * @param {?string[]} testOnEndpoints explicit list of endpoints. If not provided defaults to {@link defaultEndpoints} * @@ -322,7 +322,7 @@ export class HealthChecker extends EventEmitter { * ```ts * const hc = new wax.HealthChecker(); * - * hc.subscribe(HealthChecker.DefaultEndpoints[0]); + * hc.subscribe(HealthChecker.DefaultJsonRpcEndpoints[0]); * * hc.on("newdown", ({ endpointUrl }) => { console.log(endpointUrl, 'is down. Changing endpoint url...'); }); * hc.on("newup", ({ endpointUrl }) => { console.log(endpointUrl, 'is up. Changing to given endpoint...'); }); diff --git a/ts/wasm/lib/detailed/index.ts b/ts/wasm/lib/detailed/index.ts index 62bd86eaf0b8a683d19db4c9aa805b03a92a4577..282fbb5df0a2b17c262e0f7a46609247c35c21f3 100644 --- a/ts/wasm/lib/detailed/index.ts +++ b/ts/wasm/lib/detailed/index.ts @@ -1,9 +1,9 @@ -import "reflect-metadata"; - export { EAssetName } from "./base_api.js"; -export { EManabarType } from './chain_api.js'; +export { EManabarType, EChainApiType } from './chain_api.js'; +export { HiveApiTypes, HiveRestApiTypes } from './chain_api_data.js'; export { isPublicKey } from "./decorators/is_public_key.js"; export * from './api/index.js'; +export * from './rest-api/index.js'; export * from './formatters/index.js'; export * from './hive_apps_operations/index.js'; export * from './complex_operations/index.js'; @@ -16,6 +16,7 @@ export { TTransactionRequiredAuthorities } from './transaction.js'; export { DEFAULT_WAX_OPTIONS_CHAIN, createHiveChain } from "./chain.js"; export { DEFAULT_WAX_OPTIONS, createWaxFoundation } from "./base.js"; +export * from './extensions/signatures/index.js'; export * from './interfaces.js'; // Protobuf definitions diff --git a/ts/wasm/lib/detailed/interfaces.ts b/ts/wasm/lib/detailed/interfaces.ts index 6ae497c450167fcad106f8d93025aadf0bf30c5e..c9681aeb0ebd1424dee175c2100dbfa9e976d70f 100644 --- a/ts/wasm/lib/detailed/interfaces.ts +++ b/ts/wasm/lib/detailed/interfaces.ts @@ -1,5 +1,5 @@ -import type { IBeekeeperUnlockedWallet, TPublicKey } from "@hiveio/beekeeper"; -export type { TPublicKey } from "@hiveio/beekeeper"; +import type { TPublicKey } from "@hiveio/beekeeper"; +export type { TPublicKey, TSignature } from "@hiveio/beekeeper"; // @ts-expect-error ts(6133) Type WaxError is used in JSDoc import type { WaxError } from "./errors"; @@ -15,8 +15,11 @@ import type { OperationBase } from "./operation_base"; import type { BlogPostOperation, AccountAuthorityUpdateOperation, ReplyOperation, DefineRecurrentTransferOperation, RecurrentTransferRemovalOperation, UpdateProposalOperation, WitnessSetPropertiesOperation } from "./complex_operations"; import type { ResourceCreditsOperation, CommunityOperation, FollowOperation, TAccountName } from './hive_apps_operations'; import type { IChainConfig } from "../build_wasm/config"; +import { ISignatureProvider, IOnlineSignatureProvider } from "./extensions/signatures"; import type { IVerifyAuthorityTrace } from "./verify_authority_trace_interface"; +export type { IChainConfig }; + export * from "./verify_authority_trace_interface"; export type {TAccountName}; @@ -131,7 +134,7 @@ export interface IWaxOptionsChain extends IWaxOptions { restApiEndpoint: string; } -interface ITransactionBase { +export interface ITransactionBase { /** * Generates digest of the transaction for signing (HF26 serialization form is used). @@ -207,13 +210,13 @@ interface ITransactionBase { /** * Decrypts all underlying encrypted operations * - * @param {IBeekeeperUnlockedWallet} wallet unlocked wallet to be used for decryption + * @param {ISignatureProvider} wallet unlocked wallet to be used for decryption * * @returns {transaction} protobuf transaction object * * @throws {WaxError} on any Wax API-related error including validation error */ - decrypt(wallet: IBeekeeperUnlockedWallet): transaction; + decrypt(wallet: ISignatureProvider): transaction; /** * Returns required authority accounts from the transaction @@ -241,31 +244,7 @@ interface ITransactionBase { toString(): string; /** - * Signs the transaction using given public key. Applies the transaction expiration time - * - * Encrypts operations if any were created using {@link IEncryptingTransaction} interface - * - * @param {IBeekeeperUnlockedWallet} wallet unlocked wallet to be used for signing - * @param {TPublicKey} publicKey publicKey for signing (should be available in the wallet) - * - * @returns {THexString} transaction signature signed using given key - * - * @throws {WaxError} on any Wax API-related error or no public key found in the unlocked wallet or wallet is locked - */ - sign(wallet: IBeekeeperUnlockedWallet, publicKey: TPublicKey): THexString; - -/** - * Adds your signature to the internal signatures array inside underlying transaction. - * - * @param {THexString} signature signature to add - * - * @returns {THexString} added transaction signature - * - */ - sign(signature: THexString): THexString; - - /** - * Checks if underlying transaction has been already signed at least one time (after {@link sign}) + * Checks if underlying transaction has been already signed at least one time (after {@link ITransaction.sign}) * * @returns {boolean} either true or false based on the signatures amount */ @@ -311,6 +290,19 @@ interface ITransactionBase { */ toApiJson(): ApiTransaction; + /** + * Starts encryption chain + * + * Remember that in order to encrypt operations with given {@link mainEncryptionKey} and optional {@link otherEncryptionKey} + * you have to import those keys into the wallet passed to the {@link ITransaction.sign} method + * + * @param {TPublicKey} mainEncryptionKey First key to encrypt operations + * @param {?TPublicKey} otherEncryptionKey Optional second key to encrypt operations + * + * @returns {this & IEncryptingTransaction<this>} current transaction instance + */ + startEncrypt(mainEncryptionKey: TPublicKey, otherEncryptionKey?: TPublicKey): this & IEncryptingTransaction<this>; + /** * Converts the created transaction into the Hive API-legacy form JSON string. * @@ -334,36 +326,11 @@ interface ITransactionBase { /** * Allows to serialize underlying transaction to HF26 specific binary form, then return it as hexstring. + * @param {boolean} stripToUnsignedTransaction optional flag to strip the transaction to unsigned form (without signature container). + * This form can be useful for external transaction hash calculation. */ - toBinaryForm(): THexString; -} + toBinaryForm(stripToUnsignedTransaction?: boolean): THexString; -/** - * Transaction allows you to push simple operations (as inline objects) - * or use dedicated operation factories - * (to create more complex operations or multiple blockchain transactions for specific scenarios) - * into underlying transaction. - * Furthermore, it allows to perform analysis of the transaction - * by examining its id (hash), - * evaluating the digest to calculate signatures - * or extracting public keys involved in the attached signatures. - * - * Example usage: - * @example Base transaction usage - * ```typescript - * const tx = new waxFoundation.Transaction(); - * - * tx.pushOperation({ - * vote: { - * voter: "otom", - * author: "c0ff33a", - * permlink: "ewxhnjbj", - * weight: 2200 - * } - * }); - * ``` - */ -export interface ITransaction extends ITransactionBase { /** * Pushes given operation to the operations array in the transaction * This can also add **multiple** operations to the transaction using a straightforward complex operation interface. @@ -409,29 +376,67 @@ export interface ITransaction extends ITransactionBase { * })); * ``` * - * @returns {ITransaction} current transaction instance + * @returns {this} current transaction instance * * @throws {WaxError} on any Wax API-related error */ - pushOperation(op: operation | OperationBase): ITransaction; + pushOperation(op: operation | OperationBase): this; +} +/** + * Transaction allows you to push simple operations (as inline objects) + * or use dedicated operation factories + * (to create more complex operations or multiple blockchain transactions for specific scenarios) + * into underlying transaction. + * Furthermore, it allows to perform analysis of the transaction + * by examining its id (hash), + * evaluating the digest to calculate signatures + * or extracting public keys involved in the attached signatures. + * + * Example usage: + * @example Base transaction usage + * ```typescript + * const tx = new waxFoundation.Transaction(); + * + * tx.pushOperation({ + * vote: { + * voter: "otom", + * author: "c0ff33a", + * permlink: "ewxhnjbj", + * weight: 2200 + * } + * }); + * ``` + */ +export interface ITransaction extends ITransactionBase { /** - * Starts encryption chain + * Signs the transaction using given public key. Applies the transaction expiration time * - * Remember that in order to encrypt operations with given {@link mainEncryptionKey} and optional {@link otherEncryptionKey} - * you have to import those keys into the wallet passed to the {@link ITransactionBase.sign} method + * Encrypts operations if any were created using {@link IEncryptingTransaction} interface * - * @param {TPublicKey} mainEncryptionKey First key to encrypt operations - * @param {?TPublicKey} otherEncryptionKey Optional second key to encrypt operations + * @param {ISignatureProvider} wallet unlocked wallet to be used for signing + * @param {TPublicKey} publicKey publicKey for signing (should be available in the wallet) + * + * @returns {THexString} transaction signature signed using given key * - * @returns {IEncryptingTransaction} current transaction instance + * @throws {WaxError} on any Wax API-related error or no public key found in the unlocked wallet or wallet is locked */ - startEncrypt(mainEncryptionKey: TPublicKey, otherEncryptionKey?: TPublicKey): IEncryptingTransaction; + sign(wallet: ISignatureProvider, publicKey: TPublicKey): THexString; + + /** + * Adds your signature to the internal signatures array inside underlying transaction. + * + * @param {THexString} signature signature to add + * + * @returns {THexString} added transaction signature + * + */ + sign(signature: THexString): THexString; } /** * Same as {@link ITransaction}, but marks operations as encrypted using given keys, which will be encrypted upon - * {@link ITransactionBase.sign}. + * {@link ITransaction.sign}. * * Note: We are not able to encrypt all operations. * We are currently supporting: @@ -456,73 +461,22 @@ export interface ITransaction extends ITransactionBase { * }).stopEncrypt(); * ``` */ -export interface IEncryptingTransaction extends ITransactionBase { - /** - * Pushes given operation to the operations array in the transaction - * This can also add **multiple** operations to the transaction using a straightforward complex operation interface. - * - * We provide a standard set of factories with our implementation, but you can also create custom factories by extending the {@link OperationBase} class. - * - * @param {operation | OperationBase} op operation to append to the transaction (can be hive apps operation) - * or Class instance for a complex operation that will produce operations including given params - * - * @see Complex operations: - * {@link AccountAuthorityUpdateOperation} Creates an account authority update operation - * {@link BlogPostOperation} Creates a blog post. It requires the category on blog post to be set, - * {@link ReplyOperation} Creates a reply to a comment or a blog post. It requiers parent author and parent permlink to be set, - * {@link DefineRecurrentTransferOperation} Creates or updates a recurrent transfer. It requires the amount to be set and to be non-zero, otherwise the removal will be generated automatically, - * {@link RecurrentTransferRemovalOperation} Creates an operation removing existing recurrent transfer - * {@link UpdateProposalOperation} Creates an update proposal operation. You can optionally set the end date of the proposal, - * {@link WitnessSetPropertiesOperation} Creates a witness set properties operation with automatic data serialization, - * - * @see Hive Apps operations: - * {@link CommunityOperation} Allows to manipulate the community options, - * {@link FollowOperation} Allows to manipulate the follow options, - * {@link ResourceCreditsOperation} Allows to delegate or remove delegation of resource credits to given account(s), - * - * @example Building blog post - * ```typescript - * tx.pushOperation(new BlogPostOperation({ - * category: "test-category", - * author: "gtg", - * title: "Post with category", - * body: "Post with category", - * permlink: "post-with-category", - * tags: ["spam"], - * description: "Post with category" - * })); - * ``` - * - * @example Building recurrent transfer with pair id and automaically generated removal - * ```typescript - * tx.pushOperation(new DefineRecurrentTransferOperation({ - * from: "initminer", - * to: "gtg", - * pairId: 100 - * })); - * ``` - * - * @returns {IEncryptingTransaction} current transaction instance - * - * @throws {WaxError} on any Wax API-related error - */ - pushOperation(op: operation | OperationBase): IEncryptingTransaction; - +export interface IEncryptingTransaction<StopEncryptResult extends ITransactionBase> { /** * Stops encryption chain * * Note: This call is optional if you are not going to push any other decrypted operations * - * @returns {ITransaction} current transaction instance + * @returns {StopEncryptResult} current transaction instance */ - stopEncrypt(): ITransaction; + stopEncrypt(): StopEncryptResult; }; /** * Extends {@link ITransaction} interface by functionality which requires online chain access (i.e. accessing account * authority to prevent private keys leak). */ -export interface IOnlineTransaction extends ITransaction { +export interface IOnlineTransaction extends ITransactionBase { /** * Allows to perform transaction checks which require additional access to chain APIs i.e. to retrieve account data. * @@ -545,10 +499,42 @@ export interface IOnlineTransaction extends ITransaction { */ generateAuthorityVerificationTrace(useLegacySerialization?: boolean, externalTx?: ITransaction): Promise<IVerifyAuthorityTrace>; - /** Overrided only to change return type. - * {@inheritdoc ITransaction.pushOperation} + /** + * Signs the transaction using given public key. Applies the transaction expiration time + * + * Encrypts operations if any were created using {@link IEncryptingTransaction} interface + * + * @param {IOnlineSignatureProvider} wallet unlocked wallet to be used for signing + * + * @returns {Promise<void>} transaction signature signed using given key + * + * @throws {WaxError} on any Wax API-related error or no public key found in the unlocked wallet or wallet is locked */ - pushOperation(op: operation | OperationBase): IOnlineTransaction; + sign(wallet: IOnlineSignatureProvider): Promise<void>; + + /** + * Signs the transaction using given public key. Applies the transaction expiration time + * + * Encrypts operations if any were created using {@link IEncryptingTransaction} interface + * + * @param {ISignatureProvider} wallet unlocked wallet to be used for signing + * @param {TPublicKey} publicKey publicKey for signing (should be available in the wallet) + * + * @returns {THexString} transaction signature signed using given key + * + * @throws {WaxError} on any Wax API-related error or no public key found in the unlocked wallet or wallet is locked + */ + sign(wallet: ISignatureProvider, publicKey: TPublicKey): THexString; + + /** + * Adds your signature to the internal signatures array inside underlying transaction. + * + * @param {THexString} signature signature to add + * + * @returns {THexString} added transaction signature + * + */ + sign(signature: THexString): THexString; }; export interface IHiveAssetData { @@ -840,10 +826,24 @@ export interface IWaxBaseInterface { */ getPrivateKeyFromPassword(account: string, role: string, password: string): IPrivateKeyData; + /** + * Allows to convert raw private key to WIF format. + * @param rawPrivateKey 32 bytes buffer (64 characters hex string) representing private key secret + * @returns WIF formatted private key + */ + convertRawPrivateKeyToWif(rawPrivateKey: THexString): string; + + /** + * Allows to convert raw public key to WIF format. + * @param rawPublicKey 33 or 65 bytes buffer (doubled characters hex string) representing compressed or uncompressed public key data + * @returns WIF formatted public key (including prefix) + */ + convertRawPublicKeyToWif(rawPublicKey: THexString): string; + /** * Encrypts given data using two keys and dumps result to the encrypted string in `#encrypted` format * - * @param {IBeekeeperUnlockedWallet} wallet Wallet with imported {@link mainEncryptionKey} and {@link otherEncryptionKey} keys + * @param {ISignatureProvider} wallet Wallet with imported {@link mainEncryptionKey} and {@link otherEncryptionKey} keys * @param {string} content Content to be encoded * @param {TPublicKey} mainEncryptionKey First key to encrypt operations * @param {?TPublicKey} otherEncryptionKey Optional second key to encrypt operations @@ -851,17 +851,17 @@ export interface IWaxBaseInterface { * * @returns {string} Encrypted content */ - encrypt(wallet: IBeekeeperUnlockedWallet, content: string, mainEncryptionKey: TPublicKey, otherEncryptionKey?: TPublicKey, nonce?: number): string; + encrypt(wallet: ISignatureProvider, content: string, mainEncryptionKey: TPublicKey, otherEncryptionKey?: TPublicKey, nonce?: number): string; /** * Decrypts given data from the encrypted string in `#encrypted` format * - * @param {IBeekeeperUnlockedWallet} wallet Wallet with imported encryption keys + * @param {ISignatureProvider} wallet Wallet with imported encryption keys * @param {string} encrypted Content to be decoded * * @returns {string} Decoded content */ - decrypt(wallet: IBeekeeperUnlockedWallet, encrypted: string): string; + decrypt(wallet: ISignatureProvider, encrypted: string): string; /** * Calculates current manabar value for Hive account based on given arguments @@ -949,7 +949,7 @@ export interface IWaxBaseInterface { * * @param {TBlockHash} taposBlockId reference block id (can be head block id) for TaPoS * @param {?TTimestamp} expirationTime expiration time for the transaction. Applies upon the {@link ITransaction.sign} call or reading {@link ITransaction.transaction} property. - * Can be either any argument parsable by the {@link Date} constructor or relative time in seconds, minutes or hours + * Can be either any argument parsable by the Date constructor or relative time in seconds, minutes or hours * (remember maximum expiration time for the transaction in mainnet is 1 hour), e.g.: * `1699550966300` `"2023-11-09T17:29:30.028Z"` `new Date()` `"+10s"` `+30m` `+1h`. * Expiration time will be applied when calling any non-push-related method in {@link ITransaction} @@ -965,10 +965,11 @@ export interface IWaxBaseInterface { * Converts given transaction from Hive API-form JSON to HF26 specific binary form * * @param {ApiTransaction} transaction transaction in Hive API-form JSON - * + * @param {boolean} stripToUnsignedTransaction optional flag to strip the transaction to unsigned form (without signature container). + * This form can be useful for external transaction hash calculation. * @returns {THexString} transaction in hexstring */ - convertTransactionToBinaryForm(transaction: ApiTransaction): THexString; + convertTransactionToBinaryForm(transaction: ApiTransaction, stripToUnsignedTransaction?: boolean): THexString; /** * Converts given transaction from HF26 specific binary form to Hive API-form JSON @@ -988,7 +989,7 @@ export interface IWaxBaseInterface { /** * @internal */ -type JsonRpcApiData<T extends keyof typeof HiveApiTypes> = YourApiData<typeof HiveApiTypes[T]>; +export type JsonRpcApiData<T extends keyof typeof HiveApiTypes> = YourApiData<typeof HiveApiTypes[T]>; export type TWaxApiRequest<TReq, TRes> = { readonly params: TReq; @@ -1005,7 +1006,7 @@ export type TDeepWaxApiRequestPartial<T> = T extends object ? { /** * @internal */ -type YourApiData<YourTypes> = { +export type YourApiData<YourTypes> = { readonly [P in keyof YourTypes]: // First check for value type (YourTypes[P] extends object ? ( @@ -1101,10 +1102,10 @@ export interface IHiveChainInterface extends IWaxBaseInterface { /** * Allows to start transaction preparing process. * - * Same as {@link IWaxBaseInterface.createTransaction}, but pulls the reference block data from the remote + * Same as {@link IWaxBaseInterface.createTransactionWithTaPoS}, but pulls the reference block data from the remote * * @param {?TTimestamp} expirationTime expiration time for the transaction. Applies upon the {@link ITransaction.sign} call or reading {@link ITransaction.transaction} property. - * Can be either any argument parsable by the {@link Date} constructor or relative time in seconds, minutes or hours + * Can be either any argument parsable by the Date constructor or relative time in seconds, minutes or hours * (remember maximum expiration time for the transaction in mainnet is 1 hour), e.g.: * `1699550966300` `"2023-11-09T17:29:30.028Z"` `new Date()` `"+10s"` `+30m` `+1h`. Defaults to `+1m`. * Expiration time will be applied when calling any non-push-related method in {@link ITransaction} @@ -1119,14 +1120,14 @@ export interface IHiveChainInterface extends IWaxBaseInterface { /** * Encrypts given data using memo public keys of two accounts and dumps result to the encrypted string in `#encrypted` format * - * @param {IBeekeeperUnlockedWallet} wallet Wallet with imported {@link fromAccount} and {@link toAccount} memo public keys + * @param {ISignatureProvider} wallet Wallet with imported {@link fromAccount} and {@link toAccount} memo public keys * @param {string} content Content to be encoded * @param {string} fromAccount first account to retrieve the memo public key used for encryption * @param {?string} toAccount second account to retrieve the memo public key used for encryption * * @returns {Promise<string>} Encrypted content */ - encryptForAccounts(wallet: IBeekeeperUnlockedWallet, content: string, fromAccount: string, toAccount?: string): Promise<string>; + encryptForAccounts(wallet: ISignatureProvider, content: string, fromAccount: string, toAccount?: string): Promise<string>; /** * Allows to override default endpoint URL used to call RPC APIs initially configured by {@link IWaxOptionsChain} passed to {@link createHiveChain} builder function. diff --git a/ts/wasm/lib/detailed/online_transaction.ts b/ts/wasm/lib/detailed/online_transaction.ts index 6e4bc64816783cdc9a8b0259f816efa6864153be..a905b39206853e5efcff7f964bbe2d9719044c50 100644 --- a/ts/wasm/lib/detailed/online_transaction.ts +++ b/ts/wasm/lib/detailed/online_transaction.ts @@ -1,19 +1,18 @@ import { DEFAULT_WAX_OPTIONS } from "./base"; import { HiveChainApi, TChainReferenceData } from "./chain_api"; -import { OperationBase } from "./operation_base"; import { Transaction, TTransactionRequiredAuthorities } from "./transaction"; import type { authority, account_create, account_create_with_delegation, comment, create_claimed_account, recurrent_transfer, transfer, transfer_from_savings, transfer_to_savings, account_update2, account_update } from "./protocol"; import { OperationVisitor } from "./visitor"; -import type { IOnlineTransaction, ITransaction, TPublicKey, TTimestamp } from "./interfaces"; +import type { IOnlineTransaction, ITransaction, THexString, TPublicKey, TSignature, TTimestamp } from "./interfaces"; import { operation } from "./protocol"; import { TAccountName } from "./hive_apps_operations"; import type { IVerifyAuthorityTrace } from "./verify_authority_trace_interface"; import { AccountAuthorityCachingProvider } from "./util/account_authority_caching_provider"; import { convertAuthorityTrace } from "./verify_authority_trace"; -import type { TSignature } from "@hiveio/beekeeper"; import { authority_verification_trace, MapStringUInt16, required_authority_collection, wax_authority } from "../build_wasm/wax.common"; +import type { IOnlineSignatureProvider, ISignatureProvider } from "./extensions/signatures"; type TAuthorityHolder = { owner?: authority, /// unfortunetely protobuf defs have optional values allowed on defined authority levels @@ -163,9 +162,14 @@ export class OnlineTransaction extends Transaction implements IOnlineTransaction super(chain, chainReferenceData.head_block_id, expirationRefTime, expirationTime); } - public override pushOperation(op: operation | OperationBase): OnlineTransaction { - super.pushOperation(op); - return this; + public sign(wallet: ISignatureProvider, publicKey: TPublicKey): THexString; + public sign(wallet: IOnlineSignatureProvider): Promise<void>; + public sign(signature: THexString): THexString; + public sign(walletOrSignature: IOnlineSignatureProvider | ISignatureProvider | THexString, publicKey?: TPublicKey): Promise<void> | THexString { + if (typeof walletOrSignature === "object" && "signTransaction" in walletOrSignature) + return walletOrSignature.signTransaction(this as ITransaction); + + return super.sign(walletOrSignature, publicKey); } public async generateAuthorityVerificationTrace(useLegacySerialization: boolean = false, externalTx?: ITransaction): Promise<IVerifyAuthorityTrace> { diff --git a/ts/wasm/lib/detailed/protocol.ts b/ts/wasm/lib/detailed/protocol.ts index bd5705235824e8edbd5dcac3f65117600c8f0753..4ee2cdc0f798848836b2e9697a9ee29c3636fcc6 100644 --- a/ts/wasm/lib/detailed/protocol.ts +++ b/ts/wasm/lib/detailed/protocol.ts @@ -75,7 +75,7 @@ export { limit_order_create2 } from "../proto/limit_order_create2.js"; export { liquidity_reward } from "../proto/liquidity_reward.js"; export { pow_reward } from "../proto/pow_reward.js"; export { pow, pow_work } from "../proto/pow.js"; -export { pow2, pow2_work, equihash_pow, pow2_pow } from "../proto/pow2.js"; +export { pow2, pow2_work, pow2_input, equihash_proof, equihash_pow, pow2_pow } from "../proto/pow2.js"; export { producer_missed } from "../proto/producer_missed.js"; export { producer_reward } from "../proto/producer_reward.js"; export { proposal_fee } from "../proto/proposal_fee.js"; diff --git a/ts/wasm/lib/detailed/rest-api/hafbe/general/operation_type_counts.ts b/ts/wasm/lib/detailed/rest-api/hafbe/general/operation_type_counts.ts index ec9e103e5de7c79661013ab5fe028a65110ec82f..f488dd580a5b0ca44b9c97d61edb2077980fe1bc 100644 --- a/ts/wasm/lib/detailed/rest-api/hafbe/general/operation_type_counts.ts +++ b/ts/wasm/lib/detailed/rest-api/hafbe/general/operation_type_counts.ts @@ -1,28 +1,14 @@ -import { Type } from "class-transformer"; -import { IsArray, IsNumber, IsString, ValidateNested } from "class-validator"; - -export class OperationTypeCountsRequest { - @IsNumber() - public 'result-limit'!: number; +export interface OperationTypeCountsRequest { + 'result-limit': number; } -export class OpsCount { - @IsNumber() - public count!: number; - - @IsNumber() - public op_type_id!: number; +export interface OpsCount { + count: number; + op_type_id: number; } -export class OperationTypeCountsResponse { - @IsNumber() - public block_num!: number; - - @IsString() - public witness!: string; - - @Type(() => OpsCount) - @ValidateNested({ each: true }) - @IsArray() - public ops_count!: OpsCount[]; +export interface OperationTypeCountsResponse { + block_num: number; + witness: string; + ops_count: OpsCount[]; } diff --git a/ts/wasm/lib/detailed/rest-api/hafbe/witnesses/all.ts b/ts/wasm/lib/detailed/rest-api/hafbe/witnesses/all.ts index b99dcaacadc6ed3c9b3bad39e9f8a92f0e3190bf..fdebbc2fa0f6332848aa9e4328a8c38266bae45b 100644 --- a/ts/wasm/lib/detailed/rest-api/hafbe/witnesses/all.ts +++ b/ts/wasm/lib/detailed/rest-api/hafbe/witnesses/all.ts @@ -1,5 +1,3 @@ -import { IsIn, IsNumber } from "class-validator"; - const witnessSortKeys = ['witness', 'rank', 'url', 'votes', 'votes_daily_change', 'voters_num', 'voters_num_daily_change', 'price_feed', 'bias', 'block_size', 'signing_key', 'version'] as const; @@ -9,16 +7,12 @@ const directionKeys = ['asc', 'desc'] as const; type TDirectionKeys = typeof directionKeys[number]; -export class GetAllWitnessesRequest { - @IsNumber() - public 'result-limit'?: number = 100; +export interface GetAllWitnessesRequest { + 'result-limit'?: number; - @IsNumber() - public 'offset'?: number = 0; + 'offset'?: number; - @IsIn(witnessSortKeys) - public sort?: TWitnessSortKeys = 'votes'; + sort?: TWitnessSortKeys; - @IsIn(directionKeys) - public direction?: TDirectionKeys = 'desc'; + direction?: TDirectionKeys; } diff --git a/ts/wasm/lib/detailed/rest-api/hafbe/witnesses/by-name.ts b/ts/wasm/lib/detailed/rest-api/hafbe/witnesses/by-name.ts index bb5a4da4c5b1eefd391d1f7585290e28cb2ecf8b..9409eaf8005c1d065187f60062bdfafa99b2892a 100644 --- a/ts/wasm/lib/detailed/rest-api/hafbe/witnesses/by-name.ts +++ b/ts/wasm/lib/detailed/rest-api/hafbe/witnesses/by-name.ts @@ -1,60 +1,23 @@ -import { IsDateString, IsNumber, IsSemVer, IsString } from "class-validator"; -import { IsPublicKey } from "../../../decorators/is_public_key.js"; - -export class GetWitnessesByNameRequest { - @IsString() - public accountName!: string; +export interface GetWitnessesByNameRequest { + accountName: string; } -export class SingleWitnessResponse { - @IsString() - public witnes!: string; - - @IsNumber() - public rank!: number; - - @IsString() - public url!: string; - - @IsString() - public vests!: string; - - @IsNumber() - public vests_hive_power!: number; - - @IsString() - public votes_daily_change!: string; - - @IsString() - public votes_daily_change_hive_power!: string; - - @IsNumber() - public voters_num!: number; - - @IsNumber() - public voters_num_daily_change!: number; - - @IsNumber() - public price_feed!: number; - - @IsNumber() - public bias!: number; - - @IsDateString() - public feed_updated_at!: string; - - @IsNumber() - public block_size!: number; - - @IsPublicKey() - public signing_key!: string; - - @IsSemVer() - public version!: string; - - @IsNumber() - public missed_blocks!: number; - - @IsNumber() - public hbd_interest_rate!: number; +export interface SingleWitnessResponse { + witnes: string; + rank: number; + url: string; + vests: string; + vests_hive_power: number; + votes_daily_change: string; + votes_daily_change_hive_power: string; + voters_num: number; + voters_num_daily_change: number; + price_feed: number; + bias: number; + feed_updated_at: string; + block_size: number; + signing_key: string; + version: string; + missed_blocks: number; + hbd_interest_rate: number; } diff --git a/ts/wasm/lib/detailed/shims/structuredclone.ts b/ts/wasm/lib/detailed/shims/structuredclone.ts new file mode 100644 index 0000000000000000000000000000000000000000..4315362f95ef8a42583c5d09b4b02429aebd3e85 --- /dev/null +++ b/ts/wasm/lib/detailed/shims/structuredclone.ts @@ -0,0 +1,6 @@ +export const structuredClone = (value: any) => { + if (typeof globalThis.structuredClone === "undefined") + return JSON.parse(JSON.stringify(value)); + + return globalThis.structuredClone(value); +}; diff --git a/ts/wasm/lib/detailed/transaction.ts b/ts/wasm/lib/detailed/transaction.ts index ddee1d4510f1a653726806abd8a71f2ffa8e7b0b..7ec354b6ebfa885108a9cd0a26a75fec45f448ea 100644 --- a/ts/wasm/lib/detailed/transaction.ts +++ b/ts/wasm/lib/detailed/transaction.ts @@ -1,5 +1,4 @@ -import type { IBeekeeperUnlockedWallet, TPublicKey } from "@hiveio/beekeeper"; -import type { IBinaryViewNode, IBinaryViewOutputData, IEncryptingTransaction, ITransaction, TBlockHash, THexString, TTimestamp, TTransactionId } from "./interfaces"; +import type { IBinaryViewNode, IBinaryViewOutputData, IEncryptingTransaction, ITransaction, TBlockHash, THexString, TPublicKey, TTimestamp, TTransactionId } from "./interfaces"; import { authority, transaction, type operation } from "./protocol.js"; import { WaxBaseApi } from "./base_api.js"; @@ -10,6 +9,8 @@ import { WaxError } from "./errors.js"; import type { ApiTransaction } from "./api"; import { safeWasmCall } from "./util/wasm_errors"; import type { TAccountName } from "./hive_apps_operations"; +import { ISignatureProvider } from "./extensions/signatures"; +import { structuredClone } from "./shims/structuredclone.js"; type TIndexBeginEncryption = { mainEncryptionKey: TPublicKey; @@ -31,7 +32,7 @@ export type TTransactionRequiredAuthorities = { other: Array<authority>; } -export class Transaction implements ITransaction, IEncryptingTransaction { +export class Transaction implements ITransaction, IEncryptingTransaction<ITransaction> { private target: transaction; private taposRefer(hex: TBlockHash): { ref_block_num: number; ref_block_prefix: number } { @@ -75,8 +76,8 @@ export class Transaction implements ITransaction, IEncryptingTransaction { return keys; } - private getBinaryViewMetadataImpl(isHf26Serialization: boolean): IBinaryViewOutputData { - const binaryData = safeWasmCall(() => this.api.proto.cpp_generate_binary_transaction_metadata(this.toString(), isHf26Serialization)); + private getBinaryViewMetadataImpl(isHf26Serialization: boolean, stripSignatureContainer: boolean = false): IBinaryViewOutputData { + const binaryData = safeWasmCall(() => this.api.proto.cpp_generate_binary_transaction_metadata(this.toString(), isHf26Serialization, stripSignatureContainer)); return { binary: binaryData.binary as string, @@ -124,8 +125,8 @@ export class Transaction implements ITransaction, IEncryptingTransaction { return JSON.parse(this.toApi()); } - public toBinaryForm(): THexString { - const conversionResult = safeWasmCall(() => this.api.proto.cpp_serialize_transaction(this.toString())); + public toBinaryForm(stripSignatureContainer: boolean = false): THexString { + const conversionResult = safeWasmCall(() => this.api.proto.cpp_serialize_transaction(this.toString(), stripSignatureContainer)); const serialized = this.api.extract(conversionResult); @@ -152,10 +153,10 @@ export class Transaction implements ITransaction, IEncryptingTransaction { return JSON.stringify(transaction.toJSON(this.target)); } - public startEncrypt(mainEncryptionKey: TPublicKey, otherEncryptionKey?: TPublicKey): Transaction { + public startEncrypt(mainEncryptionKey: TPublicKey, otherEncryptionKey?: TPublicKey): this & IEncryptingTransaction<this> { this.indexKeeper.push({ mainEncryptionKey, otherEncryptionKey: otherEncryptionKey ?? mainEncryptionKey, begin: this.target.operations.length }); - return this; + return this as IEncryptingTransaction<this> & this; } public stopEncrypt(): Transaction { @@ -179,7 +180,7 @@ export class Transaction implements ITransaction, IEncryptingTransaction { return this; } - public pushOperation(op: operation | OperationBase): Transaction { + public pushOperation(op: operation | OperationBase): this { if ("finalize" in op) // Complex operation (to be built) this.produceOperations(op); else // Standard raw-object operation @@ -289,7 +290,7 @@ export class Transaction implements ITransaction, IEncryptingTransaction { this.target.expiration = expiration.toISOString().slice(0, -5); } - public decrypt(wallet: IBeekeeperUnlockedWallet): transaction { + public decrypt(wallet: ISignatureProvider): transaction { const visitor = new EncryptionVisitor(EEncryptionType.DECRYPT, (data: string) => { if(data.startsWith('#')) return this.api.decrypt(wallet, data) @@ -303,7 +304,7 @@ export class Transaction implements ITransaction, IEncryptingTransaction { return this.target; } - private encryptOperations(wallet: IBeekeeperUnlockedWallet): void { + private encryptOperations(wallet: ISignatureProvider): void { for(const index of this.indexKeeper) for(let i = index.begin; i < (index.end ?? this.target.operations.length); ++i) { const visitor = new EncryptionVisitor(EEncryptionType.ENCRYPT, (data: string) => { @@ -314,7 +315,7 @@ export class Transaction implements ITransaction, IEncryptingTransaction { } } - public sign(walletOrSignature: IBeekeeperUnlockedWallet | THexString, publicKey?: TPublicKey): THexString { + public sign(walletOrSignature: ISignatureProvider | THexString, publicKey?: TPublicKey): THexString { this.validate(); if (typeof walletOrSignature === 'string') { diff --git a/ts/wasm/lib/detailed/util/account_authority_caching_provider.ts b/ts/wasm/lib/detailed/util/account_authority_caching_provider.ts index a4795e77485c7474e443c58d21ac662619b8c652..175489cd805423a189920c7b81b020d1dac88250 100644 --- a/ts/wasm/lib/detailed/util/account_authority_caching_provider.ts +++ b/ts/wasm/lib/detailed/util/account_authority_caching_provider.ts @@ -3,6 +3,7 @@ import { TAccountName } from "../hive_apps_operations"; import type { TPublicKey } from "../interfaces"; import { WaxError } from "../errors"; import { ClassHandle, IAccountAuthorityProvider, wax_authority } from "wasm/lib/build_wasm/wax.common"; +import { structuredClone } from "../shims/structuredclone.js"; /** * Helper class used during traced authority verification process. diff --git a/ts/wasm/lib/detailed/util/api_caller.ts b/ts/wasm/lib/detailed/util/api_caller.ts index 2146ea720c1fd5b06299b119edbce1266e83594d..8bb3eac39b0fb50bb2547774ef821721ad6f65fc 100644 --- a/ts/wasm/lib/detailed/util/api_caller.ts +++ b/ts/wasm/lib/detailed/util/api_caller.ts @@ -1,10 +1,9 @@ -import { plainToInstance } from "class-transformer"; -import { validateOrReject } from "class-validator"; import { WaxChainApiError } from "../errors"; import { type TWaxApiRequest } from "../interfaces"; import { extractBracedStrings } from "../rest-api/utils.js"; import { objectToQueryString } from "./query_string.js"; import { type IDetailedResponseData, type IRequestOptions, RequestHelper } from "./request_helper.js"; +import { structuredClone } from "../shims/structuredclone.js"; export type TInterceptorRequestOptions = IRequestOptions & { paths: string[]; apiCallerId: string }; @@ -100,12 +99,6 @@ export class ApiCaller extends RequestHelper { public createApiCaller(): TRestChainCaller { const that = this; const callFn = async function(params: object | undefined, requestInterceptor: TRequestInterceptor = that.requestInterceptor, responseInterceptor: TResponseInterceptor = that.responseInterceptor): Promise<any> { - // Helper function to determine if we have to convert plain object to the instance of the given request or not - const isPlainObj = (value: unknown) => !!value && Object.getPrototypeOf(value) === Object.prototype; - - if(typeof callFn.config === 'object' && callFn.config.params !== undefined && typeof params === "object") - await validateOrReject(isPlainObj(params) ? plainToInstance(callFn.config.params, params) : params); - let path = '/' + callFn.paths.filter(node => node.length).join('/'); const allToReplace = extractBracedStrings(path); @@ -148,17 +141,6 @@ export class ApiCaller extends RequestHelper { if(typeof callFn.config === 'object') { if(result === undefined && callFn.config.result !== undefined) throw new WaxChainApiError('No result found in the Hive API response', data); - - if (callFn.config.result !== undefined && callFn.config.result !== Number && callFn.config.result !== Boolean && callFn.config.result !== String) { - // Parse any other result type which is a valid validator constructor - result = plainToInstance(callFn.config.result, result) as object; - - if (Array.isArray(result)) - for(const node of result) - await validateOrReject(node); - else - await validateOrReject(result); - } } return result; diff --git a/ts/wasm/lib/detailed/verify_authority_trace.ts b/ts/wasm/lib/detailed/verify_authority_trace.ts index 4cb7fa8f4d90751403b70b063a84b3d52322534c..3738ff190b89b20268afb98a84aca094d6b8d2f3 100644 --- a/ts/wasm/lib/detailed/verify_authority_trace.ts +++ b/ts/wasm/lib/detailed/verify_authority_trace.ts @@ -1,6 +1,6 @@ import { authority_verification_trace, path_entry, VectorPathEntry } from "../build_wasm/wax.common"; import type { IAuthorityPathEntry, IAuthorityPathTraceData, IAuthorityTraceSignatureInfo, IVerifyAuthorityTrace, TAuthorityEntryProcessingStatus } from "./verify_authority_trace_interface"; -import type { TPublicKey, TSignature } from "@hiveio/beekeeper"; +import type { TPublicKey, TSignature } from "./interfaces"; /// TODO export it through embind enum authority_entry_processing_flags diff --git a/ts/wasm/lib/detailed/verify_authority_trace_interface.ts b/ts/wasm/lib/detailed/verify_authority_trace_interface.ts index eaefd9a04ff307b7b9fb6a1981042949ba30e969..5b7f6c93585e4d2b8bafa1d52539122efe2e9f07 100644 --- a/ts/wasm/lib/detailed/verify_authority_trace_interface.ts +++ b/ts/wasm/lib/detailed/verify_authority_trace_interface.ts @@ -1,4 +1,4 @@ -import type { TPublicKey, TSignature } from "@hiveio/beekeeper"; +import type { TPublicKey, TSignature } from './interfaces'; import type { TAccountName } from './hive_apps_operations'; export type TAuthorityRole = string; /// TODO: unify with role type defined in account authority update meta operation diff --git a/ts/wasm/lib/detailed/visitor.ts b/ts/wasm/lib/detailed/visitor.ts index 537901a3a3ea2a3e3305e9bb9b7d909e2a28b075..3d3dbc3cb3e122192b18e0a337372578647193f9 100644 --- a/ts/wasm/lib/detailed/visitor.ts +++ b/ts/wasm/lib/detailed/visitor.ts @@ -16,8 +16,8 @@ export type TOperationVisitor<R = void> = { }; // https://github.com/Microsoft/TypeScript/issues/8306#issuecomment-1636697326 -declare const _: unique symbol; -type NoOverride = { [_]: typeof _; }; +export declare const _: unique symbol; +export type NoOverride = { [_]: typeof _; }; export class OperationVisitor<R = void> implements TOperationVisitor<R> { /** diff --git a/ts/wasm/lib/index.ts b/ts/wasm/lib/index.ts index 4296b5b255f3cf094e3a65201b0a123fec5b8c4f..0cdf9dd42d73cd19ac7e70c898841321bb95b5ec 100644 --- a/ts/wasm/lib/index.ts +++ b/ts/wasm/lib/index.ts @@ -11,16 +11,25 @@ declare global { } const ENVIRONMENT_IS_WORKER = typeof WorkerGlobalScope != 'undefined'; -const getModuleExt = () => ({ - locateFile: (path, scriptDirectory) => { - if (path === "wax.common.wasm") { - /// Warning: important change is moving conditional ternary expression outside of URL constructor call, what confused parcel analyzer. - /// Seems it must have simple variables & literals present to correctly translate code. - return (ENVIRONMENT_IS_WORKER ? new URL("./build_wasm/wax.common.wasm", self.location.href) : new URL("./build_wasm/wax.common.wasm", import.meta.url)).href; - } - return scriptDirectory + path; - } -}) +const getModuleExt = () => { + // Warning: important change is moving conditional ternary expression outside of URL constructor call, what confused parcel analyzer. + // Seems it must have simple variables & literals present to correctly translate code. + const wasmFilePath = (ENVIRONMENT_IS_WORKER ? new URL("./build_wasm/wax.common.wasm", self.location.href) : new URL("./build_wasm/wax.common.wasm", import.meta.url)).href; + // Fallback for client-bundled inlined WASM, e.g. when using webpack + let wasmBinary: Buffer | undefined; + if (wasmFilePath.startsWith("data:application/wasm;base64,")) + wasmBinary = Buffer.from(wasmFilePath.slice(29), "base64"); + + return { + locateFile(path: string, scriptDirectory: string): string { + if (path === "wax.common.wasm") { + return wasmFilePath; + } + return scriptDirectory + path; + }, + wasmBinary + }; +}; /** * Creates a Wax Hive chain instance diff --git a/ts/wasm/lib/vite.ts b/ts/wasm/lib/vite.ts index 16bdcdc7a90a6cb22aec5777abe7c126c92f8f14..b1e27464a0488eb802ad43e7177ca5bda7c24640 100644 --- a/ts/wasm/lib/vite.ts +++ b/ts/wasm/lib/vite.ts @@ -10,12 +10,17 @@ const moduleArgs = (async () => { if ((import.meta as any).client || (!("client" in import.meta) && typeof (import.meta as any).env === "object" && "SSR" in (import.meta as any).env)) { const resolvedUrl = (await import('./build_wasm/wax.common.wasm' + '?url')).default; + let wasmBinary: Buffer | undefined; + if (resolvedUrl.startsWith("data:application/wasm;base64,")) + wasmBinary = Buffer.from(resolvedUrl.slice(29), "base64"); + return { - locateFile: (path, scriptDirectory) => { + locateFile(path: string, scriptDirectory: string): string { if (path === "wax.common.wasm") return resolvedUrl; return scriptDirectory + path; - } + }, + wasmBinary }; } else { return {}; diff --git a/ts/wasm/src/wasm_interface.cpp b/ts/wasm/src/wasm_interface.cpp index be5189e0f3236f9d92f0870ccf513dc948e89c17..f2d4ea632e519162488bde4bdf14df1d806ee50e 100644 --- a/ts/wasm/src/wasm_interface.cpp +++ b/ts/wasm/src/wasm_interface.cpp @@ -95,6 +95,16 @@ result cpp_generate_private_key() private_key_data cpp_generate_private_key_password_based(const std::string& account, const std::string& role, const std::string& password) { return foundation::cpp_generate_private_key(account, role, password); } +std::string cpp_convert_raw_private_key_to_wif(const std::string& hexData) +{ + return foundation::cpp_convert_raw_private_key_to_wif(hexData); +} + +std::string cpp_convert_raw_public_key_to_wif(const std::string& hexData) +{ + return foundation::cpp_convert_raw_public_key_to_wif(hexData); +} + result cpp_get_public_key_from_signature(const std::string& digest, const std::string& signature) { return foundation::cpp_get_public_key_from_signature(digest, signature); } @@ -306,6 +316,8 @@ EMSCRIPTEN_BINDINGS(wax_api_instance) { .function("cpp_generate_private_key", &foundation_wasm::cpp_generate_private_key) .function("cpp_generate_private_key_password_based", &foundation_wasm::cpp_generate_private_key_password_based) + .function("cpp_convert_raw_private_key_to_wif", &foundation_wasm::cpp_convert_raw_private_key_to_wif) + .function("cpp_convert_raw_public_key_to_wif", &foundation_wasm::cpp_convert_raw_public_key_to_wif) .function("cpp_get_public_key_from_signature", &foundation_wasm::cpp_get_public_key_from_signature) // Based on https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#overloaded-functions: