From 6ae8fe277098b53b253af0fdc53c442c478d0b44 Mon Sep 17 00:00:00 2001 From: MatiasJF Date: Tue, 14 Jul 2026 18:12:44 +0200 Subject: [PATCH 1/3] feat: multi-standard token integration (STAS, DSTAS, BSV-21) + Back-to-Genesis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds native wallet support for three token standards on top of the BRC-100 wallet — receive, on-chain transfer (full + partial), peer-to-peer settlement over MessageBox, WhatsOnChain discovery, and Back-to-Genesis provenance verification. Single squashed commit against upstream base 49b4b63; standard onboarding (the branch's one-click prototype was reverted, net-zero here). Engines & registry - src/lib/services/stas, tokens/dstas, tokens/bsv21 — per-standard build/sign/ broadcast + parsers (classic-STAS, DSTAS via the vendored dxs SDK, BSV-21 ord inscription). TokenProtocolRegistry + *ProtocolAdapter give the legacy address-send path one polymorphic seam. Discovery — WhatsOnChain, single source - woc/WocTokenIndexerClient serves all three standards (no Bitails/relay/1Sat fallbacks, no feature flag). Scan loops skip already-held outpoints before any per-candidate getRawTx. Peer settlement (MessageBox) - tokens/peer/* — PeerTokenClient (imported from @bsv/message-box-client) + per-standard TokenSettlementAdapters with BRC-29 owner derivation. Back-to-Genesis — counterfeit detection - BackToGenesisClient (tri-state, fail-safe verify/trace), TokenVerificationService (session cache + worst-verdict badge), verifyOnReceive (verify at registration), persisted in token_verifications (migration 0004). Token identity keys on the resolved genesis outpoint — for classic STAS the tokenId is only the issuer PKH, so genesis is the sole spoof-proof identity. Proven against a broadcast counterfeit (same tokenId+amount as a real token, no ancestor → not-authentic). Persistence, wiring, UI - electron/stas-queries + stas-migrations (satellite tables + verifications); fee model raised to 250 sat/kb (was on the miner floor). WalletService wires the bundle; onWalletReady exposes the HTTP token routes. Assets page (grouped holdings, partial send, verification badges), Transfers/PeerTokens. Tests: test/stas + test/tokens (derivation, discovery, migration incl. 0004, registration, inscription, dstas-transfer, woc-indexer, back-to-genesis, token-verification, verify-on-receive). Renderer + Electron builds pass. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01K5d73SoN1pkMac9CbmtX5g --- .gitignore | 5 + AGENTS.md | 8 +- MULTI-PROTOCOL-TOKENS.md | 571 ++ electron/main.ts | 13 + electron/preload.ts | 9 + .../0001_create_stas_tables.ts | 74 + .../0002_add_protocol_column.ts | 154 + .../0003_bsv21_receive_contexts.ts | 32 + .../0004_token_verifications.ts | 41 + electron/stas-migrations/index.ts | 46 + electron/stas-queries.ts | 673 ++ electron/storage.ts | 51 +- package-lock.json | 6288 +++++++++++++---- package.json | 11 +- src/global.d.ts | 3 + src/lib/UserInterface.tsx | 2 + src/lib/WalletContext.tsx | 117 +- .../StasTransferPermissionHandler/index.tsx | 122 + src/lib/components/Theme.tsx | 34 + src/lib/constants/baskets.ts | 33 + src/lib/hooks/useWalletService.ts | 2 + src/lib/navigation/Menu.tsx | 44 +- src/lib/pages/Dashboard/AssetsPage.tsx | 1740 +++++ src/lib/pages/Dashboard/BasketsPage.tsx | 344 + src/lib/pages/Dashboard/PeerTokens/index.tsx | 315 + src/lib/pages/Dashboard/Settings/index.tsx | 1 + src/lib/pages/Dashboard/Transfers/index.tsx | 30 + src/lib/pages/Dashboard/index.tsx | 18 +- src/lib/services/WalletService.ts | 147 +- src/lib/services/stas/StasDiscoveryService.ts | 463 ++ src/lib/services/stas/StasKeyDeriver.ts | 118 + src/lib/services/stas/StasOwnershipService.ts | 48 + src/lib/services/stas/StasRegistration.ts | 265 + src/lib/services/stas/StasTransferService.ts | 580 ++ .../services/stas/buildChainedAtomicBeef.ts | 208 + src/lib/services/stas/constants.ts | 30 + src/lib/services/stas/dstasParser.ts | 95 + .../services/stas/findCreateContractTxid.ts | 143 + src/lib/services/stas/index.ts | 17 + .../services/stas/parseClassicStasMetadata.ts | Bin 0 -> 4028 bytes src/lib/services/stas/stasIpc.ts | 23 + .../services/tokens/BSV21ProtocolAdapter.ts | 101 + .../services/tokens/DstasProtocolAdapter.ts | 47 + .../services/tokens/StasProtocolAdapter.ts | 66 + .../services/tokens/TokenProtocolAdapter.ts | 115 + .../services/tokens/TokenProtocolRegistry.ts | 61 + .../tokens/TokenVerificationService.ts | 146 + .../tokens/bsv21/BSV21DiscoveryService.ts | 540 ++ .../services/tokens/bsv21/BSV21KeyDeriver.ts | 98 + .../tokens/bsv21/BSV21Registration.ts | 170 + .../tokens/bsv21/BSV21TransferService.ts | 479 ++ .../tokens/bsv21/OneSatIndexerClient.ts | 254 + src/lib/services/tokens/bsv21/constants.ts | 44 + src/lib/services/tokens/bsv21/index.ts | 13 + src/lib/services/tokens/bsv21/inscription.ts | 324 + .../tokens/dstas/DstasTransferService.ts | 635 ++ .../tokens/dstas/buildDstasUnlockingScript.ts | 306 + src/lib/services/tokens/index.ts | 12 + .../peer/Bsv21TokenSettlementAdapter.ts | 214 + .../peer/DstasTokenSettlementAdapter.ts | 225 + .../tokens/peer/StasTokenSettlementAdapter.ts | 263 + src/lib/services/tokens/peer/brc29KeyId.ts | 39 + .../services/tokens/peer/loadPeerHoldings.ts | 142 + .../tokens/peer/tokenSettlementTypes.ts | 40 + src/lib/services/tokens/tokenLog.ts | 42 + src/lib/services/tokens/verifyOnReceive.ts | 57 + .../tokens/woc/BackToGenesisClient.ts | 172 + .../tokens/woc/WocTokenIndexerClient.ts | 209 + src/lib/types/StasTransferRequest.ts | 30 + src/lib/utils/RateLimitedFetch.ts | 51 +- src/onWalletReady.ts | 878 ++- test/stas/derivation.test.ts | 45 + test/stas/discovery.test.ts | 235 + test/stas/migration.test.ts | 139 + test/stas/ownership.test.ts | 68 + test/stas/registration.test.ts | 179 + test/tokens/back-to-genesis.test.ts | 159 + test/tokens/bsv21-inscription.test.ts | 253 + test/tokens/dstas-transfer.test.ts | 306 + test/tokens/token-verification.test.ts | 128 + test/tokens/verify-on-receive.test.ts | 95 + test/tokens/woc-indexer.test.ts | 123 + vendor/dxs-bsv-token-sdk/README.md | 378 + vendor/dxs-bsv-token-sdk/dist/base.d.ts | 2 + vendor/dxs-bsv-token-sdk/dist/base.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/base.js | 7 + vendor/dxs-bsv-token-sdk/dist/base.js.map | 1 + vendor/dxs-bsv-token-sdk/dist/binary.d.ts | 30 + vendor/dxs-bsv-token-sdk/dist/binary.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/binary.js | 117 + vendor/dxs-bsv-token-sdk/dist/binary.js.map | 1 + .../dist/bitcoin/address.d.ts | 12 + .../dist/bitcoin/address.d.ts.map | 1 + .../dxs-bsv-token-sdk/dist/bitcoin/address.js | 30 + .../dist/bitcoin/address.js.map | 1 + .../dist/bitcoin/destination.d.ts | 8 + .../dist/bitcoin/destination.d.ts.map | 1 + .../dist/bitcoin/destination.js | 3 + .../dist/bitcoin/destination.js.map | 1 + .../dxs-bsv-token-sdk/dist/bitcoin/index.d.ts | 16 + .../dist/bitcoin/index.d.ts.map | 1 + .../dxs-bsv-token-sdk/dist/bitcoin/index.js | 32 + .../dist/bitcoin/index.js.map | 1 + .../dist/bitcoin/mnemonic.d.ts | 15 + .../dist/bitcoin/mnemonic.d.ts.map | 1 + .../dist/bitcoin/mnemonic.js | 47 + .../dist/bitcoin/mnemonic.js.map | 1 + .../dist/bitcoin/network.d.ts | 8 + .../dist/bitcoin/network.d.ts.map | 1 + .../dxs-bsv-token-sdk/dist/bitcoin/network.js | 10 + .../dist/bitcoin/network.js.map | 1 + .../dist/bitcoin/op-codes.d.ts | 123 + .../dist/bitcoin/op-codes.d.ts.map | 1 + .../dist/bitcoin/op-codes.js | 127 + .../dist/bitcoin/op-codes.js.map | 1 + .../dist/bitcoin/out-point.d.ts | 23 + .../dist/bitcoin/out-point.d.ts.map | 1 + .../dist/bitcoin/out-point.js | 55 + .../dist/bitcoin/out-point.js.map | 1 + .../dist/bitcoin/payment.d.ts | 8 + .../dist/bitcoin/payment.d.ts.map | 1 + .../dxs-bsv-token-sdk/dist/bitcoin/payment.js | 3 + .../dist/bitcoin/payment.js.map | 1 + .../dist/bitcoin/private-key.d.ts | 16 + .../dist/bitcoin/private-key.d.ts.map | 1 + .../dist/bitcoin/private-key.js | 108 + .../dist/bitcoin/private-key.js.map | 1 + .../dist/bitcoin/script-type.d.ts | 12 + .../dist/bitcoin/script-type.d.ts.map | 1 + .../dist/bitcoin/script-type.js | 16 + .../dist/bitcoin/script-type.js.map | 1 + .../dist/bitcoin/sig-hash-type.d.ts | 8 + .../dist/bitcoin/sig-hash-type.d.ts.map | 1 + .../dist/bitcoin/sig-hash-type.js | 12 + .../dist/bitcoin/sig-hash-type.js.map | 1 + .../dist/bitcoin/token-scheme.d.ts | 26 + .../dist/bitcoin/token-scheme.d.ts.map | 1 + .../dist/bitcoin/token-scheme.js | 30 + .../dist/bitcoin/token-scheme.js.map | 1 + .../dist/bitcoin/transaction-input.d.ts | 11 + .../dist/bitcoin/transaction-input.d.ts.map | 1 + .../dist/bitcoin/transaction-input.js | 27 + .../dist/bitcoin/transaction-input.js.map | 1 + .../dist/bitcoin/transaction-output.d.ts | 16 + .../dist/bitcoin/transaction-output.d.ts.map | 1 + .../dist/bitcoin/transaction-output.js | 51 + .../dist/bitcoin/transaction-output.js.map | 1 + .../dist/bitcoin/transaction.d.ts | 14 + .../dist/bitcoin/transaction.d.ts.map | 1 + .../dist/bitcoin/transaction.js | 19 + .../dist/bitcoin/transaction.js.map | 1 + .../dist/bitcoin/wallet.d.ts | 22 + .../dist/bitcoin/wallet.d.ts.map | 1 + .../dxs-bsv-token-sdk/dist/bitcoin/wallet.js | 43 + .../dist/bitcoin/wallet.js.map | 1 + vendor/dxs-bsv-token-sdk/dist/bsv.d.ts | 9 + vendor/dxs-bsv-token-sdk/dist/bsv.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/bsv.js | 55 + vendor/dxs-bsv-token-sdk/dist/bsv.js.map | 1 + .../dist/buffer/buffer-reader.d.ts | 2 + .../dist/buffer/buffer-reader.d.ts.map | 1 + .../dist/buffer/buffer-reader.js | 6 + .../dist/buffer/buffer-reader.js.map | 1 + .../dist/buffer/buffer-utils.d.ts | 16 + .../dist/buffer/buffer-utils.d.ts.map | 1 + .../dist/buffer/buffer-utils.js | 129 + .../dist/buffer/buffer-utils.js.map | 1 + .../dist/buffer/buffer-writer.d.ts | 2 + .../dist/buffer/buffer-writer.d.ts.map | 1 + .../dist/buffer/buffer-writer.js | 6 + .../dist/buffer/buffer-writer.js.map | 1 + .../dxs-bsv-token-sdk/dist/buffer/index.d.ts | 4 + .../dist/buffer/index.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/buffer/index.js | 20 + .../dist/buffer/index.js.map | 1 + vendor/dxs-bsv-token-sdk/dist/bytes.d.ts | 8 + vendor/dxs-bsv-token-sdk/dist/bytes.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/bytes.js | 55 + vendor/dxs-bsv-token-sdk/dist/bytes.js.map | 1 + .../dist/dstas-bundle-factory.d.ts | 93 + .../dist/dstas-bundle-factory.d.ts.map | 1 + .../dist/dstas-bundle-factory.js | 436 ++ .../dist/dstas-bundle-factory.js.map | 1 + .../dxs-bsv-token-sdk/dist/dstas-factory.d.ts | 110 + .../dist/dstas-factory.d.ts.map | 1 + .../dxs-bsv-token-sdk/dist/dstas-factory.js | 360 + .../dist/dstas-factory.js.map | 1 + .../dist/dstas-tx-assembly.d.ts | 43 + .../dist/dstas-tx-assembly.d.ts.map | 1 + .../dist/dstas-tx-assembly.js | 97 + .../dist/dstas-tx-assembly.js.map | 1 + vendor/dxs-bsv-token-sdk/dist/dstas.d.ts | 3 + vendor/dxs-bsv-token-sdk/dist/dstas.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/dstas.js | 22 + vendor/dxs-bsv-token-sdk/dist/dstas.js.map | 1 + vendor/dxs-bsv-token-sdk/dist/hashes.d.ts | 5 + vendor/dxs-bsv-token-sdk/dist/hashes.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/hashes.js | 14 + vendor/dxs-bsv-token-sdk/dist/hashes.js.map | 1 + vendor/dxs-bsv-token-sdk/dist/index.d.ts | 4 + vendor/dxs-bsv-token-sdk/dist/index.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/index.js | 40 + vendor/dxs-bsv-token-sdk/dist/index.js.map | 1 + .../script/build/asm-template-builder.d.ts | 4 + .../build/asm-template-builder.d.ts.map | 1 + .../dist/script/build/asm-template-builder.js | 50 + .../script/build/asm-template-builder.js.map | 1 + .../script/build/dstas-locking-builder.d.ts | 23 + .../build/dstas-locking-builder.d.ts.map | 1 + .../script/build/dstas-locking-builder.js | 114 + .../script/build/dstas-locking-builder.js.map | 1 + .../dist/script/build/null-data-builder.d.ts | 6 + .../script/build/null-data-builder.d.ts.map | 1 + .../dist/script/build/null-data-builder.js | 22 + .../script/build/null-data-builder.js.map | 1 + .../dist/script/build/p2mpkh-builder.d.ts | 6 + .../dist/script/build/p2mpkh-builder.d.ts.map | 1 + .../dist/script/build/p2mpkh-builder.js | 24 + .../dist/script/build/p2mpkh-builder.js.map | 1 + .../dist/script/build/p2pkh-builder.d.ts | 9 + .../dist/script/build/p2pkh-builder.d.ts.map | 1 + .../dist/script/build/p2pkh-builder.js | 33 + .../dist/script/build/p2pkh-builder.js.map | 1 + .../dist/script/build/p2stas-builder.d.ts | 7 + .../dist/script/build/p2stas-builder.d.ts.map | 1 + .../dist/script/build/p2stas-builder.js | 33 + .../dist/script/build/p2stas-builder.js.map | 1 + .../dist/script/build/script-builder.d.ts | 24 + .../dist/script/build/script-builder.d.ts.map | 1 + .../dist/script/build/script-builder.js | 126 + .../dist/script/build/script-builder.js.map | 1 + .../dist/script/dstas-action-data.d.ts | 30 + .../dist/script/dstas-action-data.d.ts.map | 1 + .../dist/script/dstas-action-data.js | 132 + .../dist/script/dstas-action-data.js.map | 1 + .../script/dstas-requested-script-hash.d.ts | 13 + .../dstas-requested-script-hash.d.ts.map | 1 + .../script/dstas-requested-script-hash.js | 31 + .../script/dstas-requested-script-hash.js.map | 1 + .../dist/script/dstas-swap-script.d.ts | 5 + .../dist/script/dstas-swap-script.d.ts.map | 1 + .../dist/script/dstas-swap-script.js | 103 + .../dist/script/dstas-swap-script.js.map | 1 + .../dist/script/eval/script-evaluator.d.ts | 66 + .../script/eval/script-evaluator.d.ts.map | 1 + .../dist/script/eval/script-evaluator.js | 1083 +++ .../dist/script/eval/script-evaluator.js.map | 1 + .../dist/script/identity-field.d.ts | 13 + .../dist/script/identity-field.d.ts.map | 1 + .../dist/script/identity-field.js | 59 + .../dist/script/identity-field.js.map | 1 + .../dxs-bsv-token-sdk/dist/script/index.d.ts | 23 + .../dist/script/index.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/script/index.js | 39 + .../dist/script/index.js.map | 1 + .../dist/script/read/base-script-reader.d.ts | 19 + .../script/read/base-script-reader.d.ts.map | 1 + .../dist/script/read/base-script-reader.js | 143 + .../script/read/base-script-reader.js.map | 1 + .../read/dstas-locking-script-decomposer.d.ts | 24 + .../dstas-locking-script-decomposer.d.ts.map | 1 + .../read/dstas-locking-script-decomposer.js | 143 + .../dstas-locking-script-decomposer.js.map | 1 + .../dstas-unlocking-script-decomposer.d.ts | 22 + ...dstas-unlocking-script-decomposer.d.ts.map | 1 + .../read/dstas-unlocking-script-decomposer.js | 261 + .../dstas-unlocking-script-decomposer.js.map | 1 + .../script/read/locking-script-reader.d.ts | 41 + .../read/locking-script-reader.d.ts.map | 1 + .../dist/script/read/locking-script-reader.js | 278 + .../script/read/locking-script-reader.js.map | 1 + .../dist/script/read/script-read-token.d.ts | 9 + .../script/read/script-read-token.d.ts.map | 1 + .../dist/script/read/script-read-token.js | 15 + .../dist/script/read/script-read-token.js.map | 1 + .../script/read/script-reader-extensions.d.ts | 7 + .../read/script-reader-extensions.d.ts.map | 1 + .../script/read/script-reader-extensions.js | 22 + .../read/script-reader-extensions.js.map | 1 + .../dist/script/read/script-reader.d.ts | 11 + .../dist/script/read/script-reader.d.ts.map | 1 + .../dist/script/read/script-reader.js | 87 + .../dist/script/read/script-reader.js.map | 1 + .../dist/script/script-samples.d.ts | 8 + .../dist/script/script-samples.d.ts.map | 1 + .../dist/script/script-samples.js | 127 + .../dist/script/script-samples.js.map | 1 + .../dist/script/script-token.d.ts | 17 + .../dist/script/script-token.d.ts.map | 1 + .../dist/script/script-token.js | 56 + .../dist/script/script-token.js.map | 1 + .../dist/script/script-utils.d.ts | 5 + .../dist/script/script-utils.d.ts.map | 1 + .../dist/script/script-utils.js | 13 + .../dist/script/script-utils.js.map | 1 + .../dstas-locking-template-base.d.ts | 8 + .../dstas-locking-template-base.d.ts.map | 1 + .../templates/dstas-locking-template-base.js | 47 + .../dstas-locking-template-base.js.map | 1 + .../templates/dstas-locking-template.d.ts | 2 + .../templates/dstas-locking-template.d.ts.map | 1 + .../templates/dstas-locking-template.js | 7 + .../templates/dstas-locking-template.js.map | 1 + .../dist/security/strict-mode.d.ts | 21 + .../dist/security/strict-mode.d.ts.map | 1 + .../dist/security/strict-mode.js | 34 + .../dist/security/strict-mode.js.map | 1 + .../dist/stas-bundle-factory.d.ts | 35 + .../dist/stas-bundle-factory.d.ts.map | 1 + .../dist/stas-bundle-factory.js | 226 + .../dist/stas-bundle-factory.js.map | 1 + vendor/dxs-bsv-token-sdk/dist/stas.d.ts | 3 + vendor/dxs-bsv-token-sdk/dist/stas.d.ts.map | 1 + vendor/dxs-bsv-token-sdk/dist/stas.js | 22 + vendor/dxs-bsv-token-sdk/dist/stas.js.map | 1 + .../dist/transaction-factory.d.ts | 43 + .../dist/transaction-factory.d.ts.map | 1 + .../dist/transaction-factory.js | 93 + .../dist/transaction-factory.js.map | 1 + .../dist/transaction/build/input-builder.d.ts | 46 + .../transaction/build/input-builder.d.ts.map | 1 + .../dist/transaction/build/input-builder.js | 404 ++ .../transaction/build/input-builder.js.map | 1 + .../transaction/build/output-builder.d.ts | 10 + .../transaction/build/output-builder.d.ts.map | 1 + .../dist/transaction/build/output-builder.js | 20 + .../transaction/build/output-builder.js.map | 1 + .../build/transaction-builder.d.ts | 36 + .../build/transaction-builder.d.ts.map | 1 + .../transaction/build/transaction-builder.js | 154 + .../build/transaction-builder.js.map | 1 + .../dist/transaction/index.d.ts | 5 + .../dist/transaction/index.d.ts.map | 1 + .../dist/transaction/index.js | 21 + .../dist/transaction/index.js.map | 1 + .../transaction/read/transaction-reader.d.ts | 12 + .../read/transaction-reader.d.ts.map | 1 + .../transaction/read/transaction-reader.js | 47 + .../read/transaction-reader.js.map | 1 + vendor/dxs-bsv-token-sdk/package.json | 86 + vite.config.ts | 51 +- 341 files changed, 26950 insertions(+), 1442 deletions(-) create mode 100644 MULTI-PROTOCOL-TOKENS.md create mode 100644 electron/stas-migrations/0001_create_stas_tables.ts create mode 100644 electron/stas-migrations/0002_add_protocol_column.ts create mode 100644 electron/stas-migrations/0003_bsv21_receive_contexts.ts create mode 100644 electron/stas-migrations/0004_token_verifications.ts create mode 100644 electron/stas-migrations/index.ts create mode 100644 electron/stas-queries.ts create mode 100644 src/lib/components/StasTransferPermissionHandler/index.tsx create mode 100644 src/lib/constants/baskets.ts create mode 100644 src/lib/pages/Dashboard/AssetsPage.tsx create mode 100644 src/lib/pages/Dashboard/BasketsPage.tsx create mode 100644 src/lib/pages/Dashboard/PeerTokens/index.tsx create mode 100644 src/lib/pages/Dashboard/Transfers/index.tsx create mode 100644 src/lib/services/stas/StasDiscoveryService.ts create mode 100644 src/lib/services/stas/StasKeyDeriver.ts create mode 100644 src/lib/services/stas/StasOwnershipService.ts create mode 100644 src/lib/services/stas/StasRegistration.ts create mode 100644 src/lib/services/stas/StasTransferService.ts create mode 100644 src/lib/services/stas/buildChainedAtomicBeef.ts create mode 100644 src/lib/services/stas/constants.ts create mode 100644 src/lib/services/stas/dstasParser.ts create mode 100644 src/lib/services/stas/findCreateContractTxid.ts create mode 100644 src/lib/services/stas/index.ts create mode 100644 src/lib/services/stas/parseClassicStasMetadata.ts create mode 100644 src/lib/services/stas/stasIpc.ts create mode 100644 src/lib/services/tokens/BSV21ProtocolAdapter.ts create mode 100644 src/lib/services/tokens/DstasProtocolAdapter.ts create mode 100644 src/lib/services/tokens/StasProtocolAdapter.ts create mode 100644 src/lib/services/tokens/TokenProtocolAdapter.ts create mode 100644 src/lib/services/tokens/TokenProtocolRegistry.ts create mode 100644 src/lib/services/tokens/TokenVerificationService.ts create mode 100644 src/lib/services/tokens/bsv21/BSV21DiscoveryService.ts create mode 100644 src/lib/services/tokens/bsv21/BSV21KeyDeriver.ts create mode 100644 src/lib/services/tokens/bsv21/BSV21Registration.ts create mode 100644 src/lib/services/tokens/bsv21/BSV21TransferService.ts create mode 100644 src/lib/services/tokens/bsv21/OneSatIndexerClient.ts create mode 100644 src/lib/services/tokens/bsv21/constants.ts create mode 100644 src/lib/services/tokens/bsv21/index.ts create mode 100644 src/lib/services/tokens/bsv21/inscription.ts create mode 100644 src/lib/services/tokens/dstas/DstasTransferService.ts create mode 100644 src/lib/services/tokens/dstas/buildDstasUnlockingScript.ts create mode 100644 src/lib/services/tokens/index.ts create mode 100644 src/lib/services/tokens/peer/Bsv21TokenSettlementAdapter.ts create mode 100644 src/lib/services/tokens/peer/DstasTokenSettlementAdapter.ts create mode 100644 src/lib/services/tokens/peer/StasTokenSettlementAdapter.ts create mode 100644 src/lib/services/tokens/peer/brc29KeyId.ts create mode 100644 src/lib/services/tokens/peer/loadPeerHoldings.ts create mode 100644 src/lib/services/tokens/peer/tokenSettlementTypes.ts create mode 100644 src/lib/services/tokens/tokenLog.ts create mode 100644 src/lib/services/tokens/verifyOnReceive.ts create mode 100644 src/lib/services/tokens/woc/BackToGenesisClient.ts create mode 100644 src/lib/services/tokens/woc/WocTokenIndexerClient.ts create mode 100644 src/lib/types/StasTransferRequest.ts create mode 100644 test/stas/derivation.test.ts create mode 100644 test/stas/discovery.test.ts create mode 100644 test/stas/migration.test.ts create mode 100644 test/stas/ownership.test.ts create mode 100644 test/stas/registration.test.ts create mode 100644 test/tokens/back-to-genesis.test.ts create mode 100644 test/tokens/bsv21-inscription.test.ts create mode 100644 test/tokens/dstas-transfer.test.ts create mode 100644 test/tokens/token-verification.test.ts create mode 100644 test/tokens/verify-on-receive.test.ts create mode 100644 test/tokens/woc-indexer.test.ts create mode 100644 vendor/dxs-bsv-token-sdk/README.md create mode 100644 vendor/dxs-bsv-token-sdk/dist/base.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/base.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/base.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/base.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/binary.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/binary.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/binary.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/binary.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/address.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/address.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/address.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/address.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/index.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/index.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/index.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/index.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/network.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/network.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/network.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/network.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bsv.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bsv.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bsv.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bsv.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/index.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/index.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/index.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/buffer/index.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bytes.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/bytes.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/bytes.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/bytes.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-factory.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-factory.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-factory.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-factory.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/dstas.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/hashes.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/hashes.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/hashes.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/hashes.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/index.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/index.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/index.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/index.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/identity-field.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/identity-field.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/identity-field.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/identity-field.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/index.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/index.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/index.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/index.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-samples.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-samples.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-samples.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-samples.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-token.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-token.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-token.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-token.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-utils.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-utils.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-utils.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/script-utils.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/security/strict-mode.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/security/strict-mode.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/security/strict-mode.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/security/strict-mode.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/stas.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/stas.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/stas.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/stas.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction-factory.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction-factory.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction-factory.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction-factory.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/index.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/index.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/index.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/index.js.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.d.ts create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.d.ts.map create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.js create mode 100644 vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.js.map create mode 100644 vendor/dxs-bsv-token-sdk/package.json diff --git a/.gitignore b/.gitignore index 0ff1e35..0fee2a3 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,11 @@ dist dist-electron release *.local + +# Allow vendored library dist/ (e.g. vendor/dxs-bsv-token-sdk/dist) so the +# fork is buildable standalone without the parent monorepo checked out. +!vendor/** + docs/superpowers # Editor directories and files diff --git a/AGENTS.md b/AGENTS.md index 2072fc5..6441a4e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -127,7 +127,7 @@ Main Process (storage.ts) ↓ StorageManager.callMethod() StorageKnex ↓ Knex queries -SQLite (~/.bsv-desktop/wallet.db) +SQLite (~/.bsv-desktop/wallet--main.db) ``` **Remote Storage** (`useRemoteStorage: true`): @@ -280,7 +280,7 @@ Worker Process **Local (Electron)**: - Modify `electron/storage.ts` for IPC handlers - Update `src/StorageElectronIPC.ts` for proxy methods -- Database at `~/.bsv-desktop/wallet.db` or `wallet-test.db` +- Database files at `~/.bsv-desktop/wallet--main.db` (mainnet) or `…-test.db` (testnet). One file per identity key; the bare `wallet.db` is legacy and empty on new installs. **Remote (WAB)**: - Uses `StorageClient` from `@bsv/wallet-toolbox` @@ -339,8 +339,8 @@ curl -X POST http://127.0.0.1:3321/listOutputs \ ### Database -- Location: `~/.bsv-desktop/wallet.db` (mainnet) or `wallet-test.db` (testnet) -- WAL mode files: `wallet.db-wal`, `wallet.db-shm` +- Per-identity files: `~/.bsv-desktop/wallet--main.db` (mainnet) or `…-test.db` (testnet). To find your active DB, grep the wallet log for `identityKey: …`, then match the hex prefix. +- WAL mode files: `-wal`, `-shm` - Delete database: `rm -rf ~/.bsv-desktop/` (forces re-initialization) ## Common Patterns diff --git a/MULTI-PROTOCOL-TOKENS.md b/MULTI-PROTOCOL-TOKENS.md new file mode 100644 index 0000000..a0d8d93 --- /dev/null +++ b/MULTI-PROTOCOL-TOKENS.md @@ -0,0 +1,571 @@ +# Multi-protocol token support — what changed and why + +> Handoff document for the `close-out` branch. Audience: a developer who already +> knows BSV Desktop's STAS-era architecture and needs to understand how it grew +> to support three token protocols at once. + +## TL;DR + +The wallet went from **STAS-only** to **STAS + DSTAS + BSV-21**. A new +`TokenProtocolAdapter` seam abstracts protocol-specific work (script parsing, +transfer building, basket routing); the existing STAS pipeline is now a +concrete adapter; DSTAS and BSV-21 are two more. + +**Discovery reality (verified empirically 2026-05-28):** the three +protocols sit in three different states: + +- **Classic STAS** — Bitails's STAS-aware indexer surfaces these + (mempool + confirmed). `StasDiscoveryService.scan()` works. +- **DSTAS** — no public indexer. Bitails's STAS-aware matcher locks + onto the classic `76a914…88ac69` wrap and skips the DSTAS template + entirely. WoC's curated registry returns `utxos: null` for any + self-broadcast token. Receives flow through `/stas/register-by-txid`. +- **BSV-21** — the 1Sat overlay DOES index BSV-21 outputs once the + inscription is canonical AND deploys are auto-picked-up by JungleBus. + But it has a three-gate validation chain (see §5 below) that our + inscription builder previously failed. Once fixed: + - **Deploys** index immediately via JungleBus → discovery topic + (`tm_bsv21`). `/1sat/bsv21/{tokenId}` returns full metadata. + - **Transfers** require the per-token topic-manager (`tm_{tokenId}`) + to be active — which 1sat-stack gates on the issuer funding the + `fee_address` (typically 1000 sats per output). Until the token is + "active", transfers can't be ingested by the overlay. They still + broadcast on-chain and the dex-shell's `/bsv-21/register-by-txid` + fast-path surfaces them at the recipient's colocated wallet. + +So all three protocols share the same architectural fallback — +`register-by-txid` — and BSV-21 additionally gets free deploy-discovery +via JungleBus once the inscription is canonical. + +Three database migrations land in this PR. No breaking changes to the BRC-100 +HTTP Apps API surface (`/stas/list`, `/stas/transfer`, etc.) — they remain +STAS-shaped. New parallel routes for BSV-21 exist as demo fast-paths only. + +--- + +## What the wallet was before + +Single-protocol STAS pipeline: + +- One satellite table per concept (`stas_tokens`, `stas_outputs`, + `stas_receive_contexts`). +- One basket (`stas-tokens`) for token UTXOs. +- One discovery service (`StasDiscoveryService`) that ran a per-address Bitails + scan and registered matches. +- One transfer service (`StasTransferService`) that handled the stas-js engine + flow (CreateContract + Issue, BRC-42 unlock, sighash + createSignature). +- One BRC-42 protocol-id (`'stas token ownership'`) for receive-key derivation. +- The renderer assumed every UTXO in `stas_outputs` was classic STAS even + though `StasDiscoveryService` silently also handled DSTAS via + `dstasParser.ts`. DSTAS-shaped outputs co-existed in the same basket with + no schema awareness — they were identified by re-parsing the locking script. +- Transfer worked only for classic STAS. DSTAS UTXOs that the user happened + to receive would fail at send-time with a generic *"Invalid STAS script"*. + +That was fine for a single-protocol demo and not fine for the next two protocols. + +--- + +## What this PR added + +### 1. A protocol-adapter seam (`src/lib/services/tokens/`) + +`TokenProtocolAdapter` is the cross-protocol contract: + +```ts +interface TokenProtocolAdapter { + id: 'stas' | 'dstas' | 'bsv-21' + basketName: string + displayName: string + transferSupported: boolean + parseOutput(scriptHex, ctx?): Promise + transfer?(args): Promise +} +``` + +Three concrete adapters: + +- **`StasProtocolAdapter`** — wraps `parseClassicStasMetadata` + + `findCreateContractTxid` + `StasTransferService.transfer`. + `transferSupported: true`. Basket: `stas-tokens`. +- **`DstasProtocolAdapter`** — wraps `parseDstasLockingScript` from + `dstasParser` + `DstasTransferService`. `transferSupported: true` — + spending-type 1 (regular transfer) is supported, see `DstasTransferService` + + `buildDstasUnlockingScript` which mirror the SDK's + `input-builder.ts:91-178` byte-for-byte. Basket: `dstas-tokens`. +- **`BSV21ProtocolAdapter`** — wraps the inline inscription parser + a + `BSV21TransferService` using standard `createAction`/`signAction`. + `transferSupported: true`. Basket: `bsv-21-tokens`. + +A `TokenProtocolRegistry` holds the three adapters. `find(scriptHex, ctx)` walks +them in registration order (STAS prefix sniff first — cheapest — then DSTAS SDK +reader, then BSV-21 ord-envelope match) and returns the first that recognises +the script. `getById(id)` is used by the send dialog to pick the right transfer +path for a given UTXO. + +The registry is exposed on `stas.tokens` from `WalletService` so the renderer +can dispatch sends without knowing protocol internals. + +### 2. Per-protocol baskets + +`src/lib/constants/baskets.ts`: + +```ts +export const STAS_BASKET = 'stas-tokens' +export const DSTAS_BASKET = 'dstas-tokens' +export const BSV21_BASKET = 'bsv-21-tokens' +export const TOKEN_BASKETS = [STAS_BASKET, DSTAS_BASKET, BSV21_BASKET] as const +``` + +Discovery's spendable-flag backfill iterates `TOKEN_BASKETS` so each protocol's +basket gets the same `setOutputSpendable(true)` treatment STAS got historically +(wallet-toolbox marks non-stock-template outputs `spendable=false` by default; +all three of our protocols need the flag flipped post-internalize). + +### 3. Database migrations (additive) + +| Migration | What it does | +|---|---| +| `0001_create_stas_tables.ts` | Original — `stas_tokens`, `stas_outputs`, `stas_receive_contexts`. Unchanged. | +| `0002_add_protocol_column.ts` | Adds `protocol TEXT NOT NULL DEFAULT 'stas'` to `stas_outputs` and `stas_tokens`. Backfills any DSTAS-shaped row in `stas_outputs` to `protocol = 'dstas'`. Moves those rows' wallet-toolbox `outputs.basketId` to a new `dstas-tokens` basket. Wrapped in `knex.transaction`. | +| `0003_bsv21_receive_contexts.ts` | Creates `bsv21_receive_contexts` mirroring the STAS variant — `(profileIdentityKey, keyIndex, keyId, ownerHash160, derivedPublicKey, createdAt)` unique on `(profileIdentityKey, keyIndex)`. No `bsv21_tokens` / `bsv21_outputs` satellite — BSV-21 metadata (`id/amt/dec/sym/icon`) lives on wallet-toolbox basket tags by the 1sat-toolbox convention, so the satellite is receive-only. | + +The DSTAS basket split (0002) is the only data-mutating migration. Forward-only; +running it on an empty wallet is a no-op other than the `ALTER TABLE` additions. + +### 4. Discovery model — per-protocol coverage + +Empirically verified 2026-05-28 by minting + sending each protocol's +tokens to wallet-derived addresses and observing what gets indexed: + +``` + STAS → StasDiscoveryService.scan() via Bitails + /stas/register-by-txid + ✓ mempool + confirmed coverage on `tokens/ (immediate UI feedback) + unspent` per address + + DSTAS → *** no public indexer *** /stas/register-by-txid + (Bitails's matcher locks onto classic STAS (THIS is the only working + P2PKH wrap; DSTAS template starts with a raw receive path — same route + 20-byte push and falls outside the scan rule) as STAS; registry dispatch + picks the DSTAS adapter) + + BSV-21 → JungleBus → 1Sat overlay's BSV-21 topic-mgr + /bsv-21/register-by-txid + ✓ DEPLOYS auto-index (`/1sat/bsv21/{tokenId}` (immediate UI feedback + returns metadata) AS LONG AS the inscription + transfer fallback) + passes 3 validity gates (see §6). + ✗ TRANSFERS only index for tokens whose per- + token topic-manager is "active" — gated on the + issuer funding `fee_address` (1sat-stack's + commercial model). Until then, transfers + broadcast successfully on-chain but don't + surface at recipient addresses via /1sat/owner. + register-by-txid covers this gap for the + colocated demo path. +``` + +**The `register-by-txid` HTTP routes bind to 127.0.0.1, not a public +surface.** They're the universal fallback. STAS gets free indexing via +Bitails on top. BSV-21 gets free indexing for deploys via JungleBus on +top, plus optionally for transfers if the token is activated. DSTAS only +has the localhost path. + +Why each gap exists: + +- **STAS via Bitails** — works because Bitails recognises the classic + P2PKH-wrapped STAS prefix. +- **DSTAS** — DSTAS outputs lead with a bare 20-byte push instead of + the P2PKH wrap; they fall outside Bitails's scan rule. WoC's + `stas-tokens-beta` endpoint is a curated registry (returns + `utxos: null` for newly-minted tokens of either template). A + dedicated DSTAS indexer (self-hosted overlay, Bitails matcher + extension, or relay protocol) would close the gap; the wallet code + is structured so adding one is mechanical — implement a + `DstasDiscoveryService` mirroring the BSV21 one and wire it. +- **BSV-21 transfers** — the 1sat-stack pipeline has two topic-managers + per BSV-21 token: `tm_bsv21` (discovery; admits deploys; auto-fed by + JungleBus) and `tm_` (per-token; admits transfers; only + spins up after fee activation). For demo / unfunded tokens, only + deploys index; transfers wait on activation. The wallet's send-flow + submits BEEF best-effort to `/1sat/bsv21/overlay/submit` (matching + `@1sat/client`'s pattern) and logs a 500 warning when the per-token + worker is absent — the broadcast still succeeds. + +### 5. BSV-21 ord-inscription handling + +Canonical on-chain output format (verified against indexed tokens like +`$NINJAPUNKGIRLS` and our own end-to-end test): + +``` +00 63 OP_FALSE OP_IF +03 6f7264 push "ord" +51 OP_1 (content-type tag — canonical + minimal push, NOT `01 01`) +12 6170706c69636174696f6e2f6273762d3230 push "application/bsv-20" +00 OP_0 (separator) + {"p":"bsv-20","op":"deploy+mint"|"transfer", + "id":"_", ← UNDERSCORE (transfer only) + "amt":"", ← STRING bigint + "dec":"", ← STRING (not number) + "sym":"",…} +68 OP_ENDIF +76 a9 14 <20-byte pkh> 88 ac standard P2PKH owner script +``` + +Three byte/JSON-level validity gates the 1sat-stack +`go-templates/bsv21` decoder enforces (all three silently reject +violators — they return nil, no error message): + +1. **Content-type tag must be OP_1 (0x51)**, the canonical minimal push. + Non-minimal `01 01` (push 1 byte of value 0x01) is rejected. +2. **Every JSON value must be a string.** The decoder does + `json.Unmarshal(content, &map[string]string{})` — a numeric `"dec":10` + fails the unmarshal. Must be `"dec":"10"`. +3. **Transfer `id` field must be `_` (underscore).** Dot + form (the convention used for outpoints elsewhere) is rejected. The + wallet normalizes at the boundary in `BSV21TransferService` since + some registration paths historically wrote the dot form into basket + tags. + +These gates apply to BOTH our direct overlay submit AND to JungleBus's +auto-pickup. Three regression tests in `test/tokens/bsv21-inscription.test.ts` +lock each gate in with byte-level assertions on the produced script. + +Implementation (no SDK dependency for the envelope): + +- `src/lib/services/tokens/bsv21/inscription.ts` — `buildBsv21Transfer` + + `parseBsv21LockingScript`. Pure, ~200 LOC. Parser accepts both canonical + and legacy forms so we don't break older outputs already in baskets. +- The trailing P2PKH means **wallet-toolbox can sign the input natively** via + the standard sighash + the wallet's `createSignature` path. No engine, no + custom unlock template, no `partialSTASUnlockingScript`-style trickery. + Token id = `_` of the deploy+mint outpoint. + +### 6. The 1Sat overlay coupling + +The 1sat-stack architecture has two ingest paths and three topic-managers +that matter for our wallet: + +``` + ┌─── tm_bsv21 ─────────┐ + │ (discovery topic) │ + JungleBus ────►│ admits deploys ├──► /1sat/bsv21/{tokenId} + subscriber │ triggers per-token │ /1sat/owner/{addr}/txos + │ worker creation │ + └───────────────────────┘ + │ + │ on deploy admission + + │ token activation (fee_address funded) + ▼ + ┌─── tm_{tokenId} ─────┐ + │ (per-token topic) │ + POST │ admits transfers ├──► per-token balance, + /1sat/bsv21/ ►│ validates ancestry │ /1sat/bsv21/{tokenId}/ + overlay/submit │ │ p2pkh/{addr}/unspent + └───────────────────────┘ +``` + +**For deploys (faucet path):** broadcast hits the chain → JungleBus +auto-picks-up → discovery topic admits → token metadata appears in +`/1sat/bsv21/{tokenId}`. Free, automatic, no submit needed — confirmed +empirically with our `1213` and `FB212` mints once the inscription was +canonical. The faucet's previous `POST /1sat/tx` step was redundant; +that endpoint is a broadcast pass-through (Arcade relay), not a +topic-manager ingest. + +**For transfers (wallet path):** the wallet POSTs the signed +AtomicBEEF to `POST /1sat/bsv21/overlay/submit` with the `X-Topics: +tm_` header. Matches `@1sat/client@0.0.38`'s +`OverlayClient.submitBsv21` exactly. Returns 200 STEAK when the +per-token worker is up; returns 500 with a generic error when it +isn't (tokens that haven't been activated). The wallet logs and +proceeds — the tx is broadcast separately through wallet-toolbox's +ARC, so user value isn't blocked on overlay coupling. + +**Public endpoints actually exposed on `api.1sat.app`:** +- `POST /1sat/bsv21/overlay/submit` — exists, returns 200 / 500 + depending on per-token worker availability. (`OPTIONS` returns 405 + Method Not Allowed; an earlier probe of `OPTIONS` misled us into + thinking the endpoint didn't exist.) +- `POST /bsv21/overlay/submit` (no `/1sat/` prefix) — 404 publicly, + but reachable via `wallet.1sat.app/bsv21/overlay/submit` with + BRC-103 mutual auth. Not used by our wallet; documented for + future reference. +- `POST /1sat/tx` — a public broadcast relay (returns + `ACCEPTED_BY_NETWORK`). Doesn't feed the topic-manager. The + wallet and the faucet used to hit this endpoint expecting + indexing; that was wrong. + +The faucet no longer submits to the overlay (relies on JungleBus). +The wallet submits during sends because it has the signed BEEF on +hand for free; the submit is best-effort with a console warning on +failure. + +### 7. AssetsPage UI + +- `OutputView` gained `protocol`, `tokenAmount`, `decimals`, `icon` fields. +- `groupByToken` keys on `(protocol, symbol, tokenId)` so a STAS and DSTAS that + happen to share a symbol stay separate. Token-amount sums use bigints + (`safeBigInt` defensively returns `0n` for malformed `amt` tag values). +- `formatTokenAmount(amt, dec)` renders raw bigint amounts with the right + decimal precision; malformed amounts render as `? ()` rather than + crashing the page. +- Group card carries a protocol-coloured chip ("STAS" filled / "DSTAS" outlined + / "BSV-21" outlined). +- Per-UTXO Send button is gated on `adapter.transferSupported`. All three + protocols now support transfer; the gate stays as a safety net for any + future adapter that ships with `transferSupported: false`. +- Receive card has a STAS / BSV-21 protocol toggle; DSTAS uses STAS's BRC-42 + namespace (intentional — DSTAS receive piggybacks on the STAS deriver). + +### 8. WalletService bundle + +`stas.tokens` is the new registry. The existing fields stay: + +```ts +stas: { + keyDeriver: StasKeyDeriver + ownership: StasOwnershipService + discovery: StasDiscoveryService + transfer: StasTransferService + + // New + tokens: TokenProtocolRegistry + bsv21KeyDeriver: BSV21KeyDeriver + bsv21Discovery: BSV21DiscoveryService + bsv21Indexer: OneSatIndexerClient +} +``` + +The `transfer` field is back-compat — it only handles classic STAS. New code +should route through `stas.tokens.getById(protocolId).transfer(...)`. + +### 9. Apps API HTTP surface + +| Route | Status | +|---|---| +| `GET /stas/list`, `POST /stas/receive-address`, `POST /stas/transfer`, `POST /stas/register-by-txid` | Unchanged; still STAS-shaped. | +| `POST /bsv-21/register-by-txid` | New — demo fast-path equivalent of the STAS one. Localhost only. | + +No new public route surfaces. External apps continue to talk to the STAS Apps +API unchanged. + +--- + +## Demo apps changes + +### `demo/stas-faucet/` + +Was a single-file Express server minting classic STAS via `stas-js`. Now a +multi-protocol faucet: + +- Refactored `server.mjs` into thin wiring + three protocol modules in `lib/` + (`mint-stas.mjs`, `mint-dstas.mjs`, `mint-bsv21.mjs`) sharing config, + key material, and WoC helpers. +- Three POST endpoints: `/api/send-stas`, `/api/send-dstas`, `/api/send-bsv-21`. + Same shared WIF funds all three; same `recentlyUsedOutpoints` tracker. +- `/api/info` now exposes a `protocols[]` catalog so the UI can drive itself + off the server's declared capabilities. +- The standalone faucet UI (`public/index.html`) gains a Classic STAS / DSTAS / + BSV-21 tab strip on the Mint card with protocol-specific input fields. +- DSTAS minting uses `dxs-bsv-token-sdk`'s `BuildDstasIssueTxs` — the SDK signs + internally given a `PrivateKey`, so no manual unlocking-script construction. +- BSV-21 minting builds the ord-inscription envelope inline (same code as the + wallet's parser), broadcasts via WhatsOnChain, **and** POSTs to + `https://api.1sat.app/1sat/tx` to couple the mint with the overlay's BSV-21 + topic-manager. The 1Sat submit is best-effort; a failure logs but doesn't + fail the mint (the tx is already on-chain). +- `amt` is now validated as `/^\d+$/` and rejected before broadcast — defends + against the user typing Lorem-Ipsum into the Amount field. + +### `demo/stas-dex-shell/` + +Was a STAS-only Mint tab. Now: + +- Protocol selector buttons (Classic STAS / DSTAS / BSV-21) above the existing + mint form. +- Hidden / shown fields per protocol (BSV-21 reveals `amt` + `dec`; STAS/DSTAS + show `symbol/name/satoshis`). +- After a successful mint, calls the matching wallet route: + - STAS → `/stas/register-by-txid` (basket: `stas-tokens`) + - DSTAS → `/stas/register-by-txid` (basket: `dstas-tokens` — same route, + registry dispatch picks the DSTAS adapter based on template) + - BSV-21 → `/bsv-21/register-by-txid` +- Result panel renders one txid for BSV-21 (deploy+mint is a single tx) or two + for STAS/DSTAS (Contract + Issue). + +--- + +## File index + +New files: + +``` +src/lib/services/tokens/ + TokenProtocolAdapter.ts interface + ParsedTokenOutput + TransferArgs/Result + TokenProtocolRegistry.ts singleton-ish holder + find()/getById() + StasProtocolAdapter.ts + DstasProtocolAdapter.ts + BSV21ProtocolAdapter.ts + bsv21/ + constants.ts BSV21_PROTOCOL_ID, ONESAT_API_DEFAULT_MAIN, etc. + inscription.ts build/parse the ord envelope (no SDK dep) + BSV21KeyDeriver.ts BRC-42 receive keys under the bsv21 protocol id + OneSatIndexerClient.ts REST + SSE client for api.1sat.app + BSV21Registration.ts internalizeAction into bsv-21-tokens basket + BSV21DiscoveryService.ts scan() + registerByTxid() + BSV21TransferService.ts createAction + signAction + optional origin guard + index.ts barrel exports + +electron/stas-migrations/ + 0002_add_protocol_column.ts + 0003_bsv21_receive_contexts.ts + +demo/stas-faucet/lib/ + config.mjs extracted env + defaults + wallet.mjs single-WIF key material + woc.mjs UTXO listing + balance + broadcast + mint-stas.mjs extracted from monolithic server.mjs + mint-dstas.mjs new — BuildDstasIssueTxs wrapper + mint-bsv21.mjs new — inscription builder (canonical OP_1 + content-type, string `dec`); relies on + JungleBus auto-pickup for overlay indexing +``` + +Modified files (non-trivial): + +``` +src/lib/constants/baskets.ts DSTAS_BASKET, BSV21_BASKET, TOKEN_BASKETS +src/lib/services/WalletService.ts instantiates all three adapters + indexer +src/lib/services/stas/StasDiscoveryService.ts dispatches through registry.find() +src/lib/services/stas/StasRegistration.ts accepts {id, basketName} protocol +src/lib/pages/Dashboard/AssetsPage.tsx protocol-aware grouping + decimal display +src/lib/WalletContext.tsx injects bsv21Discovery for the demo route +src/onWalletReady.ts /bsv-21/register-by-txid case +electron/stas-queries.ts protocol-aware writes + bsv21 receive CRUD +electron/stas-migrations/index.ts register 0002 + 0003 + +demo/stas-faucet/server.mjs slimmed to thin routing +demo/stas-faucet/public/index.html protocol selector + protocol-specific fields +demo/stas-dex-shell/public/index.html Mint tab protocol picker +demo/stas-dex-shell/public/app.js dispatch + per-protocol auto-register +demo/stas-dex-shell/public/styles.css .mint-proto-row styling +``` + +--- + +## Status of the original "known limitations" + +The first version of this doc listed five "limitations". A later review found three +of them were punts dressed up as constraints. All five have since been addressed: + +| Item | Original state | Now | +|---|---|---| +| **F1 — Vite production build** | `npm run build:renderer` failed on the vendored SDK's `__exportStar` re-exports (Rollup's CJS static analyser couldn't trace them). | **Fixed.** `vite.config.ts` sets `build.commonjsOptions = { include: [/dxs-bsv-token-sdk/, /node_modules/], transformMixedEsModules: true }`. Build succeeds. | +| **F2 — Wallet transfers don't reach the overlay** | `BSV21TransferService` only broadcast through wallet-toolbox's default ARC. | **Fixed.** After `signAction` succeeds, the service passes `signResp.tx` (the signed AtomicBEEF) to `OneSatIndexerClient.submitTransaction(beef, { tokenId })`, which POSTs to the correct endpoint `https://api.1sat.app/1sat/bsv21/overlay/submit` with `X-Topics: tm_` — matching `@1sat/client@0.0.38`'s `OverlayClient.submitBsv21` exactly. Returns 200 STEAK for transfers of activated tokens; returns 500 (with console warning, non-blocking) for inactive tokens whose per-token topic-manager isn't running. Earlier this column wrongly claimed `/1sat/tx` was the canonical endpoint — it's a broadcast relay. Three inscription-validity gates also fixed (see §5). | +| **F3 — DSTAS send** | `transferSupported: false`. | **Fixed (separate PR).** `DstasTransferService` + `buildDstasUnlockingScript` mirror the SDK's `input-builder.ts:91-178` byte-for-byte. Signature flows through `wallet.createSignature` with BRC-42 (same namespace as STAS). `evaluateTransactionHex(...)` is run pre-broadcast as a diagnostic (not a hard gate — input 1 is the BSV funding which isn't signed yet at evaluator time). DstasProtocolAdapter is now `transferSupported: true`. | +| **F4 — BSV-21 partial-amount send** | UI sent the full UTXO only. | **Fixed.** Send dialog has an Amount field for BSV-21 with validation. | +| **F5 — No tests for new code** | True — only existing STAS tests ran. | **Addressed.** `test/tokens/bsv21-inscription.test.ts` (15 tests, including 3 byte-level regression tests for the inscription validity gates) + `test/tokens/dstas-transfer.test.ts` (6 tests). Other new modules (OneSatIndexerClient SSE, BSV21Registration, migrations) still rely on manual verification. | + +## Outstanding work + +- **DSTAS organic-receive indexer.** Bitails doesn't match the DSTAS + template; receivers can't discover sent DSTAS via Refresh alone. The + wallet's existing `/stas/register-by-txid` route (which dispatches + through the protocol registry to the DSTAS adapter) is the working + receive path. Closing the gap requires a dedicated DSTAS indexer. +- **BSV-21 transfer indexing for unactivated tokens.** Deploys index + automatically via JungleBus → discovery topic. Transfers only index + when the token's per-token topic-manager is active, which 1sat-stack + gates on the issuer funding the `fee_address` (per-token commercial + model). The wallet's submit logs a 500 warning and proceeds; the tx + is already broadcast on-chain. For demo / unfunded tokens, the + dex-shell's `/bsv-21/register-by-txid` fast-path covers colocated + receives. + +Neither gap blocks current wallet functionality for the demo / +local-development case. + +Running the test suite: + +``` +npm run test:stas # adapter refactor didn't regress STAS +npm run test:tokens # BSV-21 inscription + DSTAS transfer +npm run build:renderer # prod build succeeds +``` + +--- + +## How to add a fourth protocol + +If you wanted to add, say, BSV-20 v1 tickers: + +1. **Adapter** — implement `TokenProtocolAdapter` in `src/lib/services/tokens/`. + `parseOutput` recognises the script shape; `transfer` is optional. Pick a + basket name and a `displayName`. +2. **Basket constant** — add `BSV20_BASKET = 'bsv-20-tokens'` to + `constants/baskets.ts` and include it in `TOKEN_BASKETS`. +3. **Receive keys** — if the protocol uses a distinct BRC-42 protocol id, mirror + `BSV21KeyDeriver` and add a `bsv20_receive_contexts` migration. If it + reuses one of the existing namespaces, skip. +4. **Discovery** — if the protocol's outputs are indexed at owner addresses by + the existing Bitails / 1Sat overlay scanners, plug the adapter into the + `TokenProtocolRegistry` (in `WalletService._buildWallet`) and the existing + scan loops will pick it up. If it needs its own indexer, mirror + `BSV21DiscoveryService` + indexer client. +5. **WalletService** — instantiate the deriver / discovery / transfer / indexer + in `_buildWallet`, register the adapter, expose any new services on the + `stas` bundle. +6. **AssetsPage** — add the new protocol to the `protocolLabel` switch + + chip-color logic. Add the per-protocol fields to the receive selector and + the send dialog if relevant. +7. **Migration** — 0004_*.ts for any schema additions. Register in + `stas-migrations/index.ts`. + +The adapter seam means none of this requires touching `StasDiscoveryService`, +`StasTransferService`, the existing migrations, or the BRC-100 HTTP Apps API. + +--- + +## Verification + +Manual (no test suite). The day-of-merge smoke test: + +1. Snapshot `~/.bsv-desktop/wallet--main.db` before first launch. +2. `npm run dev` — confirm 0002 + 0003 apply without errors in the Electron + log. Confirm any pre-existing DSTAS UTXO migrates from `stas-tokens` into + `dstas-tokens` basket (SQL: + `SELECT name, COUNT(*) FROM output_baskets b JOIN outputs o USING(basketId) WHERE name LIKE '%-tokens' GROUP BY name;`). +3. **STAS regression** — mint via the dex-shell with `Classic STAS`. Auto-registers + into `stas-tokens`. Send one UTXO to a fresh address — should be byte-identical + to pre-PR behavior. +4. **DSTAS mint + receive** — mint via the dex-shell with `DSTAS`. After mint, + see *"auto-registered into your dstas-tokens basket (1 output)"* in the + dex-shell result panel. The new row in Assets has an enabled Send button. + (Refresh from an unrelated wallet, by contrast, will NOT discover this + DSTAS — no public indexer covers the template.) +5. **DSTAS send** — pick the DSTAS UTXO, send to a fresh address. The + pre-broadcast `evaluateTransactionHex` diagnostic runs (non-blocking) and + the tx broadcasts via wallet-toolbox. +6. **BSV-21 mint + receive** — generate a BSV-21 receive address in the wallet + (Receive card → BSV-21 toggle → Generate). Paste into the dex-shell's BSV-21 + Mint tab. After mint, see *"auto-registered into your bsv-21-tokens basket + (1 output)"* in the dex-shell result panel. Refresh the wallet's Assets page + — the same UTXO should be discovered organically by the overlay too (proves + the indexer path works, not just the localhost shortcut). +7. **BSV-21 input validation** — submit the dex-shell mint with `amt = "lorem"`. + Faucet returns 500 with *"Invalid BSV-21 amt — must be a non-negative integer + string"* and broadcasts nothing. + +--- + +## References + +- yours-wallet (`@1sat/client`, `@1sat/actions`) — the production model we + matched for BSV-21 indexer coupling: +- 1sat-wallet-toolbox — the source-of-truth for the overlay's HTTP surface: + +- 1Sat Stack OpenAPI spec — `GET https://api.1sat.app/1sat/docs` (rendered) or + `GET https://api.1sat.app/api-spec/swagger.json` (raw) +- BSV-21 spec — +- DSTAS — uses `dxs-bsv-token-sdk`'s `BuildDstasIssueTxs` factory; SDK at + `workspace/dxs-bsv-token-sdk/` diff --git a/electron/main.ts b/electron/main.ts index 9198390..7b3c3ff 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -643,6 +643,19 @@ ipcMain.handle('secrets:delete', async (_event, name: string) => { vault.deleteSecret(name); }); +// STAS extension query channel — separate from storage:call-method so STAS +// queries do not share the StorageKnex method namespace. +ipcMain.handle('stas:query', async (_event, identityKey: string, chain: 'main' | 'test', method: string, args: any[]) => { + try { + const manager = await getStorageManager(); + const result = await manager.callStasQuery(identityKey, chain, method, args ?? []); + return { success: true, result }; + } catch (error: any) { + console.error('[IPC] stas:query error:', error); + return { success: false, error: error.message }; + } +}); + // ===== Auto-Update IPC Handlers ===== ipcMain.handle('update:check', async () => { diff --git a/electron/preload.ts b/electron/preload.ts index f306274..203e625 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -105,6 +105,12 @@ contextBridge.exposeInMainWorld('electronAPI', { set: (config: any): Promise => ipcRenderer.invoke('boot-config:set', config), }, + // STAS extension queries + stas: { + query: (identityKey: string, chain: 'main' | 'test', method: string, args: any[]) => + ipcRenderer.invoke('stas:query', identityKey, chain, method, args) + }, + // Auto-update operations updates: { check: () => ipcRenderer.invoke('update:check'), @@ -190,6 +196,9 @@ export interface ElectronAPI { get: () => Promise; set: (config: any) => Promise; }; + stas: { + query: (identityKey: string, chain: 'main' | 'test', method: string, args: any[]) => Promise<{ success: boolean; result?: any; error?: string }>; + }; updates: { check: () => Promise<{ success: boolean; updateInfo?: any; error?: string }>; download: () => Promise<{ success: boolean; error?: string }>; diff --git a/electron/stas-migrations/0001_create_stas_tables.ts b/electron/stas-migrations/0001_create_stas_tables.ts new file mode 100644 index 0000000..4ef1960 --- /dev/null +++ b/electron/stas-migrations/0001_create_stas_tables.ts @@ -0,0 +1,74 @@ +/** + * STAS extension schema — migration 0001. + * + * Three satellite tables that extend wallet-toolbox's own schema without + * modifying it. They live in the same SQLite database but are created and + * tracked by bsv-desktop's own migration set (tracking table + * `knex_migrations_stas`), so a wallet-toolbox upgrade never touches them. + * + * - stas_tokens one row per token contract (token-level metadata) + * - stas_outputs one row per STAS UTXO; outputId FKs wallet-toolbox's + * `outputs` table, which stays authoritative for the UTXO + * - stas_receive_contexts every derived BRC-42 receive key, recorded at + * derivation time (before funding); MAX(keyIndex) is the + * receive-key high-water mark used for resync + * + * `knex` is typed `any` here: tsconfig.electron has strict:false and this keeps + * the migration free of a direct knex type dependency. + */ + +export async function up(knex: any): Promise { + if (!(await knex.schema.hasTable('stas_tokens'))) { + await knex.schema.createTable('stas_tokens', (t: any) => { + t.text('tokenId').primary(); + t.text('symbol').notNullable(); + t.text('name'); + t.integer('satoshisPerToken').notNullable().defaultTo(1); + t.boolean('freezeEnabled').notNullable().defaultTo(false); + t.boolean('confiscationEnabled').notNullable().defaultTo(false); + t.text('redemptionPkh'); + t.text('issuerIdentityKey'); + t.text('flagsHex'); + t.text('createdAt').notNullable(); + }); + } + + if (!(await knex.schema.hasTable('stas_outputs'))) { + await knex.schema.createTable('stas_outputs', (t: any) => { + // outputId is the PK and a FK to wallet-toolbox's `outputs` table — + // wallet-toolbox owns the UTXO row; this is a satellite extension. + t.integer('outputId').primary().references('outputId').inTable('outputs'); + t.text('tokenId').notNullable().references('tokenId').inTable('stas_tokens'); + t.text('brc42KeyId'); + t.text('ownerFieldHash160').notNullable(); + t.bigInteger('tokenSatoshis').notNullable(); + t.boolean('frozen').notNullable().defaultTo(false); + t.boolean('confiscated').notNullable().defaultTo(false); + t.text('serviceFieldsJson'); + t.text('createdAt').notNullable(); + t.text('updatedAt').notNullable(); + t.index(['tokenId']); + t.index(['ownerFieldHash160']); + }); + } + + if (!(await knex.schema.hasTable('stas_receive_contexts'))) { + await knex.schema.createTable('stas_receive_contexts', (t: any) => { + t.increments('id').primary(); + t.text('profileIdentityKey').notNullable(); + t.integer('keyIndex').notNullable(); + t.text('keyId').notNullable(); + t.text('ownerFieldHash160').notNullable(); + t.text('derivedPublicKey').notNullable(); + t.text('createdAt').notNullable(); + t.unique(['profileIdentityKey', 'keyIndex']); + t.index(['ownerFieldHash160']); + }); + } +} + +export async function down(knex: any): Promise { + await knex.schema.dropTableIfExists('stas_outputs'); + await knex.schema.dropTableIfExists('stas_receive_contexts'); + await knex.schema.dropTableIfExists('stas_tokens'); +} diff --git a/electron/stas-migrations/0002_add_protocol_column.ts b/electron/stas-migrations/0002_add_protocol_column.ts new file mode 100644 index 0000000..205b1e1 --- /dev/null +++ b/electron/stas-migrations/0002_add_protocol_column.ts @@ -0,0 +1,154 @@ +/** + * STAS extension schema — migration 0002. + * + * Adds `protocol` to `stas_tokens` and `stas_outputs` so every satellite + * row self-describes which protocol it belongs to ('stas', 'dstas', and + * later 'bsv-21'). Until now, classic STAS and DSTAS UTXOs lived in the + * same satellite tables and the same wallet-toolbox basket; they were + * distinguished only by re-parsing their locking script. + * + * Three steps, all inside one transaction so partial failure leaves the + * database in its pre-migration state: + * 1. ADD COLUMN protocol DEFAULT 'stas' to stas_tokens + stas_outputs. + * 2. Backfill: any stas_outputs row whose joined locking script does + * NOT start with the classic-STAS prefix `76a914…88ac69` is DSTAS. + * Flip its protocol to 'dstas' and stamp the joined token row too. + * 3. Move every DSTAS output to a dedicated `dstas-tokens` basket + * (created lazily per user). Existing STAS outputs stay in + * `stas-tokens`. Future registrations route by protocol via the + * TokenProtocolAdapter layer. + * + * The prefix sniff is the same one StasDiscoveryService.tryParseClassicStasOwner + * uses (`76a914` head, `88ac69` at offset 23-25). It's intentionally + * cheap + dependency-free so the migration doesn't need to load the + * dxs SDK from the Electron main bundle. + */ + +const CLASSIC_STAS_PREFIX = '76a914'; +const CLASSIC_STAS_ENGINE_MARKER = '88ac69'; +const DSTAS_BASKET_NAME = 'dstas-tokens'; + +function looksLikeClassicStasHex(hex: string): boolean { + return ( + typeof hex === 'string' && + hex.length >= 56 && + hex.startsWith(CLASSIC_STAS_PREFIX) && + hex.substring(46, 52) === CLASSIC_STAS_ENGINE_MARKER + ); +} + +/** Convert a SQLite BLOB (Buffer) or hex string to lowercase hex. */ +function toHex(value: unknown): string { + if (value == null) return ''; + if (typeof value === 'string') return value.toLowerCase(); + if (Buffer.isBuffer(value)) return value.toString('hex'); + try { + return Buffer.from(value as any).toString('hex'); + } catch { + return ''; + } +} + +export async function up(knex: any): Promise { + await knex.transaction(async (trx: any) => { + // 1. Add the columns. Knex's alterTable handles SQLite's `ADD COLUMN`. + const hasOutputsProto = await trx.schema.hasColumn('stas_outputs', 'protocol'); + if (!hasOutputsProto) { + await trx.schema.alterTable('stas_outputs', (t: any) => { + t.text('protocol').notNullable().defaultTo('stas'); + t.index(['protocol']); + }); + } + const hasTokensProto = await trx.schema.hasColumn('stas_tokens', 'protocol'); + if (!hasTokensProto) { + await trx.schema.alterTable('stas_tokens', (t: any) => { + t.text('protocol').notNullable().defaultTo('stas'); + }); + } + + // 2. Identify DSTAS rows by sniffing each output's locking script. + // Anything in stas_outputs is one of the two protocols by + // construction — if it isn't classic, it must be DSTAS. + const rows: Array<{ + outputId: number; + tokenId: string; + lockingScript: unknown; + userId: number; + }> = await trx('stas_outputs as so') + .join('outputs as o', 'o.outputId', 'so.outputId') + .select('so.outputId', 'so.tokenId', 'o.lockingScript', 'o.userId'); + + const dstasOutputIds: number[] = []; + const dstasTokenIds = new Set(); + const dstasUsersToOutputs = new Map(); + for (const row of rows) { + const hex = toHex(row.lockingScript); + if (looksLikeClassicStasHex(hex)) continue; + dstasOutputIds.push(row.outputId); + if (row.tokenId) dstasTokenIds.add(row.tokenId); + const list = dstasUsersToOutputs.get(row.userId) ?? []; + list.push(row.outputId); + dstasUsersToOutputs.set(row.userId, list); + } + + if (dstasOutputIds.length > 0) { + // Stamp protocol = 'dstas' on every identified satellite row. + await trx('stas_outputs') + .whereIn('outputId', dstasOutputIds) + .update({ protocol: 'dstas' }); + } + if (dstasTokenIds.size > 0) { + await trx('stas_tokens') + .whereIn('tokenId', [...dstasTokenIds]) + .update({ protocol: 'dstas' }); + } + + // 3. Move DSTAS outputs into a `dstas-tokens` basket per user. The + // wallet-toolbox baskets table is keyed unique on (name, userId), + // so per-user provisioning is the safe shape even on databases + // that only ever held one user. + if (dstasUsersToOutputs.size > 0) { + const now = new Date().toISOString(); + for (const [userId, outputIds] of dstasUsersToOutputs) { + let basket: { basketId: number } | undefined = await trx('output_baskets') + .where({ name: DSTAS_BASKET_NAME, userId }) + .first('basketId'); + if (!basket) { + const [basketId] = await trx('output_baskets').insert({ + userId, + name: DSTAS_BASKET_NAME, + // Match the STAS basket's profile: 0 desired UTXOs (no + // change fragmentation), 10000 sat minimum (the toolbox + // default — STAS satoshisPerToken is 1 so this is moot). + numberOfDesiredUTXOs: 0, + minimumDesiredUTXOValue: 10000, + isDeleted: 0, + created_at: now, + updated_at: now, + }); + basket = { basketId }; + } + await trx('outputs') + .whereIn('outputId', outputIds) + .update({ basketId: basket.basketId, updated_at: now }); + } + } + }); +} + +/** + * Down migration is best-effort. SQLite 3.35+ supports `ALTER TABLE + * DROP COLUMN`; older builds would need a table rebuild. We don't + * attempt to reverse the basket move — that would require remembering + * which outputs we relocated, and the forward migration is idempotent + * enough that running `up()` again is safe. + */ +export async function down(knex: any): Promise { + await knex.schema.alterTable('stas_outputs', (t: any) => { + t.dropIndex(['protocol']); + t.dropColumn('protocol'); + }); + await knex.schema.alterTable('stas_tokens', (t: any) => { + t.dropColumn('protocol'); + }); +} diff --git a/electron/stas-migrations/0003_bsv21_receive_contexts.ts b/electron/stas-migrations/0003_bsv21_receive_contexts.ts new file mode 100644 index 0000000..c6f4058 --- /dev/null +++ b/electron/stas-migrations/0003_bsv21_receive_contexts.ts @@ -0,0 +1,32 @@ +/** + * STAS extension schema — migration 0003. + * + * Creates `bsv21_receive_contexts`, a per-protocol receive-key ledger that + * mirrors `stas_receive_contexts`. Each row records a BRC-42-derived owner + * key (under the BSV-21 protocolID namespace) so a resync can regenerate + * every receive address from just the persisted high-water mark. + * + * No `bsv21_outputs` or `bsv21_tokens` table — BSV-21 token metadata + * (id, amt, dec, sym, icon) lives on wallet-toolbox basket tags by the + * 1sat-wallet-toolbox convention, so the satellite stays receive-only. + */ + +export async function up(knex: any): Promise { + if (!(await knex.schema.hasTable('bsv21_receive_contexts'))) { + await knex.schema.createTable('bsv21_receive_contexts', (t: any) => { + t.increments('id').primary(); + t.text('profileIdentityKey').notNullable(); + t.integer('keyIndex').notNullable(); + t.text('keyId').notNullable(); + t.text('ownerFieldHash160').notNullable(); + t.text('derivedPublicKey').notNullable(); + t.text('createdAt').notNullable(); + t.unique(['profileIdentityKey', 'keyIndex']); + t.index(['ownerFieldHash160']); + }); + } +} + +export async function down(knex: any): Promise { + await knex.schema.dropTableIfExists('bsv21_receive_contexts'); +} diff --git a/electron/stas-migrations/0004_token_verifications.ts b/electron/stas-migrations/0004_token_verifications.ts new file mode 100644 index 0000000..c44e1a1 --- /dev/null +++ b/electron/stas-migrations/0004_token_verifications.ts @@ -0,0 +1,41 @@ +/** + * STAS extension schema — migration 0004. + * + * Creates `token_verifications`, a per-outpoint Back-to-Genesis provenance + * cache. One row per token UTXO the wallet has verified, keyed on the outpoint + * `(txid, vout)`. It is deliberately standard-agnostic — STAS, DSTAS and BSV-21 + * all share it — because BSV-21 has no satellite holdings table, and an + * outpoint's provenance is the same question regardless of token standard. + * + * Durability is the whole point: a verdict for a fixed outpoint is immutable + * (a reorg aside), so persisting it here means a re-opened wallet — or a fresh + * install restoring the same DB — shows Verified / Counterfeit badges instantly + * without re-walking the chain. The renderer's in-memory cache is only a + * same-session accelerator on top of this. + * + * Only SETTLED verdicts (`authentic` / `not-authentic`) are stored; + * `undetermined` means "couldn't decide yet" and must be retried, never frozen. + * `genesis` is the resolved `_` — the sole spoof-proof token + * identity for classic STAS (whose tokenId is merely the issuer PKH). + */ + +export async function up(knex: any): Promise { + if (!(await knex.schema.hasTable('token_verifications'))) { + await knex.schema.createTable('token_verifications', (t: any) => { + t.text('txid').notNullable(); + t.integer('vout').notNullable(); + t.text('protocol').notNullable(); // 'stas' | 'dstas' | 'bsv-21' + t.text('result').notNullable(); // 'authentic' | 'not-authentic' + t.text('genesis'); // '_' of the resolved genesis; null if none + t.integer('genesisDepth'); + t.text('reason'); // set when not-authentic + t.text('verifiedAt').notNullable(); + t.primary(['txid', 'vout']); + t.index(['genesis']); + }); + } +} + +export async function down(knex: any): Promise { + await knex.schema.dropTableIfExists('token_verifications'); +} diff --git a/electron/stas-migrations/index.ts b/electron/stas-migrations/index.ts new file mode 100644 index 0000000..a9cf9fd --- /dev/null +++ b/electron/stas-migrations/index.ts @@ -0,0 +1,46 @@ +/** + * STAS migration source. + * + * A Knex `MigrationSource` whose migrations are plain ES modules in this + * directory (compiled by tsconfig.electron to dist-electron/stas-migrations/). + * Because the migrations are imported statically — not discovered from disk by + * Knex's file scanner — no `.cjs` files and no build-time copy step are needed. + * + * Wired into electron/storage.ts as a SECOND `db.migrate.latest()` pass that + * runs after wallet-toolbox's own migrations, with a separate tracking table + * (`knex_migrations_stas`) so the two ledgers never collide. + */ + +import * as m0001 from './0001_create_stas_tables.js'; +import * as m0002 from './0002_add_protocol_column.js'; +import * as m0003 from './0003_bsv21_receive_contexts.js'; +import * as m0004 from './0004_token_verifications.js'; + +type StasMigration = { + name: string; + up: (knex: any) => Promise; + down: (knex: any) => Promise; +}; + +const migrations: StasMigration[] = [ + { name: '0001_create_stas_tables', up: m0001.up, down: m0001.down }, + { name: '0002_add_protocol_column', up: m0002.up, down: m0002.down }, + { name: '0003_bsv21_receive_contexts', up: m0003.up, down: m0003.down }, + { name: '0004_token_verifications', up: m0004.up, down: m0004.down }, +]; + +/** Knex MigrationSource over the statically-imported STAS migrations. */ +export const stasMigrationSource = { + async getMigrations(): Promise { + return migrations; + }, + getMigrationName(migration: StasMigration): string { + return migration.name; + }, + async getMigration(migration: StasMigration): Promise<{ + up: (knex: any) => Promise; + down: (knex: any) => Promise; + }> { + return { up: migration.up, down: migration.down }; + }, +}; diff --git a/electron/stas-queries.ts b/electron/stas-queries.ts new file mode 100644 index 0000000..bcb56f3 --- /dev/null +++ b/electron/stas-queries.ts @@ -0,0 +1,673 @@ +/** + * STAS query layer. + * + * A thin, parameterized accessor over the STAS extension tables created by + * electron/stas-migrations. It is reached from the renderer through the + * dedicated `stas:query` IPC channel (see electron/main.ts + preload.ts), + * kept separate from wallet-toolbox's `storage:call-method` proxy so STAS + * queries never share the StorageKnex method namespace. + * + * `knex` is typed `any` (tsconfig.electron has strict:false) to avoid a direct + * knex type dependency. + */ + +/** Token-protocol discriminator. Mirrors TokenProtocolId in the renderer. */ +export type TokenProtocolId = 'stas' | 'dstas' | 'bsv-21'; + +export interface StasTokenRow { + tokenId: string; + symbol: string; + name?: string; + satoshisPerToken: number; + freezeEnabled: boolean; + confiscationEnabled: boolean; + redemptionPkh?: string; + issuerIdentityKey?: string; + flagsHex?: string; + createdAt: string; + /** Optional on insert — the column has a DEFAULT 'stas' (migration 0002). */ + protocol?: TokenProtocolId; +} + +export interface StasOutputRow { + outputId: number; + tokenId: string; + brc42KeyId?: string; + ownerFieldHash160: string; + tokenSatoshis: number; + frozen?: boolean; + confiscated?: boolean; + serviceFieldsJson?: string; + createdAt: string; + updatedAt: string; + /** Optional on insert — the column has a DEFAULT 'stas' (migration 0002). */ + protocol?: TokenProtocolId; +} + +/** A persisted Back-to-Genesis verdict for one token outpoint (migration 0004). */ +export interface TokenVerificationRow { + txid: string; + vout: number; + protocol: TokenProtocolId; + /** Only settled verdicts are stored. */ + result: 'authentic' | 'not-authentic'; + /** Resolved genesis `_`; null/undefined when none was resolved. */ + genesis?: string | null; + genesisDepth?: number | null; + /** Present when `not-authentic`. */ + reason?: string | null; + /** ISO timestamp of when the verdict was recorded. */ + verifiedAt: string; +} + +export interface StasReceiveContextRow { + profileIdentityKey: string; + keyIndex: number; + keyId: string; + ownerFieldHash160: string; + derivedPublicKey: string; + createdAt: string; +} + +/** + * BSV-21 receive-key row. Schema identical to the STAS variant, but lives + * in its own table (`bsv21_receive_contexts`, migration 0003) so the + * receive-key namespace and high-water mark stay separate per protocol. + */ +export interface Bsv21ReceiveContextRow { + profileIdentityKey: string; + keyIndex: number; + keyId: string; + ownerFieldHash160: string; + derivedPublicKey: string; + createdAt: string; +} + +/** Query/command surface over the STAS extension tables. */ +export class StasQueries { + constructor(private readonly knex: any) {} + + // --- tokens ------------------------------------------------------------- + + async getStasToken(tokenId: string): Promise { + return this.knex('stas_tokens').where({ tokenId }).first(); + } + + async listStasTokens(): Promise { + return this.knex('stas_tokens').select('*'); + } + + async upsertStasToken(row: StasTokenRow): Promise { + const existing = await this.knex('stas_tokens') + .where({ tokenId: row.tokenId }) + .first(); + if (existing) { + await this.knex('stas_tokens').where({ tokenId: row.tokenId }).update(row); + } else { + await this.knex('stas_tokens').insert(row); + } + } + + // --- outputs ------------------------------------------------------------ + + /** + * STAS outputs the wallet STILL OWNS — joins our satellite to the wallet- + * toolbox `outputs` row and filters by `spentBy IS NULL`. + * + * wallet-toolbox's spend lifecycle: + * - own + available → spendable=1, spentBy=NULL + * - in-flight spend → spendable=0, spentBy= + * - finalised spend → spendable=0, spentBy= + * - unspent revert → spendable=1, spentBy=NULL (set by wallet-toolbox + * when the spending tx fails to confirm) + * + * Filter on `spentBy IS NULL` rather than `spendable=1` because we + * deliberately set `spendable=1` on STAS at register-time (the toolbox + * conservatively defaults it to 0 for non-template scripts). `spentBy` + * is the unambiguous "this is gone" signal. + * + * Pass `includeSpent: true` to surface fully sent STAS too (for history / + * activity views — not exposed via the Apps API by default). + */ + async listStasOutputs(filter: { + tokenId?: string; + includeSpent?: boolean; + } = {}): Promise { + // `outputs.spentBy` is an integer FK → `transactions.transactionId`, not + // a txid string. Join `transactions` so we return the actual spending + // txid the UI can render / link to WhatsOnChain. NULL when unspent. + let q = this.knex('stas_outputs') + .join('outputs', 'outputs.outputId', 'stas_outputs.outputId') + .leftJoin('transactions as spent_tx', 'spent_tx.transactionId', 'outputs.spentBy') + .select( + 'stas_outputs.*', + 'outputs.satoshis as outputSatoshis', + 'outputs.spendable', + 'spent_tx.txid as spentBy', + 'outputs.txid', + 'outputs.vout', + 'outputs.lockingScript' // bytes — converted to hex below for the transfer UI + ); + if (filter.tokenId) q = q.where('stas_outputs.tokenId', filter.tokenId); + if (!filter.includeSpent) q = q.whereNull('outputs.spentBy'); + const rows = await q; + // outputs.lockingScript is stored as Buffer in SQLite (BLOB). Convert to + // hex so renderer-side consumers (Transfer UI) get a usable string. + return rows.map((r: any) => ({ + ...r, + lockingScript: + r.lockingScript == null + ? undefined + : Buffer.isBuffer(r.lockingScript) + ? r.lockingScript.toString('hex') + : typeof r.lockingScript === 'string' + ? r.lockingScript + : Buffer.from(r.lockingScript).toString('hex'), + })); + } + + async insertStasOutput(row: StasOutputRow): Promise { + await this.knex('stas_outputs').insert(row); + } + + /** + * Persist a settled Back-to-Genesis verdict for one outpoint (migration + * 0004). Standard-agnostic — STAS/DSTAS/BSV-21 all use it. Callers must pass + * only SETTLED verdicts (`authentic` / `not-authentic`); an `undetermined` + * result means "couldn't decide yet" and must be retried, never stored. + * Idempotent upsert keyed on the outpoint (re-verifying overwrites). + */ + async upsertTokenVerification(row: TokenVerificationRow): Promise { + const existing = await this.knex('token_verifications') + .where({ txid: row.txid, vout: row.vout }) + .first(); + if (existing) { + await this.knex('token_verifications') + .where({ txid: row.txid, vout: row.vout }) + .update(row); + } else { + await this.knex('token_verifications').insert(row); + } + } + + /** Every stored verdict — the renderer seeds its badge state from this. */ + async listTokenVerifications(): Promise { + return this.knex('token_verifications').select('*'); + } + + /** + * Mark a wallet-toolbox `outputs` row as spendable / not-spendable. + * + * STAS outputs land in the basket with `spendable=false` because the + * toolbox doesn't recognise the custom locking script as one it knows how + * to unlock. Our transfer flow handles the unlocking externally via the + * BRC-42 sign path, so we need to flip the flag back to `true` so + * createAction will let us reference the outpoint as an input. + */ + async setOutputSpendable(outputId: number, spendable: boolean): Promise<{ updated: number }> { + const updated = await this.knex('outputs') + .where({ outputId }) + .update({ spendable: spendable ? 1 : 0 }); + return { updated }; + } + + /** + * Backfill: flip `outputs.spendable=1` on the given basket's UTXOs that + * the wallet still owns. Critical guard: only updates rows where + * `spentBy IS NULL` so we don't resurrect already-spent UTXOs. + * + * Generalised in PR-token-adapters so each protocol (STAS, DSTAS, + * later BSV-21) can backfill its own basket. `backfillStasSpendable` + * stays as a thin wrapper for the STAS basket. + */ + async backfillSpendableForBasket(basketName: string): Promise<{ updated: number }> { + const basket = await this.knex('output_baskets') + .where({ name: basketName, isDeleted: 0 }) + .first('basketId'); + if (!basket) return { updated: 0 }; + const updated = await this.knex('outputs') + .where({ basketId: basket.basketId }) + .andWhere({ spendable: 0 }) + .whereNull('spentBy') + .update({ spendable: 1 }); + return { updated }; + } + + /** + * Back-compat shim — classic-STAS basket backfill. New callers should + * use `backfillSpendableForBasket` with the protocol-specific basket + * name from `src/lib/constants/baskets`. + */ + async backfillStasSpendable(): Promise<{ updated: number }> { + return this.backfillSpendableForBasket('stas-tokens'); + } + + /** + * Override the `default` (change) basket's `numberOfDesiredUTXOs`. + * + * Wallet-toolbox's `generateChange` aims for this many UTXOs in the change + * basket; below the target it adds fragmentation outputs each createAction. + * The STAS engine assumes exactly 2 outputs (new STAS + one change), so + * we lower the target to 0 around a STAS transfer to suppress + * fragmentation, then restore it afterward. + * + * Returns previous + new values so the caller can restore. + */ + async setDefaultBasketUTXOTarget(target: number): Promise<{ + previous: number | null; + updated: number; + }> { + const before = await this.knex('output_baskets') + .where({ name: 'default' }) + .first('numberOfDesiredUTXOs'); + const updated = await this.knex('output_baskets') + .where({ name: 'default' }) + .update({ numberOfDesiredUTXOs: target }); + return { + previous: before?.numberOfDesiredUTXOs ?? null, + updated, + }; + } + + /** + * Enumerate every basket the wallet knows about, with output counts. + * + * BRC-100's `listOutputs` requires a basket name upfront — there's no + * "give me every basket" method on the wallet surface. We query the + * toolbox's `output_baskets` table directly and join `outputs` for + * counts/totals. + */ + async listAllBaskets(): Promise< + Array<{ + basketId: number; + name: string; + numberOfDesiredUTXOs: number | null; + minimumDesiredUTXOValue: number | null; + outputCount: number; + spendableCount: number; + totalSatoshis: number; + }> + > { + const baskets = await this.knex('output_baskets') + .where({ isDeleted: 0 }) + .select( + 'basketId', + 'name', + 'numberOfDesiredUTXOs', + 'minimumDesiredUTXOValue' + ); + if (baskets.length === 0) return []; + + const counts = await this.knex('outputs') + .whereIn( + 'basketId', + baskets.map((b: any) => b.basketId) + ) + .groupBy('basketId') + .select( + 'basketId', + this.knex.raw('COUNT(*) as outputCount'), + this.knex.raw('SUM(CASE WHEN spendable = 1 THEN 1 ELSE 0 END) as spendableCount'), + this.knex.raw('SUM(satoshis) as totalSatoshis') + ); + + const byId = new Map(); + for (const c of counts) byId.set(c.basketId, c); + + return baskets.map((b: any) => ({ + basketId: b.basketId, + name: b.name, + numberOfDesiredUTXOs: b.numberOfDesiredUTXOs ?? null, + minimumDesiredUTXOValue: b.minimumDesiredUTXOValue ?? null, + outputCount: byId.get(b.basketId)?.outputCount ?? 0, + spendableCount: byId.get(b.basketId)?.spendableCount ?? 0, + totalSatoshis: byId.get(b.basketId)?.totalSatoshis ?? 0, + })); + } + + /** + * Outputs inside a specific basket. Returns satellite-friendly fields: + * outpoint, satoshis, lockingScript (hex), spendable, customInstructions, + * tags (semicolon-joined if present on the row). + */ + async listBasketOutputs(basketName: string): Promise { + const basket = await this.knex('output_baskets') + .where({ name: basketName, isDeleted: 0 }) + .first('basketId'); + if (!basket) return []; + // wallet-toolbox stores `txid` on `transactions`, not `outputs` — outputs + // carries `transactionId` as a foreign key. Join to surface the real txid. + const rows = await this.knex('outputs as o') + .join('transactions as t', 't.transactionId', 'o.transactionId') + .where('o.basketId', basket.basketId) + .select( + 'o.outputId as outputId', + 't.txid as txid', + 'o.vout as vout', + 'o.satoshis as satoshis', + 'o.spendable as spendable', + 'o.lockingScript as lockingScript', + 'o.customInstructions as customInstructions', + 'o.type as type', + 'o.created_at as createdAt' + ) + .orderBy('o.created_at', 'desc') + .limit(500); + + return rows.map((r: any) => ({ + outputId: r.outputId, + outpoint: r.txid != null ? `${r.txid}.${r.vout}` : `?.${r.vout}`, + txid: r.txid ?? null, + vout: r.vout, + satoshis: r.satoshis, + spendable: !!r.spendable, + type: r.type, + customInstructions: r.customInstructions ?? null, + lockingScript: + r.lockingScript == null + ? null + : Buffer.isBuffer(r.lockingScript) + ? r.lockingScript.toString('hex') + : typeof r.lockingScript === 'string' + ? r.lockingScript + : Buffer.from(r.lockingScript).toString('hex'), + createdAt: r.createdAt, + })); + } + + /** Idempotency probe: has an outpoint already been registered as STAS? */ + async findStasOutputByOutpoint( + txid: string, + vout: number + ): Promise { + return this.knex('stas_outputs') + .join('outputs', 'outputs.outputId', 'stas_outputs.outputId') + .where({ 'outputs.txid': txid, 'outputs.vout': vout }) + .first('stas_outputs.*'); + } + + /** + * Look up wallet-toolbox's `outputs.outputId` for an outpoint — used after + * internalizeAction to link a satellite `stas_outputs` row to the + * authoritative UTXO row. + */ + async findOutputIdByOutpoint( + txid: string, + vout: number + ): Promise { + const row = await this.knex('outputs') + .where({ txid, vout }) + .first('outputId'); + return row ? (row.outputId as number) : undefined; + } + + async updateStasOutputState( + outputId: number, + state: { frozen?: boolean; confiscated?: boolean } + ): Promise { + await this.knex('stas_outputs') + .where({ outputId }) + .update({ ...state, updatedAt: new Date().toISOString() }); + } + + /** + * Backfill helper — assign a freshly-derived tokenId (+ symbol/flags) to + * an existing stas_outputs row, and upsert the matching stas_tokens row. + * + * Used by the dev panel's "Backfill tokenIds" button, which re-derives the + * CreateContract txid for STAS that were registered before the + * findCreateContractTxid helper existed (so they have empty or stale + * tokenId values). + * + * Order matters: stas_outputs.tokenId has a FOREIGN KEY to + * stas_tokens.tokenId. We must insert the parent row FIRST and only then + * update the satellite's FK column. + */ + async updateStasOutputAndToken(args: { + outputId: number; + tokenId: string; + symbol?: string; + flagsHex?: string; + }): Promise { + const now = new Date().toISOString(); + // 1) Ensure the stas_tokens row exists (insert if new, update symbol if + // it changed). Either way, the FK target is ready before step 2. + const existing = await this.knex('stas_tokens') + .where({ tokenId: args.tokenId }) + .first(); + if (!existing) { + await this.knex('stas_tokens').insert({ + tokenId: args.tokenId, + symbol: args.symbol ?? 'STAS', + name: null, + satoshisPerToken: 1, + freezeEnabled: false, + confiscationEnabled: false, + redemptionPkh: null, + issuerIdentityKey: null, + flagsHex: args.flagsHex ?? null, + createdAt: now, + }); + } else if (args.symbol && existing.symbol !== args.symbol) { + await this.knex('stas_tokens') + .where({ tokenId: args.tokenId }) + .update({ symbol: args.symbol }); + } + // 2) Now safely update the satellite row. + await this.knex('stas_outputs') + .where({ outputId: args.outputId }) + .update({ tokenId: args.tokenId, updatedAt: now }); + } + + /** + * Retroactively assign a basket + customInstructions + tags to an + * existing output. Used for BSV-21 orphan recovery — pre-fix sends + * produced change outputs in the `outputs` table with `basketId = NULL` + * (the toolbox doesn't recognise the token template, so the + * createAction output never claimed a basket). The recovery flow + * re-classifies them after the fact. + * + * Idempotent: if the output already has a basket, returns without + * modifying it. The output's `userId` is read from the existing row, + * so we never have to guess which user the tags belong to. + * + * Returns the outputId on success so the caller can log it. Reason + * field surfaces lookup misses without throwing. + */ + async recoverOrphanOutput(args: { + txid: string; + vout: number; + customInstructions: string; + tags: string[]; + basketName: string; + }): Promise<{ + ok: boolean; + outputId?: number; + alreadyHadBasket?: boolean; + reason?: string; + }> { + const row = await this.knex('outputs') + .where({ txid: args.txid, vout: args.vout }) + .first('outputId', 'userId', 'basketId'); + if (!row) { + return { ok: false, reason: `no outputs row matches ${args.txid}:${args.vout}` }; + } + const { outputId, userId, basketId } = row; + if (basketId) { + return { ok: true, outputId, alreadyHadBasket: true }; + } + + const basket = await this.knex('output_baskets') + .where({ name: args.basketName, isDeleted: 0 }) + .first('basketId'); + if (!basket) { + // Defensive — the basket should exist already, since the wallet + // creates it on first BSV-21 internalize. If it doesn't, surface + // the gap rather than silently creating an orphan basket row. + return { ok: false, outputId, reason: `basket "${args.basketName}" not found — has it ever been used?` }; + } + + await this.knex('outputs') + .where({ outputId }) + .update({ + basketId: basket.basketId, + customInstructions: args.customInstructions, + spendable: true, + }); + + const now = new Date().toISOString(); + for (const tag of args.tags) { + let tagRow = await this.knex('output_tags') + .where({ tag, userId }) + .first('outputTagId'); + if (!tagRow) { + const [outputTagId] = await this.knex('output_tags').insert({ + tag, + userId, + isDeleted: false, + created_at: now, + updated_at: now, + }); + tagRow = { outputTagId }; + } + // output_tags_map UNIQUE on (outputTagId, outputId) — use raw INSERT + // OR IGNORE so repeated calls are safe. + const existing = await this.knex('output_tags_map') + .where({ outputTagId: tagRow.outputTagId, outputId }) + .first(); + if (!existing) { + await this.knex('output_tags_map').insert({ + outputTagId: tagRow.outputTagId, + outputId, + isDeleted: false, + created_at: now, + updated_at: now, + }); + } + } + + return { ok: true, outputId }; + } + + // --- receive contexts --------------------------------------------------- + + async listReceiveContexts( + profileIdentityKey: string + ): Promise { + return this.knex('stas_receive_contexts') + .where({ profileIdentityKey }) + .orderBy('keyIndex', 'asc'); + } + + /** Highest issued receive-key index for a profile (0 if none) — the resync high-water mark. */ + async getReceiveHighWaterMark(profileIdentityKey: string): Promise { + const row = await this.knex('stas_receive_contexts') + .where({ profileIdentityKey }) + .max('keyIndex as m') + .first(); + return (row && row.m) || 0; + } + + async insertReceiveContext(row: StasReceiveContextRow): Promise { + await this.knex('stas_receive_contexts').insert(row); + } + + // --- BSV-21 receive contexts ------------------------------------------- + // + // Mirror of the STAS receive-context API surface, scoped to its own table + // so each protocol's key derivation stays independent. + + async listBsv21ReceiveContexts( + profileIdentityKey: string + ): Promise { + return this.knex('bsv21_receive_contexts') + .where({ profileIdentityKey }) + .orderBy('keyIndex', 'asc'); + } + + async getBsv21ReceiveHighWaterMark(profileIdentityKey: string): Promise { + const row = await this.knex('bsv21_receive_contexts') + .where({ profileIdentityKey }) + .max('keyIndex as m') + .first(); + return (row && row.m) || 0; + } + + async insertBsv21ReceiveContext(row: Bsv21ReceiveContextRow): Promise { + await this.knex('bsv21_receive_contexts').insert(row); + } + + // --- resync snapshot ---------------------------------------------------- + + /** + * Export every STAS-relevant row in a stable, fingerprint-friendly shape. + * Used by the resync verification flow: take a snapshot pre-wipe, restore + * the wallet from mnemonic, take another snapshot, diff the two. + * + * Includes a canonical sort so two exports of equivalent states produce + * byte-identical JSON (handy for shell `diff`). + */ + async exportStasState(profileIdentityKey: string): Promise<{ + tokens: any[]; + outputs: any[]; + receiveContexts: any[]; + profileIdentityKey: string; + exportedAt: string; + }> { + const tokens = await this.knex('stas_tokens') + .select( + 'tokenId', + 'symbol', + 'name', + 'satoshisPerToken', + 'freezeEnabled', + 'confiscationEnabled', + 'redemptionPkh', + 'issuerIdentityKey', + 'flagsHex' + ) + .orderBy('tokenId', 'asc'); + + const outputsRaw = await this.knex('stas_outputs as so') + .join('outputs as o', 'o.outputId', 'so.outputId') + .join('transactions as t', 't.transactionId', 'o.transactionId') + .select( + 't.txid as txid', + 'o.vout as vout', + 'so.tokenId as tokenId', + 'so.brc42KeyId as brc42KeyId', + 'so.ownerFieldHash160 as ownerFieldHash160', + 'so.tokenSatoshis as tokenSatoshis', + 'so.frozen as frozen', + 'so.confiscated as confiscated', + 'o.spendable as spendable' + ) + .orderBy('t.txid', 'asc') + .orderBy('o.vout', 'asc'); + + const outputs = outputsRaw.map((r: any) => ({ + txid: r.txid, + vout: r.vout, + tokenId: r.tokenId, + brc42KeyId: r.brc42KeyId ?? null, + ownerFieldHash160: r.ownerFieldHash160, + tokenSatoshis: r.tokenSatoshis, + frozen: !!r.frozen, + confiscated: !!r.confiscated, + spendable: !!r.spendable, + })); + + const receiveContexts = await this.knex('stas_receive_contexts') + .where({ profileIdentityKey }) + .select('keyIndex', 'keyId', 'ownerFieldHash160', 'derivedPublicKey') + .orderBy('keyIndex', 'asc'); + + return { + tokens, + outputs, + receiveContexts, + profileIdentityKey, + exportedAt: new Date().toISOString(), + }; + } +} diff --git a/electron/storage.ts b/electron/storage.ts index dece848..ad4c253 100644 --- a/electron/storage.ts +++ b/electron/storage.ts @@ -19,6 +19,8 @@ import { fork, ChildProcess } from 'child_process'; import { fileURLToPath } from 'url'; import { StorageKnex, KnexMigrations, Services, Monitor, WalletStorageManager, ChaintracksServiceClient } from '@bsv/wallet-toolbox'; import { patchListCertificates } from './optimized-queries.js'; +import { stasMigrationSource } from './stas-migrations/index.js'; +import { StasQueries } from './stas-queries.js'; const require = createRequire(import.meta.url); const __filename = fileURLToPath(import.meta.url); @@ -153,11 +155,30 @@ class StorageManager { }); console.log(`[Storage] Migrations complete`); - // Create StorageKnex instance + // Run STAS extension migrations (bsv-desktop-owned). A separate tracking + // table keeps them isolated from wallet-toolbox's own migration ledger. + console.log(`[Storage] Running STAS extension migrations for ${key}...`); + await db.migrate.latest({ + migrationSource: stasMigrationSource, + tableName: 'knex_migrations_stas' + }); + console.log(`[Storage] STAS migrations complete`); + + // Create StorageKnex instance. + // + // feeModel: TAAL and GorillaPool both advertise a miningFee of 100 sat/1000 + // bytes (`GET /v1/policy`), i.e. 0.1 sat/byte. Paying exactly 100 sat/kb put + // us *on* that floor with zero headroom, which is fine for a standalone tx + // but not for tokens: miners price the whole unconfirmed ancestor package, + // and a token transfer's package includes engine-signed txs that pay less. + // One underpriced ancestor then drags the package average below policy and + // the entire chain stalls — observed on a 21-tx mint package that settled at + // 0.095 sat/b and needed a CPFP bump to confirm. 250 sat/kb buys margin for + // pennies: a 500-byte transfer costs 125 sat instead of 50. const storage = new StorageKnex({ knex: db, chain: chain, - feeModel: { model: 'sat/kb', value: 100 }, + feeModel: { model: 'sat/kb', value: 250 }, commissionSatoshis: 0 }); @@ -428,6 +449,32 @@ class StorageManager { } } + /** + * Run a STAS extension query against the STAS tables for an identity/chain. + * Dispatched to `StasQueries` — a bounded surface, separate from the generic + * StorageKnex method proxy used by callStorageMethod. + */ + async callStasQuery( + identityKey: string, + chain: 'main' | 'test', + method: string, + args: any[] + ): Promise { + // Ensure storage (and therefore the STAS migrations) have run. + await this.getOrCreateStorage(identityKey, chain); + const key = `${identityKey}-${chain}`; + const db = this.databases.get(key); + if (!db) { + throw new Error(`No database connection for ${key}`); + } + const queries = new StasQueries(db); + const fn = (queries as any)[method]; + if (typeof fn !== 'function') { + throw new Error(`Unknown STAS query: ${method}`); + } + return fn.apply(queries, args || []); + } + /** * Cleanup all storage instances */ diff --git a/package-lock.json b/package-lock.json index 35bd60b..6e63af9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,34 +1,36 @@ { "name": "bsv-desktop-electron", - "version": "2.6.2", + "version": "2.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bsv-desktop-electron", - "version": "2.6.2", + "version": "2.3.1", + "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@bsv/amountinator": "^2.1.0", - "@bsv/btms": "^1.1.0", - "@bsv/btms-permission-module": "^1.1.0", + "@bsv/amountinator": "^2.0.1", + "@bsv/btms": "^1.0.1", + "@bsv/btms-permission-module": "^1.0.1", "@bsv/btms-permission-module-ui": "^1.0.0", "@bsv/identity-react": "^1.1.14", - "@bsv/message-box-client": "^2.2.0", - "@bsv/sdk": "^2.1.6", + "@bsv/message-box-client": "^2.2.1", + "@bsv/sdk": "^2.0.13", "@bsv/uhrp-react": "^1.0.6", - "@bsv/wallet-toolbox": "^2.3.2", - "@bsv/wallet-toolbox-client": "^2.3.2", + "@bsv/wallet-toolbox": "^2.1.19", + "@bsv/wallet-toolbox-client": "^2.1.19", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@mui/icons-material": "^6.4.8", "@mui/material": "^6.4.8", "@mui/styles": "^6.4.8", "better-sqlite3": "^12.8.0", + "bsv": "^1.5.6", "cors": "^2.8.6", "date-fns": "^4.1.0", - "dompurify": "^3.4.11", "dotenv": "^17.2.4", + "dxs-bsv-token-sdk": "file:./vendor/dxs-bsv-token-sdk", "electron-log": "^5.4.3", "electron-updater": "^6.7.3", "express": "^4.21.2", @@ -47,6 +49,7 @@ "react-i18next": "^17.0.3", "react-router-dom": "^5.2.0", "react-toastify": "^11.0.5", + "stas-js": "^3.0.3", "use-async-effect": "^2.2.7" }, "devDependencies": { @@ -65,16 +68,50 @@ "typescript": "~5.6.2", "vite": "^6.3.6", "vite-plugin-electron": "^0.29.0", + "vite-plugin-node-polyfills": "^0.28.0", "vitest": "^3.0.0" } }, + "../dxs-bsv-token-sdk": { + "version": "1.0.4", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@noble/curves": "^2.0.1", + "@noble/hashes": "^2.0.1", + "@noble/secp256k1": "^3.0.0", + "@scure/base": "^2.0.0", + "@scure/bip32": "^2.0.1", + "@scure/bip39": "^2.0.1" + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@rollup/plugin-commonjs": "^29.0.0", + "@rollup/plugin-node-resolve": "^16.0.3", + "@rollup/plugin-typescript": "^12.3.0", + "@types/jest": "^30.0.0", + "eslint": "^10.1.0", + "eslint-config-prettier": "^10.1.8", + "globals": "^17.4.0", + "husky": "^9.1.7", + "jest": "^30.2.0", + "lint-staged": "^16.2.7", + "prettier": "^3.8.1", + "rollup": "^4.57.1", + "ts-jest": "^29.4.6", + "ts-node-dev": "^2.0.0", + "tslib": "^2.8.1", + "typescript": "^5.9.3", + "typescript-eslint": "^8.57.1" + } + }, "node_modules/@babel/code-frame": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", - "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.29.7", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -83,31 +120,29 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", - "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", - "dev": true, + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", - "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", - "@babel/helper-compilation-targets": "^7.29.7", - "@babel/helper-module-transforms": "^7.29.7", - "@babel/helpers": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/template": "^7.29.7", - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -127,17 +162,16 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, "license": "MIT" }, "node_modules/@babel/generator": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", - "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.7", - "@babel/types": "^7.29.7", + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -147,14 +181,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", - "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", - "dev": true, + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.29.7", - "@babel/helper-validator-option": "^7.29.7", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -164,37 +197,36 @@ } }, "node_modules/@babel/helper-globals": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", - "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", - "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", - "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", - "dev": true, + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.29.7", - "@babel/helper-validator-identifier": "^7.29.7", - "@babel/traverse": "^7.29.7" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -204,64 +236,61 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", - "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", - "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", - "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", - "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", - "dev": true, + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "license": "MIT", "dependencies": { - "@babel/template": "^7.29.7", - "@babel/types": "^7.29.7" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", - "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.29.7" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -270,6 +299,245 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-react-jsx-self": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", @@ -312,31 +580,31 @@ } }, "node_modules/@babel/template": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", - "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/types": "^7.29.7" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", - "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", - "@babel/helper-globals": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/template": "^7.29.7", - "@babel/types": "^7.29.7", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", "debug": "^4.3.1" }, "engines": { @@ -344,50 +612,43 @@ } }, "node_modules/@babel/types": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", - "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.29.7", - "@babel/helper-validator-identifier": "^7.29.7" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "license": "MIT", + "peer": true + }, "node_modules/@bsv/amountinator": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@bsv/amountinator/-/amountinator-2.1.0.tgz", - "integrity": "sha512-tG05O59BfTBmPx83DOVrQVVi4K7aLfDij8h4Fy02f9XQg8noEbM3CoXopQ0RxCjRYNG+Rffm3ewOcDNaLnUHrQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@bsv/amountinator/-/amountinator-2.0.1.tgz", + "integrity": "sha512-7dBmIHvcm2g18V8bCW0osgKGWRNGFoKUbCNdlk08euTmmVmDaZdJpdjTMMY5brvO2e5CzHvXPSij7/oEy1R7UQ==", "license": "Open BSV License", "dependencies": { - "@bsv/wallet-toolbox-client": "^2.1.30" - }, - "peerDependencies": { - "@bsv/sdk": "^2" - }, - "peerDependenciesMeta": { - "@bsv/sdk": { - "optional": false - } + "@bsv/sdk": "^2.0.4", + "@bsv/wallet-toolbox-client": "^2.0.21" } }, "node_modules/@bsv/auth-express-middleware": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@bsv/auth-express-middleware/-/auth-express-middleware-2.1.0.tgz", - "integrity": "sha512-pdVCr8GBx+xs39KHcoiyIcyuBXTpIB+VKZNykIaVfZzhUyTIMEv1zQ+y8WhonCsvc9B9jcFAeYVI7kZ8IF4Gxw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@bsv/auth-express-middleware/-/auth-express-middleware-2.0.4.tgz", + "integrity": "sha512-E1OL/OsyElJTzwYNxAG2ThZLEH1Q6LCJSVx8GSazxCSmVPuQUdK0dAxW2Uscer2otq7BzEdYayRR0I7+E/8UAA==", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { - "express": "^5.2.1" - }, - "peerDependencies": { - "@bsv/sdk": "^2" - }, - "peerDependenciesMeta": { - "@bsv/sdk": { - "optional": false - } + "@bsv/sdk": "^2.0.4", + "express": "^5.1.0" } }, "node_modules/@bsv/auth-express-middleware/node_modules/accepts": { @@ -404,34 +665,21 @@ } }, "node_modules/@bsv/auth-express-middleware/node_modules/body-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", - "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", - "content-type": "^2.0.0", + "content-type": "^1.0.5", "debug": "^4.4.3", - "http-errors": "^2.0.1", - "iconv-lite": "^0.7.2", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", - "qs": "^6.15.2", - "raw-body": "^3.0.2", - "type-is": "^2.1.0" - }, - "engines": { - "node": ">=18" + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@bsv/auth-express-middleware/node_modules/body-parser/node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", "engines": { "node": ">=18" }, @@ -441,9 +689,9 @@ } }, "node_modules/@bsv/auth-express-middleware/node_modules/content-disposition": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", - "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", "engines": { "node": ">=18" @@ -696,34 +944,17 @@ } }, "node_modules/@bsv/auth-express-middleware/node_modules/type-is": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", - "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", "dependencies": { - "content-type": "^2.0.0", + "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" }, "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@bsv/auth-express-middleware/node_modules/type-is/node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 0.6" } }, "node_modules/@bsv/authsocket-client": { @@ -744,33 +975,23 @@ } }, "node_modules/@bsv/btms": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@bsv/btms/-/btms-1.1.0.tgz", - "integrity": "sha512-eQBfAwg+0lLSmEirbrAMS6qAKxpkQAq0F5WjLnPPzKREe65Zn3VkXmjP165CqAlvtXPL0aE9GeGL2uHuSRyc6Q==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bsv/btms/-/btms-1.0.1.tgz", + "integrity": "sha512-NBpLDxR4tw57iFizip03ulv2RPWZYvA5DOofHYjLmAVgA4UyrQmyCf33At6AIeHwlqNvdLx1fzK7/pM8jqfQ9w==", "license": "SEE LICENSE IN LICENSE.txt", "peerDependencies": { - "@bsv/sdk": "^2" - }, - "peerDependenciesMeta": { - "@bsv/sdk": { - "optional": false - } + "@bsv/sdk": "^2.0.3" } }, "node_modules/@bsv/btms-permission-module": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@bsv/btms-permission-module/-/btms-permission-module-1.1.0.tgz", - "integrity": "sha512-WnGe6KCFfdebSbqlUi5ESMDMt+bhrOByVTM8HOB6Ax/jnC/2c8g2CE0wEaBJjyoiA33/3g2LR9/N5aaZlcpK4Q==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bsv/btms-permission-module/-/btms-permission-module-1.0.1.tgz", + "integrity": "sha512-gyvjwvvMZTR3vz40dC4kF7PB9G6ih9raZgxtn8e7c3ZSW1KQunkqeG5jTq91Ah7boO1JF0d6Z3O0aEHXGwUEVw==", "license": "Open BSV", "peerDependencies": { - "@bsv/btms": "^1.0.2", - "@bsv/sdk": "^2", - "@bsv/wallet-toolbox-client": "^2.1.30" - }, - "peerDependenciesMeta": { - "@bsv/sdk": { - "optional": false - } + "@bsv/btms": ">=1.0.0", + "@bsv/sdk": ">=2.0.3", + "@bsv/wallet-toolbox-client": ">=2.0.16" } }, "node_modules/@bsv/btms-permission-module-ui": { @@ -815,15 +1036,15 @@ } }, "node_modules/@bsv/message-box-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@bsv/message-box-client/-/message-box-client-2.2.0.tgz", - "integrity": "sha512-l/bJOI9p2wetnsYaGcRbtn53soUuQxyqtH0AliyXWuKUY+aXUArAVjCmxy1Fkv+FGsa/uws8N0w/LyI3B7uDsA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@bsv/message-box-client/-/message-box-client-2.2.1.tgz", + "integrity": "sha512-iuUVcjQENP6SeFGuzd8BYHuNR0Ykc17quchSUy2PcGSSCS0rglxGgmCL1QlepXgKu28sYlqG4fbIzYaTqbR4fQ==", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { - "@bsv/authsocket-client": "^2.0.3" + "@bsv/authsocket-client": "^2.1.0" }, "peerDependencies": { - "@bsv/sdk": "^2" + "@bsv/sdk": "^2.1.6" }, "peerDependenciesMeta": { "@bsv/sdk": { @@ -832,20 +1053,13 @@ } }, "node_modules/@bsv/payment-express-middleware": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@bsv/payment-express-middleware/-/payment-express-middleware-2.1.0.tgz", - "integrity": "sha512-tiYwQeT6nnVi0pas+SaxPwaOQH1230BbI1T61TQ0btj+/QykE5Jwc+Ae0X1VMh5uj0jiHyJrMkxQ6rbX0fQ3dg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@bsv/payment-express-middleware/-/payment-express-middleware-2.0.1.tgz", + "integrity": "sha512-pFit3zEi6R2ixFWugXb6WgRoEFNXmmwRaV0oO3ala1gobtJIjc0WEJEASUQD6NYraEt7ql4xHDSkIWcisKO27g==", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { - "express": "^5.2.1" - }, - "peerDependencies": { - "@bsv/sdk": "^2" - }, - "peerDependenciesMeta": { - "@bsv/sdk": { - "optional": false - } + "@bsv/sdk": "^2.0.4", + "express": "^5.1.0" } }, "node_modules/@bsv/payment-express-middleware/node_modules/accepts": { @@ -862,34 +1076,21 @@ } }, "node_modules/@bsv/payment-express-middleware/node_modules/body-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", - "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", - "content-type": "^2.0.0", + "content-type": "^1.0.5", "debug": "^4.4.3", - "http-errors": "^2.0.1", - "iconv-lite": "^0.7.2", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", - "qs": "^6.15.2", - "raw-body": "^3.0.2", - "type-is": "^2.1.0" - }, - "engines": { - "node": ">=18" + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@bsv/payment-express-middleware/node_modules/body-parser/node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", "engines": { "node": ">=18" }, @@ -899,9 +1100,9 @@ } }, "node_modules/@bsv/payment-express-middleware/node_modules/content-disposition": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", - "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", "engines": { "node": ">=18" @@ -1154,34 +1355,17 @@ } }, "node_modules/@bsv/payment-express-middleware/node_modules/type-is": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", - "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", "dependencies": { - "content-type": "^2.0.0", + "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" }, "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@bsv/payment-express-middleware/node_modules/type-is/node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 0.6" } }, "node_modules/@bsv/sdk": { @@ -1204,787 +1388,680 @@ } }, "node_modules/@bsv/wallet-toolbox": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@bsv/wallet-toolbox/-/wallet-toolbox-2.3.2.tgz", - "integrity": "sha512-MZTENl5s59kubfsHcFB48Qdjz/WgqatBYANQgDYDwjTTb4VjnCIjFWNX1MAujJIGq1rj1hfHro8LWR/LmIckNw==", + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/@bsv/wallet-toolbox/-/wallet-toolbox-2.1.19.tgz", + "integrity": "sha512-KTKh5GHHIByPJ/HerVnQMkMeX+an5naIH0YYk+0D1NFF+dYzxl9iZzMdArpVVR7/t3Z/4k0Ey1F9Yy3qDCiycA==", "license": "SEE LICENSE IN license.md", "dependencies": { - "@bsv/auth-express-middleware": "^2.1.0", - "@bsv/payment-express-middleware": "^2.1.0", - "better-sqlite3": "^12.10.1", - "express": "^5.2.1", + "@bsv/auth-express-middleware": "^2.0.4", + "@bsv/payment-express-middleware": "^2.0.1", + "@bsv/sdk": "^2.0.13", + "better-sqlite3": "^12.6.2", + "express": "^4.21.2", "hash-wasm": "^4.12.0", "idb": "^8.0.2", - "knex": "^3.2.10", - "mysql2": "^3.22.5", - "ws": "^8.21.0" - }, - "peerDependencies": { - "@bsv/sdk": "^2.1.6" - }, - "peerDependenciesMeta": { - "@bsv/sdk": { - "optional": false - } + "knex": "^3.1.0", + "mysql2": "^3.12.0", + "ws": "^8.18.3" } }, "node_modules/@bsv/wallet-toolbox-client": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@bsv/wallet-toolbox-client/-/wallet-toolbox-client-2.3.2.tgz", - "integrity": "sha512-0WUXdQ0dLgYbsvnsUe/HAdfv8rUrJ9WyV2JYPoEGhQkDQNjoWe7nhwrvcm6dhizONfjIPL1YSMdk1eQVsdxXmw==", + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/@bsv/wallet-toolbox-client/-/wallet-toolbox-client-2.1.19.tgz", + "integrity": "sha512-uGHRUqRZsB/N3BwW7AFEXPAuap24JzPFG4hOUbtKmsLfUNnpjwMaLmAIYKJqmBPwkp7/f9UmNURxb1YgvJuQKQ==", "license": "SEE LICENSE IN license.md", "dependencies": { + "@bsv/sdk": "^2.0.13", "hash-wasm": "^4.12.0", "idb": "^8.0.2" - }, - "peerDependencies": { - "@bsv/sdk": "^2.1.6" - }, - "peerDependenciesMeta": { - "@bsv/sdk": { - "optional": false - } } }, - "node_modules/@bsv/wallet-toolbox/node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, "license": "MIT", "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/body-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", - "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "node_modules/@electron/asar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", + "dev": true, "license": "MIT", "dependencies": { - "bytes": "^3.1.2", - "content-type": "^2.0.0", - "debug": "^4.4.3", - "http-errors": "^2.0.1", - "iconv-lite": "^0.7.2", - "on-finished": "^2.4.1", - "qs": "^6.15.2", - "raw-body": "^3.0.2", - "type-is": "^2.1.0" + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" }, - "engines": { - "node": ">=18" + "bin": { + "asar": "bin/asar.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "engines": { + "node": ">=10.12.0" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/body-parser/node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", - "engines": { - "node": ">=18" + "node_modules/@electron/asar/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "engines": { + "node": "*" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/content-disposition": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", - "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "node_modules/@electron/fuses": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@electron/fuses/-/fuses-1.8.0.tgz", + "integrity": "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "chalk": "^4.1.1", + "fs-extra": "^9.0.1", + "minimist": "^1.2.5" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "bin": { + "electron-fuses": "dist/bin.js" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "node_modules/@electron/fuses/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=6.6.0" + "node": ">=10" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/express": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "node_modules/@electron/fuses/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, "license": "MIT", "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" + "universalify": "^2.0.0" }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/fuses/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 10.0.0" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" }, "engines": { - "node": ">= 18.0.0" + "node": ">=12" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "optionalDependencies": { + "global-agent": "^3.0.0" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "node_modules/@electron/notarize": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", + "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", + "dev": true, "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, "engines": { - "node": ">= 0.8" + "node": ">= 10.0.0" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "license": "MIT", "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">=10" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "node_modules/@electron/notarize/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@bsv/wallet-toolbox/node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@bsv/wallet-toolbox/node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", - "engines": { - "node": ">=18" + "universalify": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "node_modules/@electron/notarize/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 10.0.0" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "license": "MIT", + "node_modules/@electron/osx-sign": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.3.tgz", + "integrity": "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "mime-db": "^1.54.0" + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" }, - "engines": { - "node": ">=18" + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@bsv/wallet-toolbox/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=12.0.0" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=12" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, "engines": { - "node": ">= 18" + "node": ">= 8.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/gjtorikian/" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "node_modules/@electron/osx-sign/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, "license": "MIT", "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" + "universalify": "^2.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "node_modules/@electron/osx-sign/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 10.0.0" } }, - "node_modules/@bsv/wallet-toolbox/node_modules/type-is": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", - "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "node_modules/@electron/rebuild": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-4.0.3.tgz", + "integrity": "sha512-u9vpTHRMkOYCs/1FLiSVAFZ7FbjsXK+bQuzviJZa+lG7BHZl1nz52/IcGvwa3sk80/fc3llutBkbCq10Vh8WQA==", + "dev": true, "license": "MIT", "dependencies": { - "content-type": "^2.0.0", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" + "@malept/cross-spawn-promise": "^2.0.0", + "debug": "^4.1.1", + "detect-libc": "^2.0.1", + "got": "^11.7.0", + "graceful-fs": "^4.2.11", + "node-abi": "^4.2.0", + "node-api-version": "^0.2.1", + "node-gyp": "^11.2.0", + "ora": "^5.1.0", + "read-binary-file-arch": "^1.0.6", + "semver": "^7.3.5", + "tar": "^7.5.6", + "yargs": "^17.0.1" }, - "engines": { - "node": ">= 18" + "bin": { + "electron-rebuild": "lib/cli.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@bsv/wallet-toolbox/node_modules/type-is/node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">=22.12.0" } }, - "node_modules/@develar/schema-utils": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", - "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "node_modules/@electron/rebuild/node_modules/@npmcli/fs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ajv": "^6.12.0", - "ajv-keywords": "^3.4.1" + "semver": "^7.3.5" }, "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@electron/asar": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", - "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", + "node_modules/@electron/rebuild/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "license": "MIT", "dependencies": { - "commander": "^5.0.0", - "glob": "^7.1.6", - "minimatch": "^3.0.4" - }, - "bin": { - "asar": "bin/asar.js" - }, - "engines": { - "node": ">=10.12.0" + "balanced-match": "^1.0.0" } }, - "node_modules/@electron/asar/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/@electron/rebuild/node_modules/cacache": { + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "*" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@electron/fuses": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@electron/fuses/-/fuses-1.8.0.tgz", - "integrity": "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==", + "node_modules/@electron/rebuild/node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "chalk": "^4.1.1", - "fs-extra": "^9.0.1", - "minimist": "^1.2.5" + "minipass": "^7.0.3" }, - "bin": { - "electron-fuses": "dist/bin.js" + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@electron/fuses/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/@electron/rebuild/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=10" + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@electron/fuses/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "node_modules/@electron/rebuild/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "license": "ISC", + "engines": { + "node": ">=16" } }, - "node_modules/@electron/fuses/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/@electron/rebuild/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT", + "license": "ISC" + }, + "node_modules/@electron/rebuild/node_modules/make-fetch-happen": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "ssri": "^12.0.0" + }, "engines": { - "node": ">= 10.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@electron/get": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", - "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "node_modules/@electron/rebuild/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" + "brace-expansion": "^2.0.2" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, - "optionalDependencies": { - "global-agent": "^3.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@electron/notarize": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", - "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", + "node_modules/@electron/rebuild/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "fs-extra": "^9.0.1", - "promise-retry": "^2.0.1" - }, + "license": "ISC", "engines": { - "node": ">= 10.0.0" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/@electron/notarize/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/@electron/rebuild/node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/@electron/notarize/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "node_modules/@electron/rebuild/node_modules/minipass-fetch": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", "dev": true, "license": "MIT", "dependencies": { - "universalify": "^2.0.0" + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { - "graceful-fs": "^4.1.6" + "encoding": "^0.1.13" } }, - "node_modules/@electron/notarize/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/@electron/rebuild/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 10.0.0" + "node": ">= 0.6" } }, - "node_modules/@electron/osx-sign": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.3.tgz", - "integrity": "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==", + "node_modules/@electron/rebuild/node_modules/node-abi": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.26.0.tgz", + "integrity": "sha512-8QwIZqikRvDIkXS2S93LjzhsSPJuIbfaMETWH+Bx8oOT9Sa9UsUtBFQlc3gBNd1+QINjaTloitXr1W3dQLi9Iw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "compare-version": "^0.1.2", - "debug": "^4.3.4", - "fs-extra": "^10.0.0", - "isbinaryfile": "^4.0.8", - "minimist": "^1.2.6", - "plist": "^3.0.5" - }, - "bin": { - "electron-osx-flat": "bin/electron-osx-flat.js", - "electron-osx-sign": "bin/electron-osx-sign.js" + "semver": "^7.6.3" }, "engines": { - "node": ">=12.0.0" + "node": ">=22.12.0" } }, - "node_modules/@electron/osx-sign/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "node_modules/@electron/rebuild/node_modules/node-gyp": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz", + "integrity": "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "tar": "^7.4.3", + "tinyglobby": "^0.2.12", + "which": "^5.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": ">=12" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "node_modules/@electron/rebuild/node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 8.0.0" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/gjtorikian/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@electron/osx-sign/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "node_modules/@electron/rebuild/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/osx-sign/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", "engines": { - "node": ">= 10.0.0" + "node": ">=10" } }, - "node_modules/@electron/rebuild": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-4.0.3.tgz", - "integrity": "sha512-u9vpTHRMkOYCs/1FLiSVAFZ7FbjsXK+bQuzviJZa+lG7BHZl1nz52/IcGvwa3sk80/fc3llutBkbCq10Vh8WQA==", + "node_modules/@electron/rebuild/node_modules/ssri": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@malept/cross-spawn-promise": "^2.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "got": "^11.7.0", - "graceful-fs": "^4.2.11", - "node-abi": "^4.2.0", - "node-api-version": "^0.2.1", - "node-gyp": "^11.2.0", - "ora": "^5.1.0", - "read-binary-file-arch": "^1.0.6", - "semver": "^7.3.5", - "tar": "^7.5.6", - "yargs": "^17.0.1" - }, - "bin": { - "electron-rebuild": "lib/cli.js" + "minipass": "^7.0.3" }, "engines": { - "node": ">=22.12.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@electron/rebuild/node_modules/@npmcli/fs": { + "node_modules/@electron/rebuild/node_modules/unique-filename": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", - "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "semver": "^7.3.5" + "unique-slug": "^5.0.0" }, "engines": { "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@electron/rebuild/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "node_modules/@electron/rebuild/node_modules/unique-slug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "balanced-match": "^1.0.0" + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@electron/rebuild/node_modules/cacache": { - "version": "19.0.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", - "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", + "node_modules/@electron/rebuild/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^4.0.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^7.0.2", - "ssri": "^12.0.0", - "tar": "^7.4.3", - "unique-filename": "^4.0.0" + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" }, "engines": { "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@electron/rebuild/node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "node_modules/@electron/universal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.3.tgz", + "integrity": "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^7.0.3" + "@electron/asar": "^3.3.1", + "@malept/cross-spawn-promise": "^2.0.0", + "debug": "^4.3.1", + "dir-compare": "^4.2.0", + "fs-extra": "^11.1.1", + "minimatch": "^9.0.3", + "plist": "^3.1.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=16.4" } }, - "node_modules/@electron/rebuild/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "node_modules/@electron/universal/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "balanced-match": "^1.0.0" } }, - "node_modules/@electron/rebuild/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", + "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=16" + "node": ">=14.14" } }, - "node_modules/@electron/rebuild/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/@electron/rebuild/node_modules/make-fetch-happen": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", - "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "@npmcli/agent": "^3.0.0", - "cacache": "^19.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^1.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "ssri": "^12.0.0" + "universalify": "^2.0.0" }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/@electron/rebuild/node_modules/minimatch": { + "node_modules/@electron/universal/node_modules/minimatch": { "version": "9.0.9", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", @@ -2000,293 +2077,50 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@electron/rebuild/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 10.0.0" } }, - "node_modules/@electron/rebuild/node_modules/minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "node_modules/@electron/windows-sign": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.2.tgz", + "integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", + "optional": true, + "peer": true, "dependencies": { - "minipass": "^7.0.3" + "cross-dirname": "^0.1.0", + "debug": "^4.3.4", + "fs-extra": "^11.1.1", + "minimist": "^1.2.8", + "postject": "^1.0.0-alpha.6" + }, + "bin": { + "electron-windows-sign": "bin/electron-windows-sign.js" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=14.14" } }, - "node_modules/@electron/rebuild/node_modules/minipass-fetch": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", - "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", + "node_modules/@electron/windows-sign/node_modules/fs-extra": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", + "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/@electron/rebuild/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@electron/rebuild/node_modules/node-abi": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.26.0.tgz", - "integrity": "sha512-8QwIZqikRvDIkXS2S93LjzhsSPJuIbfaMETWH+Bx8oOT9Sa9UsUtBFQlc3gBNd1+QINjaTloitXr1W3dQLi9Iw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.6.3" - }, - "engines": { - "node": ">=22.12.0" - } - }, - "node_modules/@electron/rebuild/node_modules/node-gyp": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz", - "integrity": "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^14.0.3", - "nopt": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "tar": "^7.4.3", - "tinyglobby": "^0.2.12", - "which": "^5.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@electron/rebuild/node_modules/p-map": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", - "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@electron/rebuild/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/rebuild/node_modules/ssri": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", - "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@electron/rebuild/node_modules/unique-filename": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", - "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@electron/rebuild/node_modules/unique-slug": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", - "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@electron/rebuild/node_modules/which": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", - "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@electron/universal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.3.tgz", - "integrity": "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron/asar": "^3.3.1", - "@malept/cross-spawn-promise": "^2.0.0", - "debug": "^4.3.1", - "dir-compare": "^4.2.0", - "fs-extra": "^11.1.1", - "minimatch": "^9.0.3", - "plist": "^3.1.0" - }, - "engines": { - "node": ">=16.4" - } - }, - "node_modules/@electron/universal/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@electron/universal/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/universal/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@electron/universal/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/windows-sign": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.2.tgz", - "integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "peer": true, - "dependencies": { - "cross-dirname": "^0.1.0", - "debug": "^4.3.4", - "fs-extra": "^11.1.1", - "minimist": "^1.2.8", - "postject": "^1.0.0-alpha.6" - }, - "bin": { - "electron-windows-sign": "bin/electron-windows-sign.js" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@electron/windows-sign/node_modules/fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { "node": ">=14.14" @@ -3033,11 +2867,174 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "license": "MIT", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3" }, @@ -3045,6 +3042,84 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -3057,6 +3132,86 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT", + "peer": true + }, "node_modules/@jest/types": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", @@ -3088,7 +3243,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -3469,6 +3623,42 @@ } } }, + "node_modules/@noble/curves": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.2.0.tgz", + "integrity": "sha512-T/BoHgFXirb0ENSPBquzX0rcjXeM6Lo892a2jlYJkqk83LqZx0l1Of7DzlKJ6jkpvMrkHSnAcgb5JegL8SeIkQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "2.2.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz", + "integrity": "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/secp256k1": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-3.1.0.tgz", + "integrity": "sha512-+F7iS7tUMaNGXcc9X3PjmjvuQnXEuSjCRNzVVA2xAcKXgCaP0dHYz4SFyt4FKNHef7sOP//xihowcySSS7PK9g==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@npmcli/agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", @@ -3536,31 +3726,91 @@ "dev": true, "license": "MIT" }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", - "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", - "cpu": [ - "arm" - ], + "node_modules/@rollup/plugin-inject": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz", + "integrity": "sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", - "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", - "cpu": [ - "arm64" - ], + "node_modules/@rollup/plugin-inject/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ "android" ] }, @@ -3886,6 +4136,42 @@ "win32" ] }, + "node_modules/@scure/base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-2.2.0.tgz", + "integrity": "sha512-b8XEupJibegiXV+tDUseI8oLQc8ei3d/4Jkb2RpbHh3MfE054ov3uIz2dhFkB3FI8iwYkEh0gGCApkrYggkPNg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-2.2.0.tgz", + "integrity": "sha512-zFr7t2F+a9+5tB7QbarF2HQNYrgjCNaoLAupZdKkrFMYMozJf5zqH2WJCQibMzm1qQ0QogrxVGO3qXfQDYMaQg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "2.2.0", + "@noble/hashes": "2.2.0", + "@scure/base": "2.2.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-2.2.0.tgz", + "integrity": "sha512-T/Bj/YvYMNkIPq6EENO6/rcs2e7qTNuyoUXf0KBFDmp0ZDu0H2X4Lq6yC3i0c8PcWkov5EbW+yQZZbdMmk154A==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "2.2.0", + "@scure/base": "2.2.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -3905,6 +4191,26 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", @@ -3924,11 +4230,16 @@ "node": ">=10" } }, + "node_modules/@types/allure-js-commons": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@types/allure-js-commons/-/allure-js-commons-0.0.0.tgz", + "integrity": "sha512-LvREMEGmh0oZIQ11d/vt6BSv6CD0w3berVRRFrpgDVkRhAu+UFkreDrRrdl+01PFjf7/J0lJV1UrhVyRS2tOWA==", + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", @@ -3942,7 +4253,6 @@ "version": "7.27.0", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" @@ -3952,7 +4262,6 @@ "version": "7.4.4", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", @@ -3963,7 +4272,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.28.2" @@ -4083,6 +4391,16 @@ "@types/node": "*" } }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/history": { "version": "4.7.11", "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", @@ -4320,12 +4638,11 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "license": "MIT" }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true + "node_modules/@types/strip-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-ansi/-/strip-ansi-3.0.0.tgz", + "integrity": "sha512-wVhzc+WJ/JNdV25MeaK0skxGdbdOFeqYv1sqY8yPXbsshZ0XwSbWWwfKzj836cPW+e+PpqUNvKoiac9ZqCdyRQ==", + "license": "MIT" }, "node_modules/@types/verror": { "version": "1.10.11", @@ -4383,15 +4700,15 @@ } }, "node_modules/@vitest/expect": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.6.tgz", - "integrity": "sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.6", - "@vitest/utils": "3.2.6", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -4400,13 +4717,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.6.tgz", - "integrity": "sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.6", + "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -4427,9 +4744,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz", - "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -4440,13 +4757,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.6.tgz", - "integrity": "sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.6", + "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" }, @@ -4455,13 +4772,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.6.tgz", - "integrity": "sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.6", + "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -4470,9 +4787,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.6.tgz", - "integrity": "sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", "dependencies": { @@ -4483,13 +4800,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.6.tgz", - "integrity": "sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.6", + "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" }, @@ -4527,6 +4844,12 @@ "node": ">= 0.6" } }, + "node_modules/aes-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", + "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==", + "license": "MIT" + }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -4564,11 +4887,72 @@ "ajv": "^6.9.1" } }, + "node_modules/allure-js-commons": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/allure-js-commons/-/allure-js-commons-1.3.2.tgz", + "integrity": "sha512-FTmoqP36ZjHFT4iLdYamyCFhyj1jqD6BIdiZ5pBlyafDJrFRV76XIXNxwRqbHpSw40o1vHzYi4vGpmREnhnHVw==", + "license": "Apache-2.0", + "dependencies": { + "file-type": "^7.7.1", + "fs-extra": "^6.0.1", + "js2xmlparser": "^3.0.0", + "mime": "^2.3.1", + "object-assign": "^4.1.1", + "uuid": "^3.0.0" + } + }, + "node_modules/allure-js-commons/node_modules/fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-font": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ansi-font/-/ansi-font-0.0.2.tgz", + "integrity": "sha512-F0/7wvsUxF38bWUB1yI2O4Cxm04XUvnF5emQmvjJyPjYkbTbiQR51pHmxuFBUkTvWA2vG0Uvzm2/TU+teFTwwg==", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4589,6 +4973,33 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "peer": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/app-builder-bin": { "version": "5.0.0-alpha.12", "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.12.tgz", @@ -4813,6 +5224,32 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -4828,7 +5265,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -4879,6 +5315,22 @@ "node": ">= 4.0.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/aws-ssl-profiles": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", @@ -4888,6 +5340,87 @@ "node": ">= 6.0.0" } }, + "node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -4903,15 +5436,67 @@ "npm": ">=6" } }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "license": "MIT", + "peer": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, - "node_modules/base64-js": { - "version": "1.5.1", + "node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ @@ -4931,22 +5516,18 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.38", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", - "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", - "dev": true, + "version": "2.8.10", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.10.tgz", + "integrity": "sha512-uLfgBi+7IBNay8ECBO2mVMGZAc1VgZWEChxm4lv+TobGdG82LnXMjuNGo/BSSZZL4UmkWhxEHP2f5ziLNwGWMA==", "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" + "baseline-browser-mapping": "dist/cli.js" } }, "node_modules/better-sqlite3": { - "version": "12.11.1", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.11.1.tgz", - "integrity": "sha512-dq9AtApgg5PGFtBzPFSBl3HZQjHok5gaQCM6zh2Yk0aSmDCs1CbnVI8/HgASQkNKsWFpseIO9beg5xxpYhbIfA==", + "version": "12.8.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.8.0.tgz", + "integrity": "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -4954,7 +5535,7 @@ "prebuild-install": "^7.1.1" }, "engines": { - "node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x" + "node": "20.x || 22.x || 23.x || 24.x || 25.x" } }, "node_modules/bindings": { @@ -4977,10 +5558,16 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "license": "MIT" + }, "node_modules/body-parser": { - "version": "1.20.5", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", - "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -4991,7 +5578,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.15.1", + "qs": "~6.14.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -5070,7 +5657,6 @@ "version": "1.1.13", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -5089,11 +5675,196 @@ "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.17.0" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-rsa/node_modules/bn.js": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "dev": true, + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.6.1", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign/node_modules/bn.js": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", "funding": [ { "type": "opencollective", @@ -5110,11 +5881,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -5123,6 +5894,47 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/bsv": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/bsv/-/bsv-1.5.6.tgz", + "integrity": "sha512-A0g36x63lVF9Ia6/z/RjcxaQMHE5cLl2rDxjUIKz0UTMLf5bPPyLI9yVyY2JkecF77MrU+MQdKVt0MSdU5abtw==", + "license": "MIT", + "dependencies": { + "aes-js": "^3.1.2", + "bn.js": "=4.11.9", + "bs58": "=4.0.1", + "clone-deep": "^4.0.1", + "elliptic": "6.5.4", + "hash.js": "^1.1.7", + "inherits": "2.0.3", + "unorm": "1.4.1" + } + }, + "node_modules/bsv/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -5161,6 +5973,12 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "dev": true, "license": "MIT" }, @@ -5240,6 +6058,13 @@ "node": ">= 10.0.0" } }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true, + "license": "MIT" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -5288,6 +6113,25 @@ "node": ">=8" } }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -5326,11 +6170,20 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/caniuse-lite": { - "version": "1.0.30001799", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", - "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", - "dev": true, + "version": "1.0.30001746", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001746.tgz", + "integrity": "sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==", "funding": [ { "type": "opencollective", @@ -5360,7 +6213,6 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", - "dev": true, "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", @@ -5373,6 +6225,30 @@ "node": ">=18" } }, + "node_modules/chai-as-promised": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz", + "integrity": "sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==", + "license": "WTFPL", + "dependencies": { + "check-error": "^1.0.2" + }, + "peerDependencies": { + "chai": ">= 2.1.2 < 6" + } + }, + "node_modules/chai-as-promised/node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -5401,11 +6277,20 @@ "node": ">=8" } }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + } + }, "node_modules/check-error": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 16" @@ -5439,6 +6324,28 @@ "node": ">=8" } }, + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "license": "MIT", + "peer": true + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -5487,7 +6394,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -5508,6 +6414,20 @@ "node": ">=0.8" } }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/clone-response": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", @@ -5530,6 +6450,23 @@ "node": ">=6" } }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "license": "MIT", + "peer": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "license": "MIT" + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -5591,19 +6528,18 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/concurrently": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.3.tgz", - "integrity": "sha512-ihjs0E2SxvDgq/MK418hX6YycQgKhsqxpbZuZbHo0yKfqDWdymWMjWYIpCIzqDDLLKClHlXev8whW/8WXmJ0BA==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", + "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", "dev": true, "license": "MIT", "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", - "shell-quote": "1.8.4", + "shell-quote": "1.8.3", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" @@ -5619,6 +6555,19 @@ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true, + "license": "MIT" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -5666,8 +6615,7 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/cors": { "version": "2.8.6", @@ -5722,6 +6670,75 @@ "buffer": "^5.1.0" } }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-dirname": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/cross-dirname/-/cross-dirname-0.1.0.tgz", @@ -5735,7 +6752,6 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -5746,7 +6762,34 @@ "node": ">= 8" } }, - "node_modules/css-vendor": { + "node_modules/crypto-browserify": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/css-vendor": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", @@ -5781,6 +6824,15 @@ "url": "https://github.com/sponsors/kossnocorp" } }, + "node_modules/dateformat": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.2.tgz", + "integrity": "sha512-EelsCzH0gMC2YmXuMeaZ3c6md1sUJQxyb1XXc4xaisi/K6qKukqZhKPrEQyRkdNIncgYyLoDTReq0nNyuKerTg==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -5825,11 +6877,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deep-eql": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5844,6 +6910,16 @@ "node": ">=4.0.0" } }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -5873,7 +6949,6 @@ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -5892,7 +6967,6 @@ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -5933,6 +7007,17 @@ "node": ">= 0.8" } }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -5952,6 +7037,16 @@ "node": ">=8" } }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", @@ -5969,6 +7064,18 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, "node_modules/dir-compare": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", @@ -6085,13 +7192,17 @@ "csstype": "^3.0.2" } }, - "node_modules/dompurify": { - "version": "3.4.11", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz", - "integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" + "node_modules/domain-browser": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", + "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://bevry.me/fund" } }, "node_modules/dotenv": { @@ -6149,6 +7260,10 @@ "node": ">= 0.4" } }, + "node_modules/dxs-bsv-token-sdk": { + "resolved": "vendor/dxs-bsv-token-sdk", + "link": true + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -6355,10 +7470,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.376", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.376.tgz", - "integrity": "sha512-cUVA7/RvbFTEuw/i3obUwDTRIXojaxkResf+ibByPFxjc6XK3VNtcQXV0NSbAlJ0FMjcJGgftVVB4Qo184EXvA==", - "dev": true, + "version": "1.5.228", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.228.tgz", + "integrity": "sha512-nxkiyuqAn4MJ1QbobwqJILiDtu/jk14hEAWaMiJmNPh1Z+jqoFlBFZjdXwLWGeVSeu9hGLg6+2G9yJaW8rBIFA==", "license": "ISC" }, "node_modules/electron-updater": { @@ -6479,11 +7593,38 @@ "dev": true, "license": "MIT" }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/encodeurl": { @@ -6499,7 +7640,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -6702,6 +7842,20 @@ "node": ">=6" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -6721,6 +7875,73 @@ "node": ">= 0.6" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -6764,14 +7985,14 @@ "license": "Apache-2.0" }, "node_modules/express": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", - "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "~1.20.5", + "body-parser": "~1.20.3", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", @@ -6790,7 +8011,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "~6.15.1", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", @@ -6867,9 +8088,18 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, "license": "MIT" }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "bser": "2.1.1" + } + }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -6921,6 +8151,15 @@ "node": "^12.20 || >= 14.13" } }, + "node_modules/file-type": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-7.7.1.tgz", + "integrity": "sha512-bTrKkzzZI6wH+NXhyD3SOXtb2zXTw2SbwI2RxUlRcXVsnN7jNL5hJzVQLYv7FOQhxFkK4XWdAflEaWFpaLLWpQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -7011,6 +8250,56 @@ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", "license": "MIT" }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -7042,17 +8331,17 @@ } }, "node_modules/form-data": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", - "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.4", - "mime-types": "^2.1.35" + "hasown": "^2.0.2", + "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" @@ -7113,14 +8402,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -7158,11 +8445,20 @@ "is-property": "^1.0.2" } }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -7172,12 +8468,20 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -7257,7 +8561,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -7278,7 +8581,6 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -7397,7 +8699,6 @@ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -7433,16 +8734,40 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/hash-wasm": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.12.0.tgz", "integrity": "sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ==", "license": "MIT" }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -7465,6 +8790,17 @@ "value-equal": "^1.0.1" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -7513,6 +8849,13 @@ "dev": true, "license": "ISC" }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "license": "MIT", + "peer": true + }, "node_modules/html-parse-stringify": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", @@ -7573,6 +8916,13 @@ "node": ">=10.19.0" } }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true, + "license": "MIT" + }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", @@ -7587,6 +8937,16 @@ "node": ">= 14" } }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/hyphenate-style-name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", @@ -7646,7 +9006,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -7697,11 +9057,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "license": "MIT", + "peer": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -7712,7 +9091,6 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -7759,12 +9137,42 @@ "node": ">= 0.10" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "license": "MIT" }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -7784,12 +9192,41 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-in-browser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", @@ -7806,6 +9243,23 @@ "node": ">=8" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -7815,6 +9269,18 @@ "node": ">=0.12.0" } }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -7827,6 +9293,54 @@ "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", "license": "MIT" }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -7863,7 +9377,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/iso-3166-ts": { @@ -7872,6 +9385,132 @@ "integrity": "sha512-tgV67XkuIVjZuS5Kr8HxGeLkqnP2MFJ1KDx6dTeniZCXVs4GoF44Cgei2MSy6mv+RnPwMfL+vwvvKl0XRgl2Wg==", "license": "ISC" }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isomorphic-timers-promises": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz", + "integrity": "sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", @@ -7884,102 +9523,645 @@ "funding": { "url": "https://github.com/sponsors/isaacs" }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jdenticon": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/jdenticon/-/jdenticon-3.3.0.tgz", + "integrity": "sha512-DhuBRNRIybGPeAjMjdHbkIfiwZCCmf8ggu7C49jhp6aJ7DYsZfudnvnTY5/1vgUhrGA7JaDAx1WevnpjCPvaGg==", + "license": "MIT", + "dependencies": { + "canvas-renderer": "~2.2.0" + }, + "bin": { + "jdenticon": "bin/jdenticon.js" + }, + "engines": { + "node": ">=6.4.0" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-allure": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/jest-allure/-/jest-allure-0.1.3.tgz", + "integrity": "sha512-EkO3LmkPx/a4VDg81JKtdy6kFXI0D1rHRIJ5Sa9MZaGtFYpgiCJFa6XwTgIySaVN+3+QBbIt1558CEkIW7FKFA==", + "license": "MIT", + "dependencies": { + "@types/allure-js-commons": "^0.0.0", + "@types/jest": "^22.2.3", + "@types/node": "^10.1.2", + "@types/strip-ansi": "^3.0.0", + "allure-js-commons": "^1.3.2", + "strip-ansi": "^4.0.0" + } + }, + "node_modules/jest-allure/node_modules/@types/jest": { + "version": "22.2.3", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-22.2.3.tgz", + "integrity": "sha512-e74sM9W/4qqWB6D4TWV9FQk0WoHtX1X4FJpbjxucMSVJHtFjbQOH3H6yp+xno4br0AKG0wz/kPtaN599GUOvAg==", + "license": "MIT" + }, + "node_modules/jest-allure/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "license": "MIT" + }, + "node_modules/jest-allure/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-allure/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "license": "MIT", + "peer": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "license": "MIT", + "peer": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-html-reporter": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/jest-html-reporter/-/jest-html-reporter-3.10.2.tgz", + "integrity": "sha512-XRBa5ylHPUQoo8aJXEEdKsTruieTdlPbRktMx9WG9evMTxzJEKGFMaw5x+sQxJuClWdNR72GGwbOaz+6HIlksA==", + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.0.2", + "@jest/types": "^29.0.2", + "dateformat": "3.0.2", + "mkdirp": "^1.0.3", + "strip-ansi": "6.0.1", + "xmlbuilder": "15.0.0" + }, + "engines": { + "node": ">=4.8.3" + }, + "peerDependencies": { + "jest": "19.x - 29.x", + "typescript": "^3.7.x || ^4.3.x || ^5.x" + } + }, + "node_modules/jest-html-reporter/node_modules/xmlbuilder": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.0.0.tgz", + "integrity": "sha512-KLu/G0DoWhkncQ9eHSI6s0/w+T4TM7rQaLhtCaL6tORv8jFlJPlnGumsgTcGfYeS1qZ/IHqrvDG7zJZ4d7e+nw==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "license": "MIT", + "peer": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jake": { - "version": "10.9.4", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", - "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", - "dev": true, - "license": "Apache-2.0", + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "license": "MIT", + "peer": true, "dependencies": { - "async": "^3.2.6", - "filelist": "^1.0.4", - "picocolors": "^1.1.1" - }, - "bin": { - "jake": "bin/cli.js" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jdenticon": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/jdenticon/-/jdenticon-3.3.0.tgz", - "integrity": "sha512-DhuBRNRIybGPeAjMjdHbkIfiwZCCmf8ggu7C49jhp6aJ7DYsZfudnvnTY5/1vgUhrGA7JaDAx1WevnpjCPvaGg==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "license": "MIT", - "dependencies": { - "canvas-renderer": "~2.2.0" + "peer": true, + "engines": { + "node": ">=6" }, - "bin": { - "jdenticon": "bin/jdenticon.js" + "peerDependencies": { + "jest-resolve": "*" }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "license": "MIT", + "peer": true, "engines": { - "node": ">=6.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-diff": { + "node_modules/jest-resolve": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "license": "MIT", + "peer": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "license": "MIT", + "peer": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils": { + "node_modules/jest-runner": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "license": "MIT", + "peer": true, "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-message-util": { + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "license": "MIT", + "peer": true, "dependencies": { - "@babel/code-frame": "^7.12.13", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", + "@types/node": "*", "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -8009,6 +10191,73 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -8026,19 +10275,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -8047,6 +10286,15 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", + "integrity": "sha512-CSOkdn0/GhRFwxnipmhXfqJ+FG6+wkWBi46kKSsPx6+j65176ZiQcrCYpg6K8x3iLbO4k3zScBnZ7I/L80dAtw==", + "license": "Apache-2.0", + "dependencies": { + "xmlcreate": "^1.0.1" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -8091,7 +10339,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -8104,7 +10351,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" @@ -8210,10 +10456,29 @@ "json-buffer": "3.0.1" } }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/knex": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/knex/-/knex-3.2.10.tgz", - "integrity": "sha512-oypTHfrc9i72iyxaUQBKHOxhcr0xM65MPf6FpN02nimsftXwzXprIkLjfXdubvhbu4PMWLp023q8o8CYvHSuZw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz", + "integrity": "sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==", "license": "MIT", "dependencies": { "colorette": "2.0.19", @@ -8224,7 +10489,7 @@ "get-package-type": "^0.1.0", "getopts": "2.3.0", "interpret": "^2.2.0", - "lodash": "^4.18.1", + "lodash": "^4.17.21", "pg-connection-string": "2.6.2", "rechoir": "^0.8.0", "resolve-from": "^5.0.0", @@ -8237,9 +10502,6 @@ "engines": { "node": ">=16" }, - "peerDependencies": { - "pg-query-stream": "^4.14.0" - }, "peerDependenciesMeta": { "better-sqlite3": { "optional": true @@ -8256,9 +10518,6 @@ "pg-native": { "optional": true }, - "pg-query-stream": { - "optional": true - }, "sqlite3": { "optional": true }, @@ -8314,6 +10573,16 @@ "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", "license": "MIT" }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/libphonenumber-js": { "version": "1.12.37", "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.37.tgz", @@ -8326,6 +10595,19 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/lodash": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", @@ -8384,7 +10666,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", - "dev": true, "license": "MIT" }, "node_modules/lowercase-keys": { @@ -8401,16 +10682,15 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/lru.min": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", - "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", + "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", "license": "MIT", "engines": { "bun": ">=1.0.0", @@ -8429,7 +10709,46 @@ "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "license": "MIT", + "peer": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "tmpl": "1.0.5" } }, "node_modules/matcher": { @@ -8455,6 +10774,18 @@ "node": ">= 0.4" } }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -8473,6 +10804,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT", + "peer": true + }, "node_modules/metanet-apps": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/metanet-apps/-/metanet-apps-1.0.9.tgz", @@ -8796,11 +11134,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, "node_modules/mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, "license": "MIT", "bin": { "mime": "cli.js" @@ -8834,7 +11185,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8850,6 +11200,18 @@ "node": ">=4" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" + }, "node_modules/minimatch": { "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", @@ -8877,9 +11239,9 @@ } }, "node_modules/minimatch/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8980,6 +11342,18 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -8993,31 +11367,29 @@ "license": "MIT" }, "node_modules/mysql2": { - "version": "3.22.5", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.22.5.tgz", - "integrity": "sha512-95uZ2TrPWAZdwpB3vvvDbmEMcNG8yIeNCyu6GUcr/QnWEE/wXm7+mhOCsdQfWQDTV7qYT/PDUZ4U4UPP4AsXqQ==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.15.2.tgz", + "integrity": "sha512-kFm5+jbwR5mC+lo+3Cy46eHiykWSpUtTLOH3GE+AR7GeLq8PgfJcvpMiyVWk9/O53DjQsqm6a3VOOfq7gYWFRg==", "license": "MIT", "dependencies": { - "aws-ssl-profiles": "^1.1.2", + "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", - "iconv-lite": "^0.7.2", - "long": "^5.3.2", - "lru.min": "^1.1.4", - "named-placeholders": "^1.1.6", - "sql-escaper": "^1.3.3" + "iconv-lite": "^0.7.0", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" }, "engines": { "node": ">= 8.0" - }, - "peerDependencies": { - "@types/node": ">= 8" } }, "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -9031,15 +11403,24 @@ } }, "node_modules/named-placeholders": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", - "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", "license": "MIT", "dependencies": { - "lru.min": "^1.1.0" + "lru-cache": "^7.14.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" } }, "node_modules/nanoid": { @@ -9067,6 +11448,13 @@ "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", "license": "MIT" }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "license": "MIT", + "peer": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -9178,16 +11566,127 @@ "node": ">= 6.13.0" } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "license": "MIT", + "peer": true + }, "node_modules/node-releases": { - "version": "2.0.48", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.48.tgz", - "integrity": "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", + "license": "MIT" + }, + "node_modules/node-stdlib-browser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.3.1.tgz", + "integrity": "sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert": "^2.0.0", + "browser-resolve": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.7.1", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "create-require": "^1.1.1", + "crypto-browserify": "^3.12.1", + "domain-browser": "4.22.0", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "isomorphic-timers-promises": "^1.0.1", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "pkg-dir": "^5.0.0", + "process": "^0.11.10", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.6.0", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.1", + "url": "^0.11.4", + "util": "^0.12.4", + "vm-browserify": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-stdlib-browser/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/node-stdlib-browser/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/node-stdlib-browser/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/node-stdlib-browser/node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" } }, + "node_modules/node-stdlib-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/nopt": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", @@ -9214,6 +11713,16 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -9227,6 +11736,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "peer": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -9248,17 +11770,54 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 0.4" } }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -9284,7 +11843,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" @@ -9320,6 +11878,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true, + "license": "MIT" + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -9334,7 +11899,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -9346,6 +11910,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -9353,6 +11956,13 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -9365,6 +11975,23 @@ "node": ">=6" } }, + "node_modules/parse-asn1": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -9392,11 +12019,26 @@ "node": ">= 0.8" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9406,7 +12048,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9478,12 +12119,29 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 14.16" } }, + "node_modules/pbkdf2": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/pe-library": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz", @@ -9531,6 +12189,29 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/plist": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", @@ -9546,6 +12227,16 @@ "node": ">=10.4.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.5.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", @@ -9671,9 +12362,26 @@ "dev": true, "license": "ISC", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -9698,6 +12406,20 @@ "node": ">=10" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -9740,6 +12462,21 @@ "node": ">= 0.10" } }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -9760,6 +12497,23 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "peer": true + }, "node_modules/qrcode.react": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz", @@ -9770,9 +12524,9 @@ } }, "node_modules/qs": { - "version": "6.15.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", - "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -9784,6 +12538,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", @@ -9797,6 +12560,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -10079,7 +12863,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10130,6 +12913,29 @@ "dev": true, "license": "MIT" }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "license": "MIT", + "peer": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -10145,6 +12951,16 @@ "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", "license": "MIT" }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -10182,6 +12998,83 @@ "node": ">= 4" } }, + "node_modules/ripemd160": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ripemd160/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/ripemd160/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -10302,6 +13195,24 @@ ], "license": "MIT" }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -10337,7 +13248,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -10411,6 +13321,11 @@ "node": ">=4" } }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "node_modules/serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", @@ -10443,17 +13358,74 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -10466,16 +13438,15 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shell-quote": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", - "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, "license": "MIT", "engines": { @@ -10568,7 +13539,6 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, "license": "ISC" }, "node_modules/simple-concat": { @@ -10642,6 +13612,13 @@ "node": ">=10" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT", + "peer": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -10769,19 +13746,13 @@ "license": "BSD-3-Clause", "optional": true }, - "node_modules/sql-escaper": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/sql-escaper/-/sql-escaper-1.3.3.tgz", - "integrity": "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw==", + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", "license": "MIT", "engines": { - "bun": ">=1.0.0", - "deno": ">=2.0.0", - "node": ">=12.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/mysqljs/sql-escaper?sponsor=1" + "node": ">= 0.6" } }, "node_modules/stack-utils": { @@ -10792,25 +13763,151 @@ "dependencies": { "escape-string-regexp": "^2.0.0" }, - "engines": { - "node": ">=10" + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/stas-js": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/stas-js/-/stas-js-3.0.3.tgz", + "integrity": "sha512-FwSt0RU70xUPbFeQQE6hTPppAxMC6nF9rA/z+tFDo3jLkwrEfedQo12QLdUMgJDK4bQKn7hG4vVzIjvusFlgUQ==", + "license": "ISC", + "dependencies": { + "axios": "^0.21.4", + "chai": "^4.3.4", + "chai-as-promised": "^7.1.1", + "dotenv": "^10.0.0", + "jest-allure": "0.1.3", + "jest-html-reporter": "^3.4.2", + "node-fetch": "^2.6.6", + "test": "^0.6.0" + }, + "peerDependencies": { + "bsv": "^1.5.4" + } + }, + "node_modules/stas-js/node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/stas-js/node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/stas-js/node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stas-js/node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stas-js/node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, + "node_modules/stas-js/node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/stas-js/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/stas-js/node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "license": "MIT", "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" + "node_modules/stas-js/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "license": "MIT", + "engines": { + "node": ">=4" + } }, "node_modules/stat-mode": { "version": "1.0.0", @@ -10838,6 +13935,30 @@ "dev": true, "license": "MIT" }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -10847,11 +13968,24 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -10882,7 +14016,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -10905,6 +14038,26 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -10957,7 +14110,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -10982,9 +14134,9 @@ } }, "node_modules/tar": { - "version": "7.5.16", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz", - "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==", + "version": "7.5.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz", + "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -11158,6 +14310,42 @@ "rimraf": "bin.js" } }, + "node_modules/test": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/test/-/test-0.6.0.tgz", + "integrity": "sha512-dfbzeAI09tjJM0TCxxzLzPnHAO8gXHN6KaZ6N9zBde2YOFXunHO69tetz/ai93XRsOOkEm8q4IE3MJB/RlszxA==", + "dependencies": { + "ansi-font": "0.0.2" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "license": "ISC", + "peer": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/tildify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", @@ -11167,6 +14355,19 @@ "node": ">=8" } }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tiny-async-pool": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz", @@ -11267,9 +14468,9 @@ } }, "node_modules/tmp": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", - "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, "license": "MIT", "engines": { @@ -11286,6 +14487,35 @@ "tmp": "^0.2.0" } }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-buffer/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -11307,6 +14537,12 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -11334,6 +14570,13 @@ "dev": true, "license": "0BSD" }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true, + "license": "MIT" + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -11346,6 +14589,16 @@ "node": "*" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", @@ -11373,11 +14626,25 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/typescript": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -11397,12 +14664,20 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4.0.0" } }, + "node_modules/unorm": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.4.1.tgz", + "integrity": "sha512-ZKduSr7qaZXq/R784+M3vudsguIahTX9aVtlfJdMaQj/yQw7A8LhkaS76/a6d0TzeBtiMDl+clvrLxq6HG/nAA==", + "license": "MIT or GPL-2.0", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -11413,10 +14688,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -11453,6 +14727,27 @@ "punycode": "^2.1.0" } }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/use-async-effect": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/use-async-effect/-/use-async-effect-2.2.7.tgz", @@ -11478,6 +14773,20 @@ "dev": true, "license": "(WTFPL OR MIT)" }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -11493,6 +14802,38 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "license": "ISC", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT", + "peer": true + }, "node_modules/value-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", @@ -11525,9 +14866,9 @@ } }, "node_modules/vite": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", - "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11637,21 +14978,38 @@ } } }, + "node_modules/vite-plugin-node-polyfills": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.28.0.tgz", + "integrity": "sha512-NXct/ci2ef4fRyCfTb8fk2HmR80Rv7icLd+cRH41TnUugDzdKMFKqFPpZYCFUInZMMem9bkLv5pkq02+7Xu7+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/plugin-inject": "^5.0.5", + "node-stdlib-browser": "^1.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/davidmyersdev" + }, + "peerDependencies": { + "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/vitest": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.6.tgz", - "integrity": "sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.6", - "@vitest/mocker": "3.2.6", - "@vitest/pretty-format": "^3.2.6", - "@vitest/runner": "3.2.6", - "@vitest/snapshot": "3.2.6", - "@vitest/spy": "3.2.6", - "@vitest/utils": "3.2.6", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", @@ -11681,8 +15039,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.6", - "@vitest/ui": "3.2.6", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, @@ -11710,6 +15068,13 @@ } } }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true, + "license": "MIT" + }, "node_modules/void-elements": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", @@ -11719,6 +15084,16 @@ "node": ">=0.10.0" } }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -11738,11 +15113,26 @@ "node": ">= 8" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -11754,6 +15144,28 @@ "node": ">= 8" } }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -11775,7 +15187,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -11814,6 +15225,20 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/ws": { "version": "8.21.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", @@ -11845,6 +15270,12 @@ "node": ">=8.0" } }, + "node_modules/xmlcreate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", + "integrity": "sha512-Mbe56Dvj00onbnSo9J0qj/XlY5bfN9KidsOnpd5tRCsR3ekB3hyyNU9fGrTdqNT5ZNvv4BsA2TcQlignsZyVcw==", + "license": "Apache-2.0" + }, "node_modules/xmlhttprequest-ssl": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", @@ -11853,11 +15284,20 @@ "node": ">=0.4.0" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -11867,14 +15307,12 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -11893,7 +15331,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -11914,7 +15351,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -11950,6 +15386,18 @@ "optional": true } } + }, + "vendor/dxs-bsv-token-sdk": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "@noble/curves": "^2.0.1", + "@noble/hashes": "^2.0.1", + "@noble/secp256k1": "^3.0.0", + "@scure/base": "^2.0.0", + "@scure/bip32": "^2.0.1", + "@scure/bip39": "^2.0.1" + } } } } diff --git a/package.json b/package.json index 7839bc4..890eb53 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "author": "BSV Association ", "license": "Apache-2.0", "scripts": { + "postinstall": "electron-builder install-app-deps", "dev": "concurrently \"npm run dev:vite\" \"npm run dev:electron\"", "dev:vite": "vite", "dev:electron": "tsc -p tsconfig.electron.json && cp electron/storage-loader.cjs electron/updater.cjs dist-electron/ && electron .", @@ -20,6 +21,10 @@ "package:linux": "electron-builder --linux", "lint:ci": "echo 'No linting'", "test": "vitest run --config vitest.config.electron.ts test/translations.test.ts", + "test:stas": "vitest run --config vitest.config.electron.ts test/stas", + "test:tokens": "vitest run --config vitest.config.electron.ts test/tokens", + "test:stas:db": "npm rebuild better-sqlite3 && vitest run --config vitest.config.electron.ts test/stas; npm run rebuild:electron", + "rebuild:electron": "electron-rebuild -f -o better-sqlite3 --build-from-source", "test:perf": "vitest run --config vitest.config.electron.ts" }, "dependencies": { @@ -28,7 +33,7 @@ "@bsv/btms-permission-module": "^1.1.0", "@bsv/btms-permission-module-ui": "^1.0.0", "@bsv/identity-react": "^1.1.14", - "@bsv/message-box-client": "^2.2.0", + "@bsv/message-box-client": "^2.2.1", "@bsv/sdk": "^2.1.6", "@bsv/uhrp-react": "^1.0.6", "@bsv/wallet-toolbox": "^2.3.2", @@ -39,10 +44,12 @@ "@mui/material": "^6.4.8", "@mui/styles": "^6.4.8", "better-sqlite3": "^12.8.0", + "bsv": "^1.5.6", "cors": "^2.8.6", "date-fns": "^4.1.0", "dompurify": "^3.4.11", "dotenv": "^17.2.4", + "dxs-bsv-token-sdk": "file:./vendor/dxs-bsv-token-sdk", "electron-log": "^5.4.3", "electron-updater": "^6.7.3", "express": "^4.21.2", @@ -61,6 +68,7 @@ "react-i18next": "^17.0.3", "react-router-dom": "^5.2.0", "react-toastify": "^11.0.5", + "stas-js": "^3.0.3", "use-async-effect": "^2.2.7" }, "devDependencies": { @@ -79,6 +87,7 @@ "typescript": "~5.6.2", "vite": "^6.3.6", "vite-plugin-electron": "^0.29.0", + "vite-plugin-node-polyfills": "^0.28.0", "vitest": "^3.0.0" }, "build": { diff --git a/src/global.d.ts b/src/global.d.ts index 0925d7f..a5701ad 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -57,6 +57,9 @@ export interface ElectronAPI { get: () => Promise; set: (config: any) => Promise; }; + stas: { + query: (identityKey: string, chain: 'main' | 'test', method: string, args: any[]) => Promise<{ success: boolean; result?: any; error?: string }>; + }; updates: { check: () => Promise<{ success: boolean; updateInfo?: any; error?: string }>; download: () => Promise<{ success: boolean; error?: string }>; diff --git a/src/lib/UserInterface.tsx b/src/lib/UserInterface.tsx index b20636f..33bbd0a 100644 --- a/src/lib/UserInterface.tsx +++ b/src/lib/UserInterface.tsx @@ -18,6 +18,7 @@ import PasswordHandler from './components/PasswordHandler' import RecoveryKeyHandler from './components/RecoveryKeyHandler' import FundingHandler from './components/FundingHandler' import SpendingAuthorizationHandler from './components/SpendingAuthorizationHandler' +import StasTransferPermissionHandler from './components/StasTransferPermissionHandler' import AuthRedirector from './navigation/AuthRedirector' import ThemedToastContainer from './components/ThemedToastContainer' import { WalletInterface } from '@bsv/sdk' @@ -73,6 +74,7 @@ const UserInterface: React.FC = ({ onWalletReady, nativeHand + diff --git a/src/lib/WalletContext.tsx b/src/lib/WalletContext.tsx index 3012efe..401e87e 100644 --- a/src/lib/WalletContext.tsx +++ b/src/lib/WalletContext.tsx @@ -29,10 +29,13 @@ import 'react-toastify/dist/ReactToastify.css' import { ADMIN_ORIGINATOR, DEFAULT_SETTINGS } from './config' import { UserContext } from './UserContext' import { useWalletService, getWalletService } from './hooks/useWalletService' +import type { StasServices } from './services/WalletService' import { buildPermissionModuleRegistry } from './permissionModules/registry' import type { PermissionModuleDefinition, PermissionPromptHandler } from './permissionModules/types' import type { GroupPermissionRequest, CounterpartyPermissionRequest } from './types/GroupedPermissions' import type { WalletProfile } from './types/WalletProfile' +import { setStasForHttpRoute, setStasTransferEnqueuer, setBsv21DiscoveryForHttpRoute, setPeerTokensForHttpRoute } from '../onWalletReady' +import type { StasTransferRequest } from './types/StasTransferRequest' import { RequestInterceptorWallet } from './RequestInterceptorWallet' import { updateRecentApp } from './pages/Dashboard/Apps/getApps' @@ -121,6 +124,8 @@ export interface WalletContextValue { * plumbing). App-originated requests must go through `managers.permissionsManager`. */ wallet?: WalletInterface; + /** STAS BRC-42 services + discovery loop (Tasks 3/4). */ + stas?: StasServices; settings: WalletSettings; updateSettings: (newSettings: WalletSettings) => Promise; network: 'mainnet' | 'testnet'; @@ -138,6 +143,14 @@ export interface WalletContextValue { certificateRequests: any[]; protocolRequests: any[]; spendingRequests: any[]; + /** + * Pending STAS transfer authorization requests from external apps + * calling `POST /stas/transfer`. Surfaced by `StasTransferPermissionHandler`. + * Resolves the awaiting route handler when the user clicks Approve/Deny. + */ + stasTransferRequests: StasTransferRequest[]; + /** Resolves the head of `stasTransferRequests` and removes it from the queue. */ + advanceStasTransferQueue: (approved: boolean) => void; groupPermissionRequests: GroupPermissionRequest[]; counterpartyPermissionRequests: CounterpartyPermissionRequest[]; startPactCooldownForCounterparty: (originator: string, counterparty: string) => void; @@ -200,6 +213,8 @@ export const WalletContext = createContext({ certificateRequests: [], protocolRequests: [], spendingRequests: [], + stasTransferRequests: [], + advanceStasTransferQueue: () => {}, groupPermissionRequests: [], counterpartyPermissionRequests: [], startPactCooldownForCounterparty: () => {}, @@ -338,6 +353,41 @@ export const WalletContextProvider: React.FC = ({ // ---- React adapter hook — provides all the context values ---- const walletServiceValues = useWalletService() + // ---- STAS transfer authorization queue (Apps API permission prompts) ---- + // External apps hitting POST /stas/transfer get gated by a user prompt + // here. enqueueStasTransferRequest is exposed to the HTTP route handler + // via setStasTransferEnqueuer (parallel to setStasForHttpRoute). + const [stasTransferRequests, setStasTransferRequests] = useState([]) + + const enqueueStasTransferRequest = useCallback( + ( + args: Omit + ): Promise => { + return new Promise((resolve) => { + const requestId = Math.random().toString(36).slice(2) + Date.now().toString(36) + setStasTransferRequests((q) => [ + ...q, + { ...args, requestId, resolve }, + ]) + }) + }, + [] + ) + + const advanceStasTransferQueue = useCallback((approved: boolean) => { + setStasTransferRequests((q) => { + if (q.length === 0) return q + const [head, ...rest] = q + try { head.resolve(approved) } catch { /* ignore */ } + return rest + }) + }, []) + + useEffect(() => { + setStasTransferEnqueuer(enqueueStasTransferRequest) + return () => setStasTransferEnqueuer(null) + }, [enqueueStasTransferRequest]) + // ---- onWalletReady integration (replaces Effect 14) ---- // This stays in React because it depends on onWalletReady prop and activeProfile const { managers, activeProfile } = walletServiceValues @@ -376,16 +426,79 @@ export const WalletContextProvider: React.FC = ({ } const interceptorWallet = new RequestInterceptorWallet(managers.permissionsManager, Utils.toBase64(activeProfile.id), updateRecentAppWrapper) - // onWalletReady registers IPC listener once, subsequent calls just swap wallet ref + // onWalletReady registers IPC listener once, subsequent calls just swap + // wallet ref. The STAS service bundle (for the Apps API routes + // /stas/list, /stas/tokens, /stas/transfer, /stas/receive-address, + // /stas/register-by-txid — Task 7a) is injected via a separate setter so + // the prop interface stays single-arg. onWalletReady(interceptorWallet) + const stas = walletServiceValues.stas + if (stas?.keyDeriver && stas.discovery && stas.transfer) { + setStasForHttpRoute({ + discovery: stas.discovery, + transfer: stas.transfer, + keyDeriver: stas.keyDeriver, + identityKey: stas.keyDeriver.identityKey, + chain: stas.keyDeriver.chain, + }) + } else { + setStasForHttpRoute(null) + } + + // Parallel injection for the BSV-21 register-by-txid demo fast-path. + // The primary discovery mechanism is bsv21Discovery.scan() — fired by + // the AssetsPage Refresh button — which queries the 1Sat overlay's + // per-address SSE stream and covers organic receive end-to-end. + setBsv21DiscoveryForHttpRoute(stas?.bsv21Discovery ?? null) + + // Peer-token routes (Phase B) — the standalone web page drives this + // wallet over /peerToken/*. The page references holdings by outpoint; + // source resolution + key derivation stay here behind the HTTP boundary. + if (stas?.peerTokens && stas.keyDeriver) { + setPeerTokensForHttpRoute({ + client: stas.peerTokens, + wallet: managers.permissionsManager, + identityKey: stas.keyDeriver.identityKey, + chain: stas.keyDeriver.chain, + originator: ADMIN_ORIGINATOR, + // TokenProtocolRegistry — powers the /dstas/transfer + /bsv-21/transfer + // legacy address-send routes (same adapters the Assets page Send uses). + tokens: stas.tokens, + }) + } else { + setPeerTokensForHttpRoute(null) + } // No cleanup — IPC listener is permanent, wallet ref is swapped not re-registered }, [managers?.permissionsManager, activeProfile?.id, onWalletReady]) + // STAS auto-scan: one shot when the raw wallet + STAS services first appear. + // The dev-only Dashboard panel exposes a manual re-scan. + useEffect(() => { + const stas = walletServiceValues.stas + const wallet = walletServiceValues.wallet + if (!wallet || !stas?.discovery) return + + let cancelled = false + ;(async () => { + try { + console.log('[STAS Discovery] auto-scan starting') + const result = await stas.discovery.scan() + if (cancelled) return + console.log('[STAS Discovery] auto-scan result:', result) + } catch (err) { + if (!cancelled) console.error('[STAS Discovery] auto-scan error:', err) + } + })() + return () => { cancelled = true } + }, [walletServiceValues.wallet, walletServiceValues.stas]) + // ---- Context value ---- const contextValue = useMemo(() => ({ ...walletServiceValues, - }), [walletServiceValues]) + stasTransferRequests, + advanceStasTransferQueue, + }), [walletServiceValues, stasTransferRequests, advanceStasTransferQueue]) return ( diff --git a/src/lib/components/StasTransferPermissionHandler/index.tsx b/src/lib/components/StasTransferPermissionHandler/index.tsx new file mode 100644 index 0000000..b6552e9 --- /dev/null +++ b/src/lib/components/StasTransferPermissionHandler/index.tsx @@ -0,0 +1,122 @@ +/** + * StasTransferPermissionHandler — modal that prompts the user to approve or + * deny a STAS transfer requested by an external app via POST /stas/transfer. + * + * Hooks into WalletContext's `stasTransferRequests` queue (populated by the + * HTTP route handler in onWalletReady.ts). Renders the head of the queue; + * Approve/Deny resolves the request and advances. While idle (empty queue) + * the component renders nothing. + */ + +import React, { useContext } from 'react' +import { + DialogContent, + DialogActions, + Button, + Stack, + Typography, + Box, + Divider, + Chip, +} from '@mui/material' +import SendIcon from '@mui/icons-material/Send' +import OpenInNewIcon from '@mui/icons-material/OpenInNew' +import CustomDialog from '../CustomDialog' +import { WalletContext } from '../../WalletContext' + +const StasTransferPermissionHandler: React.FC = () => { + const { stasTransferRequests, advanceStasTransferQueue } = useContext(WalletContext) + + if (!stasTransferRequests || stasTransferRequests.length === 0) { + return null + } + + const req = stasTransferRequests[0] + const symbolText = req.symbol ?? 'STAS' + + const onDeny = () => advanceStasTransferQueue(false) + const onApprove = () => advanceStasTransferQueue(true) + + return ( + + + + + Requested by + + {req.originator} + + + + + + + Sending + + + {req.satoshis.toLocaleString()} + + sats + + + {req.tokenId && ( + + token id {req.tokenId.substring(0, 12)}… + + )} + + + + From your wallet + + {req.brc42KeyId && } + + {req.outpoint.substring(0, 20)}… + + + + + + + + + Recipient + + {req.recipient} + + + + + Approving will sign and broadcast a transaction. BSV fees come from your + default basket. This action cannot be undone once the transaction + confirms on chain. + + + + + + + + + ) +} + +export default StasTransferPermissionHandler diff --git a/src/lib/components/Theme.tsx b/src/lib/components/Theme.tsx index cdb2dce..e5c1a82 100644 --- a/src/lib/components/Theme.tsx +++ b/src/lib/components/Theme.tsx @@ -225,6 +225,40 @@ export function AppThemeProvider({ children }: ThemeProps) { backgroundPosition: 'center', backgroundAttachment: 'fixed', }, + // App-wide themed scrollbars — replaces the default gray/white bars. + // Thin, rounded, translucent brand colour on a transparent track so + // they sit quietly on any surface and fade with the light/dark theme. + '*::-webkit-scrollbar': { + width: '10px', + height: '10px', + }, + '*::-webkit-scrollbar-track': { + backgroundColor: 'transparent', + }, + '*::-webkit-scrollbar-thumb': { + backgroundColor: + mode === 'light' ? 'rgba(27,54,93,0.30)' : 'rgba(255,255,255,0.22)', + borderRadius: '8px', + // Transparent border + padding-box clip = inset padding around the + // thumb, so it reads as a slim pill rather than a full-width bar. + border: '2px solid transparent', + backgroundClip: 'padding-box', + minHeight: '40px', + }, + '*::-webkit-scrollbar-thumb:hover': { + backgroundColor: + mode === 'light' ? 'rgba(27,54,93,0.50)' : 'rgba(255,255,255,0.42)', + }, + '*::-webkit-scrollbar-corner': { + backgroundColor: 'transparent', + }, + // Firefox (and the web-served build) — thin bars in matching colours. + '*': { + scrollbarWidth: 'thin', + scrollbarColor: `${ + mode === 'light' ? 'rgba(27,54,93,0.30)' : 'rgba(255,255,255,0.22)' + } transparent`, + }, }, }, MuiButton: { diff --git a/src/lib/constants/baskets.ts b/src/lib/constants/baskets.ts new file mode 100644 index 0000000..a74bc57 --- /dev/null +++ b/src/lib/constants/baskets.ts @@ -0,0 +1,33 @@ +/** + * Output basket names. + * + * Baskets are bare strings in wallet-toolbox's `output_baskets` table and were + * scattered as string literals across the codebase. New code should reference + * these constants. + */ + +/** wallet-toolbox's default basket for ordinary BSV outputs. */ +export const DEFAULT_BASKET = 'default'; + +/** + * Basket holding wallet-owned classic-STAS token UTXOs. Created lazily the + * first time a STAS output is internalized. + */ +export const STAS_BASKET = 'stas-tokens'; + +/** + * Basket holding wallet-owned DSTAS token UTXOs. Separated from STAS so the + * wallet-toolbox spend lifecycle (and any per-basket UTXO targeting) stays + * isolated per protocol. Created lazily by `internalizeAction`. + */ +export const DSTAS_BASKET = 'dstas-tokens'; + +/** + * Basket holding wallet-owned BSV-21 token UTXOs. Defined now so the + * token-protocol adapter for BSV-21 can route its registrations into a + * dedicated basket once that protocol lands. + */ +export const BSV21_BASKET = 'bsv-21-tokens'; + +/** All token-protocol baskets, in protocol-id order. */ +export const TOKEN_BASKETS = [STAS_BASKET, DSTAS_BASKET, BSV21_BASKET] as const; diff --git a/src/lib/hooks/useWalletService.ts b/src/lib/hooks/useWalletService.ts index d5db45e..c5e9ecf 100644 --- a/src/lib/hooks/useWalletService.ts +++ b/src/lib/hooks/useWalletService.ts @@ -359,6 +359,8 @@ export function useWalletService() { // Raw, unwrapped Wallet — for internal first-party use only. App-originated // requests must go through managers.permissionsManager. wallet: walletState.wallet, + // STAS BRC-42 services + discovery loop (Tasks 3/4). + stas: walletState.stas, // Settings settings: walletState.settings, updateSettings, diff --git a/src/lib/navigation/Menu.tsx b/src/lib/navigation/Menu.tsx index c4cc39c..cab5902 100644 --- a/src/lib/navigation/Menu.tsx +++ b/src/lib/navigation/Menu.tsx @@ -14,6 +14,8 @@ import { AccountBalanceWallet as PaymentsIcon, } from '@mui/icons-material' import SyncAltIcon from '@mui/icons-material/SyncAlt'; +import InventoryIcon from '@mui/icons-material/Inventory'; +import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; import VerifiedUserIcon from '@mui/icons-material/VerifiedUser' import GridViewIcon from '@mui/icons-material/GridView' import ReceiptLongIcon from '@mui/icons-material/ReceiptLong' @@ -738,7 +740,47 @@ export default function Menu({ menuOpen, setMenuOpen, menuRef }: MenuProps) { variant="body1" fontWeight={history.location.pathname === '/dashboard/payments' ? 600 : 400} > - {t('menu_payments')} + {t('menu_transfers', 'Transfers')} + + } + /> + + + navigation.push('/dashboard/assets')} + selected={history.location.pathname === '/dashboard/assets'} + sx={menuItemStyle(history.location.pathname === '/dashboard/assets')} + > + + + + + Assets + + } + /> + + + navigation.push('/dashboard/baskets')} + selected={history.location.pathname === '/dashboard/baskets'} + sx={menuItemStyle(history.location.pathname === '/dashboard/baskets')} + > + + + + + Baskets } /> diff --git a/src/lib/pages/Dashboard/AssetsPage.tsx b/src/lib/pages/Dashboard/AssetsPage.tsx new file mode 100644 index 0000000..7fde5dc --- /dev/null +++ b/src/lib/pages/Dashboard/AssetsPage.tsx @@ -0,0 +1,1740 @@ +/** + * AssetsPage — production-facing wallet view for STAS holdings. + * + * Replaces the dev panel's "My STAS" surface with a token-grouped layout: + * one card per (symbol, tokenId) bucket, expandable to show the underlying + * UTXOs, with explicit Send and Receive flows. + * + * Reads + writes through the same internal services the Apps API exposes + * externally. This page is the user-facing surface for token holdings. + */ + +import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react' +import { + Box, + Button, + Card, + CardContent, + Chip, + CircularProgress, + Collapse, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Divider, + IconButton, + Stack, + TextField, + Tooltip, + Typography, +} from '@mui/material' +import RefreshIcon from '@mui/icons-material/Refresh' +import ContentCopyIcon from '@mui/icons-material/ContentCopy' +import CheckIcon from '@mui/icons-material/Check' +import ExpandMoreIcon from '@mui/icons-material/ExpandMore' +import ExpandLessIcon from '@mui/icons-material/ExpandLess' +import SendIcon from '@mui/icons-material/Send' +import OpenInNewIcon from '@mui/icons-material/OpenInNew' +import TokenIcon from '@mui/icons-material/Token' +import VerifiedIcon from '@mui/icons-material/Verified' +import GppBadIcon from '@mui/icons-material/GppBad' +import HelpOutlineIcon from '@mui/icons-material/HelpOutline' +import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline' +import SearchIcon from '@mui/icons-material/Search' +import { QRCodeSVG } from 'qrcode.react' +import { Address, fromHex } from 'dxs-bsv-token-sdk/bsv' +import { WalletContext } from '../../WalletContext' +import { stasQuery } from '../../services/stas' +import type { TokenProtocolId, Bsv21SendExtras } from '../../services/tokens' +import { parseBsv21LockingScript } from '../../services/tokens' +import { BSV21_BASKET } from '../../constants/baskets' +import { + TokenVerificationService, + aggregateBadge, + type OutpointVerification, + type VerificationBadge, +} from '../../services/tokens/TokenVerificationService' + +interface OutputView { + outpoint: string + txid: string + vout: number + satoshis: number + spendable: boolean + tokenId: string + symbol: string | null + name: string | null + brc42KeyId: string | null + ownerFieldHash160: string + ownerAddress: string + scriptHex: string | null + frozen: boolean + confiscated: boolean + /** Set when wallet-toolbox marked this row as spent (consumed by a tx). */ + spentBy: string | null + /** ISO timestamp from stas_outputs.createdAt — used for activity ordering. */ + createdAt: string | null + /** Which token protocol this UTXO belongs to. */ + protocol: TokenProtocolId + /** + * Raw token amount (stringified bigint). For STAS/DSTAS this is `satoshis` + * since their satoshisPerToken=1. For BSV-21 it's the `amt` field parsed + * from the basket tag, which may be much larger than the 1-sat output. + */ + tokenAmount: string + /** Decimal precision for display. Zero for STAS/DSTAS. */ + decimals: number + /** Optional icon URL/outpoint for BSV-21. */ + icon: string | null + /** Back-to-Genesis verdict for this outpoint; undefined until verified. */ + verification?: OutpointVerification +} + +interface TokenGroup { + groupKey: string + symbol: string + name: string | null + tokenIds: Set + outputCount: number + totalSatoshis: number + spendableSatoshis: number + outputs: OutputView[] + /** Protocol this group represents — distinct protocols never merge. */ + protocol: TokenProtocolId + /** + * Resolved genesis outpoints across this group's UTXOs. For classic STAS the + * tokenId is only the issuer PKH (shared by every token that issuer minted), + * so the genesis is the real identity — a group keyed on it can't be spoofed + * by a same-symbol relabel. Empty until B2G verification resolves. + */ + genesisSet: Set + /** Card-level provenance rollup (worst outpoint verdict wins). */ + badge: VerificationBadge + /** Sum of `tokenAmount` across outputs in this group (stringified bigint). */ + tokenAmount: string + /** Same, but only for spendable outputs. */ + spendableTokenAmount: string + /** Decimal precision for display, taken from the first output. */ + decimals: number +} + +/** + * Parse a stringified bigint defensively. BSV-21 `amt` tags come from + * arbitrary minter input and can be anything — non-numeric values used + * to crash the entire AssetsPage at the `BigInt()` call site. Return + * `0n` for anything that doesn't parse so the row still renders. + */ +function safeBigInt(s: string | null | undefined): bigint { + if (!s) return 0n + try { + return BigInt(s) + } catch { + return 0n + } +} + +function groupByToken(outputs: OutputView[]): TokenGroup[] { + const byKey = new Map() + for (const o of outputs) { + // Identity key. Prefer the resolved genesis outpoint: for classic STAS the + // tokenId is just the issuer PKH, so two genuinely different tokens from one + // issuer share it — and a counterfeit deliberately reuses it. Keying on + // genesis keeps EXSTAS2 (or a forgery) from collapsing into EXSTAS1's card. + // Falls back to (protocol, symbol, tokenId) until verification resolves. + const genesis = o.verification?.genesis + const key = genesis + ? `${o.protocol}::genesis::${genesis}` + : o.tokenId + ? `${o.protocol}::${o.symbol ?? '?'}::${o.tokenId}` + : `${o.protocol}::${o.symbol ?? 'unknown'}` + let g = byKey.get(key) + if (!g) { + g = { + groupKey: key, + symbol: o.symbol ?? 'unknown', + name: o.name, + tokenIds: new Set(), + outputCount: 0, + totalSatoshis: 0, + spendableSatoshis: 0, + outputs: [], + protocol: o.protocol, + tokenAmount: '0', + spendableTokenAmount: '0', + decimals: o.decimals, + genesisSet: new Set(), + badge: 'unknown', + } + byKey.set(key, g) + } + g.outputCount += 1 + g.totalSatoshis += o.satoshis + if (o.spendable) g.spendableSatoshis += o.satoshis + // BigInt sums for token amounts — BSV-21 values can exceed JS's safe-int. + // `safeBigInt` defends against malformed amt tags (e.g. someone minted + // BSV-21 with `amt: "lorem ipsum"`); we keep the row visible at 0. + g.tokenAmount = (safeBigInt(g.tokenAmount) + safeBigInt(o.tokenAmount)).toString() + if (o.spendable) { + g.spendableTokenAmount = (safeBigInt(g.spendableTokenAmount) + safeBigInt(o.tokenAmount)).toString() + } + if (o.tokenId) g.tokenIds.add(o.tokenId) + if (genesis) g.genesisSet.add(genesis) + if (!g.name && o.name) g.name = o.name + g.outputs.push(o) + } + // Compute each card's provenance rollup from its outputs' verdicts. + for (const g of byKey.values()) { + g.badge = aggregateBadge( + g.outputs.map((o) => o.verification).filter((v): v is OutpointVerification => !!v) + ) + } + // Sort by spendable-amount descending. BigInt-safe comparator. + return Array.from(byKey.values()).sort((a, b) => { + const av = safeBigInt(a.tokenAmount) + const bv = safeBigInt(b.tokenAmount) + return av < bv ? 1 : av > bv ? -1 : 0 + }) +} + +/** + * Format a raw token amount (stringified bigint) with the protocol's + * decimal precision. `dec=0` is the STAS/DSTAS case — render the integer + * with locale separators. `dec>0` is BSV-21 — divide by 10^dec and trim + * trailing zeros so 1500000 with dec=6 reads as "1.5", not "1.500000". + */ +function formatTokenAmount(amount: string, dec: number): string { + // Defensive: malformed `amt` tags (non-numeric strings, e.g. when a mint + // call accidentally passed "lorem ipsum") show as `?` rather than crashing. + let n: bigint + try { n = BigInt(amount || '0') } catch { return amount ? `? (${amount})` : '0' } + if (dec === 0) return n.toLocaleString() + const divisor = 10n ** BigInt(dec) + const integer = n / divisor + const fraction = n % divisor + const intStr = integer.toLocaleString() + const fracPadded = fraction.toString().padStart(dec, '0') + const fracTrimmed = fracPadded.replace(/0+$/, '') + return fracTrimmed ? `${intStr}.${fracTrimmed}` : intStr +} + +/** Extract tag values like `id:abc` → `abc`. Returns undefined if absent. */ +function tagValue(tags: string[] | undefined, prefix: string): string | undefined { + if (!tags) return undefined + for (const t of tags) { + if (t.startsWith(prefix + ':')) return t.slice(prefix.length + 1) + } + return undefined +} + +/** Parse customInstructions JSON safely; returns null if malformed. */ +function parseCustomInstructions(s: string | null | undefined): any | null { + if (!s) return null + try { return JSON.parse(s) } catch { return null } +} + +/** + * Shape a wallet-toolbox `listOutputs` row from the `bsv-21-tokens` basket + * into the unified `OutputView`. Token-level metadata (id, amt, dec, sym, + * icon) lives on basket TAGS per 1sat-toolbox convention; BRC-42 unlock + * context lives in customInstructions. + */ +function bsv21RowToView(o: any): OutputView { + const tags: string[] | undefined = o.tags + const tokenId = tagValue(tags, 'id') ?? '' + const amt = tagValue(tags, 'amt') ?? '0' + const decStr = tagValue(tags, 'dec') + const decimals = decStr ? Number(decStr) : 0 + const sym = tagValue(tags, 'sym') ?? null + const icon = tagValue(tags, 'icon') ?? null + + const ci = parseCustomInstructions(o.customInstructions) + const brc42KeyId = (ci && typeof ci.keyID === 'string') ? ci.keyID : null + const ownerAddrFromCI = (ci && typeof ci.ownerAddress === 'string') ? ci.ownerAddress : null + + // Locking script may include the full ord envelope; parse to recover the + // P2PKH owner hash160. Fall back to customInstructions for the address. + const scriptHex: string | null = o.lockingScript ?? null + const parsed = scriptHex ? parseBsv21LockingScript(scriptHex) : null + + const [txid, voutStr] = (o.outpoint ?? '.').split('.') + const vout = Number(voutStr) + + return { + outpoint: o.outpoint, + txid, + vout: Number.isNaN(vout) ? 0 : vout, + satoshis: o.satoshis ?? 1, + spendable: !!o.spendable, + tokenId, + symbol: sym, + name: null, + brc42KeyId, + ownerFieldHash160: parsed?.ownerHash160 ?? '', + ownerAddress: ownerAddrFromCI ?? (parsed ? hash160ToAddress(parsed.ownerHash160) : ''), + scriptHex, + frozen: false, + confiscated: false, + spentBy: null, + createdAt: o.createdAt ?? null, + protocol: 'bsv-21', + tokenAmount: amt, + decimals, + icon, + } +} + +/** Display label for the protocol badge chip. */ +function protocolLabel(p: TokenProtocolId): string { + switch (p) { + case 'stas': return 'STAS' + case 'dstas': return 'DSTAS' + case 'bsv-21': return 'BSV-21' + } +} + +/** + * Back-to-Genesis provenance chip for a token card. + * + * - verified → green: every UTXO traced to a genesis mint. + * - counterfeit → red: at least one UTXO failed a provenance rule (does not + * descend from a real mint). The dangerous case — the reason is shown. + * - unknown → grey. Distinguish "still checking" (a UTXO not yet verified) + * from "couldn't decide" (B2G returned undetermined — a deep chain or an + * unavailable source). Neither is a counterfeit; both fail safe. + */ +function TokenVerificationChip({ group, onReverify }: { group: TokenGroup; onReverify?: () => void }) { + const pending = group.outputs.some((o) => !o.verification) + if (pending && group.badge !== 'counterfeit') { + // Mid-flight — no re-verify affordance while a check is already running. + return ( + } + label='Verifying…' + /> + ) + } + // A settled badge is never re-checked automatically. Clicking it is the + // explicit re-verify — stop the click from also toggling the card's expand. + const reverify = onReverify + ? (e: React.MouseEvent) => { + e.stopPropagation() + onReverify() + } + : undefined + const hint = reverify ? ' · click to re-verify' : '' + + if (group.badge === 'verified') { + const genesis = [...group.genesisSet][0] + return ( + + } label='Verified' onClick={reverify} clickable={!!reverify} /> + + ) + } + if (group.badge === 'counterfeit') { + const reason = group.outputs.find((o) => o.verification?.result === 'not-authentic')?.verification?.reason + return ( + + } label='Counterfeit' onClick={reverify} clickable={!!reverify} /> + + ) + } + return ( + + } label='Unverified' onClick={reverify} clickable={!!reverify} /> + + ) +} + +function hash160ToAddress(hash160Hex: string): string { + return new (Address as any)(fromHex(hash160Hex)).Value as string +} + +/** + * Collapse a stored brc42KeyId into a compact ownership label. Self-owned + * outputs carry a clean `recv N`; a peer-received (BRC-29) output stores the + * full `brc29|prefix|suffix|senderIdentityKey` derivation — far too long for a + * chip — so we show a short "received" badge with the full string on hover. + */ +function ownershipLabel( + brc42KeyId: string | null +): { short: string; full: string; peer: boolean } | null { + if (!brc42KeyId) return null + if (brc42KeyId.startsWith('brc29|')) { + const sender = brc42KeyId.split('|')[3] ?? '' + return { + short: 'received', + full: `Peer-received (BRC-29)${sender ? ` · sender ${sender.slice(0, 16)}…` : ''}`, + peer: true, + } + } + return { short: brc42KeyId, full: `Self-owned · ${brc42KeyId}`, peer: false } +} + +export default function AssetsPage() { + const { wallet, stas } = useContext(WalletContext) + + const [holdings, setHoldings] = useState([]) + const [sentHoldings, setSentHoldings] = useState([]) + // Back-to-Genesis verdicts, keyed by `${txid}_${vout}`. Filled in the + // background after holdings load; merged into the grouped view as they arrive. + const [verifications, setVerifications] = useState>(new Map()) + const [activityExpanded, setActivityExpanded] = useState(false) + const [loading, setLoading] = useState(false) + const [scanning, setScanning] = useState(false) + // WOC has no bulk token endpoint, so a scan is one throttled request per + // derived address — tens of seconds on a grown wallet. Show where it is. + const [scanProgress, setScanProgress] = useState(null) + const [scanStats, setScanStats] = useState< + | { + rows: { + label: string + found: number + registered: number + known: number + errors: number + errorMessages: string[] + }[] + failed?: string + } + | null + >(null) + const [error, setError] = useState(null) + const [expanded, setExpanded] = useState>(new Set()) + + const [receiveAddress, setReceiveAddress] = useState(null) + const [receiveLabel, setReceiveLabel] = useState(null) + const [generatingReceive, setGeneratingReceive] = useState(false) + const [receiveCopied, setReceiveCopied] = useState(false) + const [receiveError, setReceiveError] = useState(null) + /** Which protocol the next "Generate new address" derives under. */ + const [receiveProtocol, setReceiveProtocol] = useState('stas') + + const [sendTarget, setSendTarget] = useState(null) + const [sendRecipient, setSendRecipient] = useState('') + /** + * Amount to send. Empty string = full UTXO. For STAS/DSTAS it's an integer + * number of token satoshis (≤ source satoshis); for BSV-21 it's raw token + * units (pre-decimals). A partial amount SPLITS: the recipient gets `amount` + * and the remainder returns to the sender as token-change. + */ + const [sendAmount, setSendAmount] = useState('') + const [sending, setSending] = useState(false) + const [sendResult, setSendResult] = useState<{ ok: boolean; message: string } | null>(null) + + // BSV-21 orphan recovery — pre-PR-32 sends produced change outputs + // without basket+customInstructions+tags, so they don't show up in + // the holdings list. This dialog lets a user re-internalize one by + // outpoint after the fix shipped. + const [recoverDialogOpen, setRecoverDialogOpen] = useState(false) + const [recoverTxid, setRecoverTxid] = useState('') + const [recoverVout, setRecoverVout] = useState('') + const [recovering, setRecovering] = useState(false) + const [recoverResult, setRecoverResult] = useState<{ ok: boolean; message: string } | null>(null) + + // Filter state — applied to groups by symbol, name, or tokenId. + const [filter, setFilter] = useState('') + + const identityKey = stas?.keyDeriver?.identityKey + const chain = stas?.keyDeriver?.chain + + // One verification service per chain — it owns the per-outpoint cache, so a + // re-open of the page verifies only newly-arrived tokens. Reuses the + // wallet-wide BackToGenesisClient when present (avoids a duplicate instance). + const b2gClient = stas?.backToGenesis + const verifier = useMemo( + () => + new TokenVerificationService({ + chain: (chain as 'main' | 'test') ?? 'main', + client: b2gClient, + }), + [chain, b2gClient] + ) + + // Verify a set of holdings and fold each verdict into state. Fail-safe: the + // service never throws, so a WOC hiccup just leaves those outpoints `unknown`. + // + // A settled verdict is FINAL: an outpoint's provenance can't change (a reorg + // aside), so once we know it we never call the endpoint for it again — not on + // the next load, not on Refresh. Only outpoints with no settled verdict yet + // are verified. Pass `{ force: true }` to deliberately re-check (the badge's + // click handler does this). + // + // Durable store is the wallet DB (`token_verifications`, migration 0004): we + // seed from it so a re-opened wallet shows badges with zero network, and only + // freshly obtained verdicts are written back. + const verifyHoldings = useCallback( + async (rows: OutputView[], opts: { force?: boolean } = {}) => { + if (!identityKey || !chain) return + const force = opts.force === true + + // 1. Seed from the DB — instant badges, and the record of what's already + // settled so we can skip it below. + const settled = new Set() + try { + const persisted: any[] = (await stasQuery(identityKey, chain, 'listTokenVerifications', [])) ?? [] + const byOutpoint = new Map(persisted.map((r) => [`${r.txid}_${r.vout}`, r])) + const seed: Array<{ output: { txid: string; vout: number; protocol: TokenProtocolId }; verdict: OutpointVerification }> = [] + const seededState = new Map() + for (const o of rows) { + const r = byOutpoint.get(`${o.txid}_${o.vout}`) + if (!r) continue + const verdict: OutpointVerification = { + outpoint: `${o.txid}_${o.vout}`, + result: r.result, + reason: r.reason ?? undefined, + genesis: r.genesis ?? undefined, + genesisDepth: r.genesisDepth ?? undefined, + } + seed.push({ output: { txid: o.txid, vout: o.vout, protocol: o.protocol }, verdict }) + seededState.set(verdict.outpoint, verdict) + settled.add(verdict.outpoint) // DB only ever holds settled verdicts + } + verifier.seed(seed) + if (seededState.size) setVerifications((prev) => new Map([...prev, ...seededState])) + } catch { + /* DB seed is best-effort; verification below still runs from scratch */ + } + + // 2. Verify ONLY the outpoints without a settled verdict — from the DB + // above, or from a verdict reached earlier this session. Each verified + // result is persisted; already-settled ones are neither re-fetched nor + // re-written. `force` overrides the skip for an explicit re-check. + for (const o of rows) { + const op = `${o.txid}_${o.vout}` + if (!force) { + if (settled.has(op)) continue + const cached = verifier.peek(o) + if (cached && cached.result !== 'undetermined') continue + } + const v = await verifier.verifyOutput(o, { force }) + setVerifications((prev) => { + const next = new Map(prev) + next.set(v.outpoint, v) + return next + }) + if (v.result !== 'undetermined') { + try { + await stasQuery(identityKey, chain, 'upsertTokenVerification', [ + { + txid: o.txid, + vout: o.vout, + protocol: o.protocol, + result: v.result, + genesis: v.genesis ?? null, + genesisDepth: v.genesisDepth ?? null, + reason: v.reason ?? null, + verifiedAt: new Date().toISOString(), + }, + ]) + } catch { + /* persistence is best-effort; the badge already rendered from state */ + } + } + } + }, + [verifier, identityKey, chain] + ) + + const loadHoldings = useCallback(async () => { + if (!identityKey || !chain) return + setLoading(true) + setError(null) + try { + // Fetch both current (default) and the full set (includeSpent: true). + // The full set lets us build the Activity feed alongside the live holdings. + const [outputsRaw, allRaw, tokensRaw]: [any[], any[], any[]] = await Promise.all([ + stasQuery(identityKey, chain, 'listStasOutputs', []), + stasQuery(identityKey, chain, 'listStasOutputs', [{ includeSpent: true }]), + stasQuery(identityKey, chain, 'listStasTokens', []), + ]) + const tokenMap: Record = {} + for (const t of tokensRaw ?? []) tokenMap[t.tokenId] = t + + const toView = (o: any): OutputView => { + const sats = o.outputSatoshis ?? o.tokenSatoshis ?? 0 + return { + outpoint: `${o.txid}.${o.vout}`, + txid: o.txid, + vout: o.vout, + satoshis: sats, + spendable: !!o.spendable, + tokenId: o.tokenId ?? '', + symbol: tokenMap[o.tokenId]?.symbol ?? o.symbol ?? null, + name: tokenMap[o.tokenId]?.name ?? null, + brc42KeyId: o.brc42KeyId ?? null, + ownerFieldHash160: o.ownerFieldHash160, + ownerAddress: hash160ToAddress(o.ownerFieldHash160), + scriptHex: o.lockingScript ?? null, + frozen: !!o.frozen, + confiscated: !!o.confiscated, + spentBy: o.spentBy ?? null, + createdAt: o.createdAt ?? null, + // Stamped by migration 0002; legacy rows default to 'stas'. + protocol: (o.protocol as TokenProtocolId) ?? 'stas', + // STAS/DSTAS: satoshisPerToken=1, so tokenAmount = satoshis. + tokenAmount: String(sats), + decimals: 0, + icon: null, + } + } + + // STAS / DSTAS holdings. + const stasHoldings = (outputsRaw ?? []).map(toView) + + // BSV-21 holdings — second data source. Goes through the BRC-100 + // listOutputs surface so tags (id/amt/dec/sym/icon) come back with + // each row. The IPC basket query doesn't expose tags. + let bsv21Holdings: OutputView[] = [] + if (wallet) { + try { + const res: any = await wallet.listOutputs({ + basket: BSV21_BASKET, + includeTags: true, + // includeCustomInstructions is load-bearing: bsv21RowToView reads + // brc42KeyId / ownerAddress out of customInstructions, and the + // Send button gate disables on `!brc42KeyId`. Without this flag + // every BSV-21 row renders unsendable. + includeCustomInstructions: true, + include: 'locking scripts', + limit: 10000, + } as any) + const rows: any[] = res?.outputs ?? [] + bsv21Holdings = rows.map(bsv21RowToView) + } catch { + /* BSV-21 holdings just won't surface if the basket is missing */ + } + } + + const combined = [...stasHoldings, ...bsv21Holdings] + setHoldings(combined) + // Kick off Back-to-Genesis verification in the background — the card + // badges fill in as verdicts arrive; holdings render immediately. + void verifyHoldings(combined) + + // Sent = anything from the "all" set that has spentBy set (and isn't in + // the current set). Newest first by createdAt (best proxy we have). + const sent = (allRaw ?? []) + .filter((o: any) => o?.spentBy) + .map(toView) + .sort((a, b) => (b.createdAt ?? '').localeCompare(a.createdAt ?? '')) + setSentHoldings(sent) + } catch (e) { + setError(e instanceof Error ? e.message : String(e)) + } finally { + setLoading(false) + } + }, [identityKey, chain, wallet, verifyHoldings]) + + // Wraps loadHoldings with a real Bitails discovery scan first — picks up + // STAS that arrived after the wallet's startup auto-scan. Without this the + // page would only ever surface what's already in the local satellite, and + // freshly received UTXOs stay invisible until the user manually scans from + // the dev panel. + const handleScan = useCallback(async () => { + if (!stas?.discovery) { + // No discovery service available — fall back to local refresh. + await loadHoldings() + return + } + setScanning(true) + setScanStats(null) + setScanProgress(null) + const PHASE_LABEL: Record = { + stas: 'STAS', + dstas: 'DSTAS', + bsv21: 'BSV-21', + register: 'registering', + } + const onProgress = (p: { phase: string; done: number; total: number }) => + setScanProgress(`${PHASE_LABEL[p.phase] ?? p.phase} ${p.done + 1}/${p.total}`) + try { + // Run STAS / DSTAS first (one merged WOC scan), then BSV-21. Sequential + // so error attribution stays clear in the summary chips below. + // A scan error carries the reason that made a candidate unusable. Keep it + // — a bare count tells a tester nothing about what to report back. + const describe = (errs?: { outpoint?: string; message: string }[]): string[] => + (errs ?? []).map((e) => (e.outpoint ? `${e.outpoint}: ${e.message}` : e.message)) + + const stasRes = await stas.discovery.scan({ onProgress }) + const stasErrors = describe(stasRes.errors) + if (stasErrors.length > 0) console.warn('[scan] STAS/DSTAS errors:', stasErrors) + const rows = [ + { + label: 'STAS / DSTAS', + found: stasRes.candidates ?? 0, + registered: stasRes.registered ?? 0, + known: stasRes.skippedAlreadyKnown ?? 0, + errors: stasErrors.length, + errorMessages: stasErrors, + }, + ] + let failed: string | undefined + if (stas.bsv21Discovery) { + try { + const bsv21Res = await stas.bsv21Discovery.scan({ onProgress }) + const bsv21Errors = describe(bsv21Res.errors) + if (bsv21Errors.length > 0) console.warn('[scan] BSV-21 errors:', bsv21Errors) + rows.push({ + label: 'BSV-21', + found: bsv21Res.candidates ?? 0, + registered: bsv21Res.registered ?? 0, + known: bsv21Res.skippedAlreadyKnown ?? 0, + errors: bsv21Errors.length, + errorMessages: bsv21Errors, + }) + } catch (e) { + failed = `BSV-21 scan failed: ${e instanceof Error ? e.message : String(e)}` + } + } + setScanStats({ rows, failed }) + } catch (e) { + setScanStats({ rows: [], failed: `Scan failed: ${e instanceof Error ? e.message : String(e)}` }) + } finally { + setScanning(false) + setScanProgress(null) + } + await loadHoldings() + }, [stas?.discovery, stas?.bsv21Discovery, loadHoldings]) + + useEffect(() => { + if (!stas?.keyDeriver) return + // First load: local-only (fast paint) plus a real scan in the background + // so freshly arrived STAS show up without the user pressing anything. + loadHoldings() + handleScan() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [stas?.keyDeriver]) + + const handleRecoverOrphan = useCallback(async () => { + if (!stas?.bsv21Discovery || !identityKey || !chain) { + setRecoverResult({ ok: false, message: 'discovery service or identity not ready' }) + return + } + const txid = recoverTxid.trim().toLowerCase() + const voutNum = Number(recoverVout.trim()) + if (!/^[0-9a-f]{64}$/.test(txid)) { + setRecoverResult({ ok: false, message: 'txid must be 64 hex chars' }) + return + } + if (!Number.isInteger(voutNum) || voutNum < 0) { + setRecoverResult({ ok: false, message: 'vout must be a non-negative integer' }) + return + } + setRecovering(true) + setRecoverResult(null) + try { + const res = await (stas.bsv21Discovery as any).recoverByOutpoint({ + txid, + vout: voutNum, + identityKey, + chain, + }) + if (res.ok) { + if (res.alreadyHadBasket) { + setRecoverResult({ ok: true, message: `Already recovered (outputId ${res.outputId}). No-op.` }) + } else { + setRecoverResult({ + ok: true, + message: `Recovered outputId ${res.outputId} (token ${res.tokenId?.slice(0, 12)}…, key recv ${res.keyIndex})`, + }) + } + await loadHoldings() + } else { + setRecoverResult({ ok: false, message: res.reason ?? 'recovery failed' }) + } + } catch (e) { + setRecoverResult({ ok: false, message: e instanceof Error ? e.message : String(e) }) + } finally { + setRecovering(false) + } + }, [stas?.bsv21Discovery, identityKey, chain, recoverTxid, recoverVout, loadHoldings]) + + // Fold the latest B2G verdicts into each holding before grouping, so the + // grouping can key on genesis and the cards can badge. Kept as a derivation + // (not baked into `holdings`) so a verdict update re-groups without a reload. + const verifiedHoldings = useMemo( + () => + holdings.map((o) => { + const v = verifications.get(`${o.txid}_${o.vout}`) + return v ? { ...o, verification: v } : o + }), + [holdings, verifications] + ) + + const allGroups = useMemo(() => groupByToken(verifiedHoldings), [verifiedHoldings]) + + const groups = useMemo(() => { + const needle = filter.trim().toLowerCase() + if (!needle) return allGroups + return allGroups.filter((g) => { + if (g.symbol.toLowerCase().includes(needle)) return true + if (g.name && g.name.toLowerCase().includes(needle)) return true + for (const id of g.tokenIds) { + if (id.toLowerCase().includes(needle)) return true + } + return false + }) + }, [allGroups, filter]) + + const totalSats = useMemo(() => holdings.reduce((s, o) => s + o.satoshis, 0), [holdings]) + + const handleGenerateReceive = async () => { + if (!stas) return + setGeneratingReceive(true) + setReceiveError(null) + setReceiveCopied(false) + try { + // Dispatch to the protocol-specific deriver. BSV-21 lives in its own + // BRC-42 keyspace so the receive-counter never collides with STAS. + const deriver = + receiveProtocol === 'bsv-21' ? stas.bsv21KeyDeriver : stas.keyDeriver + if (!deriver) throw new Error(`no deriver for protocol ${receiveProtocol}`) + const row = await deriver.createNextReceiveContext() + setReceiveAddress(hash160ToAddress(row.ownerFieldHash160)) + setReceiveLabel(`${protocolLabel(receiveProtocol)} · ${row.keyId}`) + } catch (e) { + setReceiveError(e instanceof Error ? e.message : String(e)) + } finally { + setGeneratingReceive(false) + } + } + + const handleCopyReceive = async () => { + if (!receiveAddress) return + try { + await navigator.clipboard.writeText(receiveAddress) + setReceiveCopied(true) + setTimeout(() => setReceiveCopied(false), 1500) + } catch { + /* ignore */ + } + } + + const openSend = (o: OutputView) => { + setSendTarget(o) + setSendRecipient('') + // Pre-fill the amount with the full balance so the default is "send + // everything" (editable down to split). STAS/DSTAS are satoshi-denominated; + // BSV-21 uses raw token units. + setSendAmount(o.protocol === 'bsv-21' ? o.tokenAmount : String(o.satoshis)) + setSendResult(null) + } + + const handleSendConfirm = async () => { + if (!sendTarget || !stas?.tokens || !sendTarget.scriptHex || !sendTarget.brc42KeyId) return + const adapter = stas.tokens.getById(sendTarget.protocol) + if (!adapter || !adapter.transferSupported || !adapter.transfer) { + setSendResult({ + ok: false, + message: `Send is not yet available for ${protocolLabel(sendTarget.protocol)} in this wallet.`, + }) + return + } + setSending(true) + setSendResult(null) + try { + // Build the cross-protocol args; per-protocol amount handling below. + const baseArgs = { + source: { + txid: sendTarget.txid, + vout: sendTarget.vout, + scriptHex: sendTarget.scriptHex, + satoshis: sendTarget.satoshis, + brc42KeyId: sendTarget.brc42KeyId, + }, + recipientAddress: sendRecipient.trim(), + } + let args: any = baseArgs + let isPartial = false + + if (sendTarget.protocol === 'bsv-21') { + // BSV-21 amount is a raw bigint string; validated here at the UI + // boundary so the transfer service can trust its input. + const raw = sendAmount.trim() || sendTarget.tokenAmount + if (!/^\d+$/.test(raw)) { + setSendResult({ ok: false, message: 'Amount must be a non-negative integer (raw token units).' }) + setSending(false) + return + } + let sendAmtBig: bigint + let sourceAmtBig: bigint + try { + sendAmtBig = BigInt(raw) + sourceAmtBig = BigInt(sendTarget.tokenAmount) + } catch { + setSendResult({ ok: false, message: 'Could not parse amount as a bigint.' }) + setSending(false) + return + } + if (sendAmtBig <= 0n) { + setSendResult({ ok: false, message: 'Amount must be > 0.' }) + setSending(false) + return + } + if (sendAmtBig > sourceAmtBig) { + setSendResult({ ok: false, message: `Amount exceeds UTXO balance (${formatTokenAmount(sendTarget.tokenAmount, sendTarget.decimals)}).` }) + setSending(false) + return + } + isPartial = sendAmtBig < sourceAmtBig + // BSV21TransferService builds a token-change output when sendAmt < sourceAmt. + const extras: Bsv21SendExtras = { + tokenId: sendTarget.tokenId, + sourceAmt: sendTarget.tokenAmount, + amount: sendAmtBig.toString(), + dec: sendTarget.decimals || undefined, + sym: sendTarget.symbol ?? undefined, + icon: sendTarget.icon ?? undefined, + } + args = { ...baseArgs, ...extras } + } else { + // STAS / DSTAS — satoshi-denominated. A blank amount (or the full + // balance) sends the whole UTXO; a smaller amount SPLITS, and we derive + // a self-owned change receive context so the remainder stays spendable + // (mirrors the peer settlement adapter). + const raw = sendAmount.trim() + if (raw) { + if (!/^\d+$/.test(raw)) { + setSendResult({ ok: false, message: 'Amount must be a positive integer (token sats).' }) + setSending(false) + return + } + const amt = Number(raw) + if (amt <= 0 || amt > sendTarget.satoshis) { + setSendResult({ ok: false, message: `Amount must be between 1 and ${sendTarget.satoshis.toLocaleString()} sats.` }) + setSending(false) + return + } + if (amt < sendTarget.satoshis) { + isPartial = true + if (!stas.keyDeriver) { + setSendResult({ ok: false, message: 'Key deriver unavailable — cannot build token-change for a partial send.' }) + setSending(false) + return + } + const ctxRow = await stas.keyDeriver.createNextReceiveContext() + args = { + ...baseArgs, + amount: amt, + senderChangeHash160: ctxRow.ownerFieldHash160, + senderChangeKeyId: ctxRow.keyId, + tokenId: sendTarget.tokenId || undefined, + } + } + } + } + + const result = await adapter.transfer(args) + if (result.ok) { + setSendResult({ + ok: true, + message: `Broadcast ✓ txid=${result.txid}${isPartial ? ' · change kept in your wallet' : ''}`, + }) + // Both cases just reload from the DB — no scan needed. The transfer + // service already spent the source and (on a partial send) registered + // the token-change output before returning, so listStasOutputs / + // the basket reflect the new balance immediately. The old scan-on- + // partial was a leftover from before change-registration was synchronous. + loadHoldings() + } else { + setSendResult({ ok: false, message: result.reason ?? 'transfer failed' }) + } + } catch (e) { + setSendResult({ ok: false, message: e instanceof Error ? e.message : String(e) }) + } finally { + setSending(false) + } + } + + const toggleExpand = (key: string) => { + setExpanded((cur) => { + const next = new Set(cur) + if (next.has(key)) next.delete(key) + else next.add(key) + return next + }) + } + + if (!wallet) return null + + return ( + + {/* Header */} + + + + + + Assets + + + Tokens held by this wallet — grouped by token, expandable to see each UTXO. + + + } + label={`${allGroups.length} ${allGroups.length === 1 ? 'token' : 'tokens'}`} + /> + + + + setFilter(e.target.value)} + sx={{ mt: 2, width: '100%', maxWidth: 360 }} + InputProps={{ + startAdornment: , + }} + /> + + + + + + + {scanStats && (scanStats.rows.length > 0 || scanStats.failed) && ( + + {scanStats.rows.map((r) => ( + + + + {r.label} + + + {r.registered > 0 && ( + + )} + {r.known > 0 && } + {r.errors > 0 && ( + + )} + + {r.errorMessages.map((m) => ( + + {m} + + ))} + + ))} + {scanStats.failed && ( + + {scanStats.failed} + + )} + + )} + + + {error && ( + + {error} + + )} + + + + {/* Receive address */} + + + + + + Receive {receiveProtocol === 'stas' ? 'STAS / DSTAS' : protocolLabel(receiveProtocol)} + + + Generates the next BRC-42 receive address for this standard. Share it with a sender. + + + + {(['stas', 'bsv-21'] as TokenProtocolId[]).map((p) => ( + + ))} + + + + {receiveError && ( + + {receiveError} + + )} + {receiveAddress && ( + + + + + + + {receiveLabel} + + + {receiveAddress} + + + + + + + )} + + + + {/* Token groups */} + {groups.length === 0 && !loading && ( + + + + No token holdings yet. Generate a receive address above and have a sender + transfer STAS, DSTAS, or BSV-21 to it — then press Refresh. + + + + )} + + {groups.map((g) => { + const isExpanded = expanded.has(g.groupKey) + return ( + + toggleExpand(g.groupKey)} + sx={{ + cursor: 'pointer', + py: 1.5, + '&:last-child': { pb: 1.5 }, + '&:hover': { bgcolor: 'action.hover' }, + }} + > + + + + + {g.name || g.symbol} + {g.name && g.symbol !== g.name && ( + + ({g.symbol}) + + )} + + + + verifyHoldings(g.outputs, { force: true })} /> + + + {g.protocol === 'bsv-21' + ? (g.spendableTokenAmount !== g.tokenAmount && ( + + )) + : (g.spendableSatoshis < g.totalSatoshis && ( + + ))} + {g.tokenIds.size > 0 && ( + + + + )} + + + + {isExpanded ? : } + + + + + + + + {g.outputs.map((o) => { + const own = ownershipLabel(o.brc42KeyId) + const adapter = stas?.tokens?.getById(o.protocol) + const transferSupported = adapter?.transferSupported ?? false + const sendDisabled = + !o.spendable || + o.frozen || + o.confiscated || + !o.scriptHex || + !o.brc42KeyId || + !transferSupported + const sendTip = !transferSupported + ? `Send is not yet available for ${protocolLabel(o.protocol)} in this wallet.` + : !o.spendable + ? 'This output is not spendable yet.' + : '' + const sendBtn = ( + + ) + return ( + + + + + {o.protocol === 'bsv-21' + ? `${formatTokenAmount(o.tokenAmount, o.decimals)} ${o.symbol ?? ''}` + : `${o.satoshis.toLocaleString()} sats`} + + {own && ( + + + + )} + {!o.spendable && ( + + )} + {o.frozen && } + {o.confiscated && } + + + + {o.txid.substring(0, 16)}…:{o.vout} + + e.stopPropagation()} + > + + + + + owner: {o.ownerAddress} + + + + {sendTip ? ( + + {/* span so MUI can attach the tooltip to a disabled button */} + {sendBtn} + + ) : ( + sendBtn + )} + + + ) + })} + + + + ) + })} + + {/* Activity — sent STAS history (uses includeSpent:true on listStasOutputs) */} + {sentHoldings.length > 0 && ( + + setActivityExpanded((v) => !v)} + sx={{ + cursor: 'pointer', + py: 1.5, + '&:last-child': { pb: 1.5 }, + '&:hover': { bgcolor: 'action.hover' }, + }} + > + + + + + Recent activity + + + {sentHoldings.length} STAS {sentHoldings.length === 1 ? 'transfer' : 'transfers'} sent from this wallet + + + + {activityExpanded ? : } + + + + + + + {sentHoldings.map((o) => ( + + + + + + {o.protocol === 'bsv-21' + ? `${formatTokenAmount(o.tokenAmount, o.decimals)} ${o.symbol ?? ''}` + : `${o.satoshis.toLocaleString()} sats`} + + {o.protocol !== 'bsv-21' && o.symbol && ( + + )} + {o.brc42KeyId && ( + + )} + + + source + e.stopPropagation()} + > + {o.txid.substring(0, 14)}…:{o.vout} + + + {o.spentBy && ( + + spent in + e.stopPropagation()} + > + {o.spentBy.substring(0, 14)}… + + + )} + {o.createdAt && ( + + received {new Date(o.createdAt).toLocaleString()} + + )} + + + ))} + + + + )} + + {/* Send dialog */} + { + if (!sending) { + setSendTarget(null) + setSendResult(null) + } + }} + fullWidth + maxWidth='sm' + > + Send {sendTarget?.symbol ?? 'STAS'} + + {sendTarget && ( + + {sendTarget.verification?.result === 'not-authentic' && ( + + + + This token failed provenance verification. It does not + descend from a genuine mint + {sendTarget.verification.reason ? ` (${sendTarget.verification.reason})` : ''} — + it may be counterfeit. Forwarding it passes the problem to the recipient. + + + )} + {sendTarget.verification?.result === 'undetermined' && ( + + + + Provenance could not be verified yet (unknown, not proven fake). You can + still send, but the origin hasn't been confirmed to a genesis mint. + + + )} + + + Sending + + + {sendTarget.protocol === 'bsv-21' + ? `${formatTokenAmount(sendTarget.tokenAmount, sendTarget.decimals)} ${sendTarget.symbol ?? ''}` + : `${sendTarget.satoshis.toLocaleString()} sats · ${sendTarget.symbol ?? 'STAS'}`} + + + from {ownershipLabel(sendTarget.brc42KeyId)?.short ?? '—'} ({sendTarget.ownerAddress.substring(0, 14)}…) + + + setSendRecipient(e.target.value)} + fullWidth + placeholder='1...' + disabled={sending} + autoFocus + /> + {(() => { + // Amount + split preview — for all three standards. STAS/DSTAS + // are satoshi-denominated; BSV-21 uses raw token units. + const isB21 = sendTarget.protocol === 'bsv-21' + const maxStr = isB21 ? sendTarget.tokenAmount : String(sendTarget.satoshis) + let helper: string = isB21 + ? 'Raw token units (integer). Leave blank to send the whole UTXO.' + : 'Token satoshis (integer). Leave blank to send the whole UTXO.' + if (sendAmount && /^\d+$/.test(sendAmount)) { + try { + const amt = BigInt(sendAmount) + const max = BigInt(maxStr) + const change = max > amt ? max - amt : 0n + if (isB21) { + helper = `≈ ${formatTokenAmount(sendAmount, sendTarget.decimals)} ${sendTarget.symbol ?? ''}` + + (change > 0n ? ` · change ${formatTokenAmount(change.toString(), sendTarget.decimals)} ${sendTarget.symbol ?? ''} stays in your wallet` : '') + } else { + helper = change > 0n + ? `${amt.toLocaleString()} sats sent · ${change.toLocaleString()} sats change stays in your wallet` + : `${amt.toLocaleString()} sats — whole UTXO` + } + } catch { /* keep default helper */ } + } + return ( + setSendAmount(e.target.value)} + fullWidth + placeholder={maxStr} + disabled={sending} + helperText={helper} + /> + ) + })()} + + The wallet covers BSV fee automatically. After broadcast, the recipient + wallet picks up the UTXO via the indexer-driven scan on its next Refresh. + + {sendResult && ( + + {sendResult.message} + + )} + + )} + + + + + + + + !recovering && setRecoverDialogOpen(false)} + maxWidth='sm' + fullWidth + > + Recover orphaned BSV-21 output + + + + Pre-fix BSV-21 sends produced change outputs that landed in the wallet's + outputs table but were not assigned to the bsv-21-tokens basket, so they + don't show up in your holdings. Enter the outpoint to reassign it + retroactively. Idempotent — re-running on a recovered output is a no-op. + + setRecoverTxid(e.target.value)} + disabled={recovering} + fullWidth + /> + setRecoverVout(e.target.value)} + disabled={recovering} + fullWidth + /> + {recoverResult && ( + + {recoverResult.message} + + )} + + + + + + + + + ) +} diff --git a/src/lib/pages/Dashboard/BasketsPage.tsx b/src/lib/pages/Dashboard/BasketsPage.tsx new file mode 100644 index 0000000..cedf3e4 --- /dev/null +++ b/src/lib/pages/Dashboard/BasketsPage.tsx @@ -0,0 +1,344 @@ +/** + * BasketsPage — browse the wallet's baskets and the outputs inside each. + * + * A basket is a labelled bucket of outputs (tokens, change, app data). BRC-100's + * `listOutputs` needs a basket name upfront, so there's no "enumerate baskets" + * call on the wallet surface; we read the basket list + per-basket counts over + * the stas:query IPC. + * + * Layout: a sticky basket list on the left, the selected basket's outputs on the + * right. Responsive — the two panes stack on a narrow window. + */ + +import React, { useContext, useEffect, useState, useCallback } from 'react' +import { + Card, + CardContent, + Typography, + Box, + Button, + Stack, + Chip, + Divider, + CircularProgress, + Table, + TableHead, + TableBody, + TableRow, + TableCell, + TableContainer, + Paper, +} from '@mui/material' +import RefreshIcon from '@mui/icons-material/Refresh' +import InventoryIcon from '@mui/icons-material/Inventory' +import { WalletContext } from '../../WalletContext' +import { stasQuery } from '../../services/stas' + +interface BasketRow { + basketId: number + name: string + numberOfDesiredUTXOs: number | null + minimumDesiredUTXOValue: number | null + outputCount: number + spendableCount: number + totalSatoshis: number +} + +interface OutputRow { + outputId: number + outpoint: string + txid: string | null + vout: number + satoshis: number + spendable: boolean + type?: string + customInstructions: string | null + lockingScript: string | null + createdAt?: string +} + +function formatSats(n: number | undefined | null): string { + return (n ?? 0).toLocaleString() + ' sats' +} + +function truncateHex(hex: string | null | undefined, len = 24): string { + if (!hex) return '—' + if (hex.length <= len) return hex + return `${hex.substring(0, len)}…` +} + +export default function BasketsPage() { + const { stas } = useContext(WalletContext) + const identityKey = stas?.keyDeriver?.identityKey + const chain = stas?.keyDeriver?.chain + + const [baskets, setBaskets] = useState(null) + const [loadingBaskets, setLoadingBaskets] = useState(false) + const [basketsError, setBasketsError] = useState(null) + + const [selectedBasket, setSelectedBasket] = useState(null) + const [outputs, setOutputs] = useState(null) + const [loadingOutputs, setLoadingOutputs] = useState(false) + const [outputsError, setOutputsError] = useState(null) + + const loadBaskets = useCallback(async () => { + if (!identityKey || !chain) return + setLoadingBaskets(true) + setBasketsError(null) + try { + const rows = (await stasQuery(identityKey, chain, 'listAllBaskets', [])) ?? [] + setBaskets(rows as BasketRow[]) + // Auto-select the basket with the most outputs on first load. + if (!selectedBasket && Array.isArray(rows) && rows.length > 0) { + const sorted = [...rows].sort( + (a: any, b: any) => (b.outputCount ?? 0) - (a.outputCount ?? 0) + ) + setSelectedBasket(sorted[0].name) + } + } catch (e) { + setBasketsError(e instanceof Error ? e.message : String(e)) + } finally { + setLoadingBaskets(false) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [identityKey, chain]) + + const loadOutputs = useCallback( + async (basket: string) => { + if (!identityKey || !chain) return + setLoadingOutputs(true) + setOutputsError(null) + try { + const rows = + (await stasQuery(identityKey, chain, 'listBasketOutputs', [basket])) ?? [] + setOutputs(rows as OutputRow[]) + } catch (e) { + setOutputsError(e instanceof Error ? e.message : String(e)) + } finally { + setLoadingOutputs(false) + } + }, + [identityKey, chain] + ) + + useEffect(() => { + loadBaskets() + }, [loadBaskets]) + + useEffect(() => { + if (selectedBasket) loadOutputs(selectedBasket) + }, [selectedBasket, loadOutputs]) + + return ( + + + + + + Baskets + + + Every basket this wallet holds, with the outputs inside it and each + basket's spendable count and total value. Pick a basket to see its outputs. + + + + + + + + {basketsError && ( + + {basketsError} + + )} + + {/* Two panes — basket list + outputs. Stacks on a narrow window; on wide + windows the basket list sticks so scrolling outputs keeps it in view. */} + + + + Baskets ({baskets?.length ?? 0}) + + {baskets && baskets.length === 0 && ( + + No baskets yet. The wallet creates `default` on first use. + + )} + {baskets && baskets.length > 0 && ( + + {baskets.map((b) => { + const isSelected = b.name === selectedBasket + return ( + setSelectedBasket(b.name)} + role='button' + tabIndex={0} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + setSelectedBasket(b.name) + } + }} + sx={{ + p: 1, + borderRadius: 1, + cursor: 'pointer', + bgcolor: isSelected ? 'action.selected' : 'action.hover', + borderLeft: '3px solid', + borderColor: isSelected ? 'primary.main' : 'transparent', + transition: 'background-color 0.1s', + '&:hover': { bgcolor: 'action.selected' }, + '&:focus-visible': { outline: '2px solid', outlineColor: 'primary.main' }, + }} + > + + {b.name} + + + + 0 ? 'success' : 'default'} + variant='outlined' + /> + + + {b.numberOfDesiredUTXOs != null && ( + + target: {b.numberOfDesiredUTXOs} + + )} + + ) + })} + + )} + + + {/* Outputs table for the selected basket */} + + + {selectedBasket + ? `Outputs in "${selectedBasket}" (${outputs?.length ?? 0})` + : 'Select a basket to see its outputs'} + + + {outputsError && ( + + {outputsError} + + )} + + {loadingOutputs && ( + + + Loading outputs… + + )} + + {!loadingOutputs && outputs && outputs.length === 0 && selectedBasket && ( + + No outputs in this basket yet. + + )} + + {!loadingOutputs && outputs && outputs.length > 0 && ( + + + + + Outpoint + Satoshis + Spendable + Script + Custom Instr. + + + + {outputs.map((o) => ( + + + {o.txid ? ( + + {o.txid.substring(0, 12)}…:{o.vout} + + ) : ( + ?:{o.vout} + )} + + + {o.satoshis.toLocaleString()} + + + {o.spendable ? ( + + ) : ( + + )} + + + + {truncateHex(o.lockingScript, 22)} + {o.lockingScript && ( + + ({(o.lockingScript.length / 2).toLocaleString()}B) + + )} + + + + + {truncateHex(o.customInstructions, 30)} + + + + ))} + +
+
+ )} +
+
+
+
+ ) +} diff --git a/src/lib/pages/Dashboard/PeerTokens/index.tsx b/src/lib/pages/Dashboard/PeerTokens/index.tsx new file mode 100644 index 0000000..3566e7f --- /dev/null +++ b/src/lib/pages/Dashboard/PeerTokens/index.tsx @@ -0,0 +1,315 @@ +/** + * Tokens — the token tab of the Transfers page. Send STAS / DSTAS / BSV-21 + * peer-to-peer over MessageBox, mirroring the Payments (PeerPay) tab format: + * - inner tabs [ Send | Incoming ] + * - the Send tab carries a Transaction History section (past token sends, + * tagged with the `peertoken` action label) + * - the Incoming tab lists tokens sent to you, each with Accept + * + * Holdings load like AssetsPage (STAS/DSTAS via listStasOutputs, BSV-21 via + * listOutputs); source resolution + BRC-29 derivation stay in the adapters. + */ +import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react' +import { + Container, Paper, Stack, Typography, TextField, Button, Chip, Divider, List, + ListItem, ListItemText, IconButton, Tooltip, MenuItem, Tabs, Tab, Card, CardContent, + Link, Dialog, DialogTitle, DialogContent, DialogActions, Alert, CircularProgress, Box +} from '@mui/material' +import RefreshIcon from '@mui/icons-material/Refresh' +import { toast } from 'react-toastify' +import { WalletContext } from '../../../WalletContext' +import type { IncomingToken, SendTokenParams } from '@bsv/message-box-client' +import { loadPeerHoldings, type PeerHolding as Holding } from '../../../services/tokens/peer/loadPeerHoldings' + +interface TokenTx { + txid: string + description: string + satoshis: number +} + +export default function PeerTokens() { + const ctx = useContext(WalletContext) as any + const stas = ctx?.stas + const wallet = ctx?.managers?.permissionsManager ?? ctx?.wallet + const network: string = ctx?.network ?? 'mainnet' + const useMessageBox: boolean = ctx?.useMessageBox ?? false + + const peerTokens = stas?.peerTokens + const identityKey: string | undefined = stas?.keyDeriver?.identityKey + const chain: 'main' | 'test' = stas?.keyDeriver?.chain ?? 'main' + const originator: string | undefined = ctx?.adminOriginator + + const [tab, setTab] = useState(0) + const [holdings, setHoldings] = useState([]) + const [loadingHoldings, setLoadingHoldings] = useState(false) + const [selectedKey, setSelectedKey] = useState('') + const [recipient, setRecipient] = useState('') + const [amount, setAmount] = useState('') + const [sending, setSending] = useState(false) + const [confirmOpen, setConfirmOpen] = useState(false) + + const [transactions, setTransactions] = useState([]) + const [incoming, setIncoming] = useState([]) + const [accepting, setAccepting] = useState(null) + + const selected = useMemo(() => holdings.find((h) => h.key === selectedKey), [holdings, selectedKey]) + + // ── Load holdings ───────────────────────────────────────────────────────── + const loadHoldings = useCallback(async () => { + if (!wallet || !identityKey) return + setLoadingHoldings(true) + try { + setHoldings(await loadPeerHoldings({ wallet, identityKey, chain, originator })) + } catch (e) { + console.warn('[Tokens] loadPeerHoldings failed', e) + } finally { + setLoadingHoldings(false) + } + }, [wallet, identityKey, chain, originator]) + + // ── Transaction history (past token sends, tagged `peertoken`) ────────────── + const getHistory = useCallback(async () => { + if (!wallet) return + try { + const res = await wallet.listActions( + { labels: ['peertoken'], labelQueryMode: 'any', includeOutputs: true, limit: 100 }, + originator + ) + setTransactions( + (res?.actions ?? []).map((a: any) => ({ + txid: a.txid, + description: a.description ?? '', + satoshis: a.satoshis ?? 0, + })) + ) + } catch (e) { + console.warn('[Tokens] listActions failed', e) + } + }, [wallet, originator]) + + // ── Incoming ──────────────────────────────────────────────────────────────── + const refreshIncoming = useCallback(async () => { + if (!peerTokens) return + try { + setIncoming(await peerTokens.listIncomingTokens()) + } catch (e) { + console.warn('[Tokens] listIncomingTokens failed', e) + } + }, [peerTokens]) + + useEffect(() => { + void loadHoldings() + void getHistory() + void refreshIncoming() + }, [loadHoldings, getHistory, refreshIncoming]) + + useEffect(() => { + if (!peerTokens) return + let active = true + peerTokens + .listenForLiveTokens({ + onToken: (t: IncomingToken) => { + if (!active) return + setIncoming((prev) => (prev.some((p) => p.messageId === t.messageId) ? prev : [t, ...prev])) + toast.info(`Incoming ${t.token.protocol} token`) + }, + }) + .catch((e: any) => console.warn('[Tokens] listen failed', e)) + return () => { active = false } + }, [peerTokens]) + + // ── Send ────────────────────────────────────────────────────────────────── + const startSend = () => { + if (!selected) return toast.error('Pick a token to send') + if (!recipient.trim()) return toast.error('Enter a recipient identity key') + setConfirmOpen(true) + } + + const doSend = async () => { + if (!selected || !peerTokens) return + setConfirmOpen(false) + setSending(true) + try { + const params: SendTokenParams = { + recipient: recipient.trim(), + protocol: selected.protocol, + source: selected.source, + amount: amount || selected.amount, + } + const sent = await peerTokens.sendToken(params) + toast.success(`Sent ${selected.protocol} ✓ txid ${sent?.txid ? sent.txid.slice(0, 16) + '…' : '(pending)'}`) + await loadHoldings() + await getHistory() + } catch (e: any) { + console.error('[Tokens] send failed — full error:', e) + toast.error(`Send failed: ${String(e?.message ?? e).slice(0, 160)}`) + } finally { + setSending(false) + } + } + + const accept = async (t: IncomingToken) => { + if (!peerTokens) return + setAccepting(t.messageId) + try { + const r = await peerTokens.acceptToken(t) + if (typeof r === 'string') toast.error(r) + else { + toast.success(`Accepted ${t.token.protocol} token`) + setIncoming((prev) => prev.filter((p) => p.messageId !== t.messageId)) + await loadHoldings() + } + } catch (e: any) { + toast.error(`Accept failed: ${e?.message ?? String(e)}`) + } finally { + setAccepting(null) + } + } + + if (!useMessageBox || !peerTokens) { + return ( + + + Tokens + + MessageBox is not enabled for this wallet. Enable it in wallet configuration to send and + receive tokens peer-to-peer. + + + + ) + } + + const wocTxBase = network === 'mainnet' ? 'https://whatsonchain.com/tx/' : 'https://test.whatsonchain.com/tx/' + + return ( + + + Tokens + { setTab(v); if (v === 1) void refreshIncoming() }} + variant="fullWidth" + sx={{ mb: 2, borderBottom: 1, borderColor: 'divider' }} + > + + + + + {/* Tab 0: Send + Transaction History */} + {tab === 0 && ( + + + + Send a token + + void loadHoldings()} disabled={loadingHoldings}> + + + + { setSelectedKey(e.target.value); const h = holdings.find((x) => x.key === e.target.value); setAmount(h?.amount ?? '') }} + helperText={loadingHoldings ? 'Loading…' : holdings.length === 0 ? 'No token holdings found' : `${holdings.length} holding(s)`} + > + {holdings.map((h) => ( + {h.protocol.toUpperCase()} — {h.label} + ))} + + setRecipient(e.target.value)} placeholder="03…" /> + setAmount(e.target.value)} + helperText={'Partial amounts supported (STAS/DSTAS split; BSV-21 makes change)'} + /> + + + + + + + {/* Transaction History */} + + Transaction history + + + {transactions.length === 0 ? ( + No token transactions yet + ) : ( + + {transactions.map((tx) => ( + + + + txid:{' '} + {tx.txid} + + {tx.description && ( + details: {tx.description} + )} + + + ))} + + )} + + + )} + + {/* Tab 1: Incoming tokens */} + {tab === 1 && ( + + + Incoming tokens + + + {incoming.length === 0 ? ( + No incoming tokens + ) : ( + + {incoming.map((t) => ( + + void accept(t)} + startIcon={accepting === t.messageId ? : undefined}> + {accepting === t.messageId ? 'Accepting…' : 'Accept'} + + }> + + + {t.token.amount} · {t.token.assetId.slice(0, 12)}… + } + secondary={from {t.sender?.slice?.(0, 14) ?? '?'}…} + /> + + + + ))} + + )} + + )} + + {/* Confirm send */} + setConfirmOpen(false)}> + Confirm token send + + + Protocol: {selected?.protocol} + Token: {selected?.label} + Amount: {amount || selected?.amount} + To: {recipient} + + + + + + + + + + ) +} diff --git a/src/lib/pages/Dashboard/Settings/index.tsx b/src/lib/pages/Dashboard/Settings/index.tsx index 6356c79..98c46ce 100644 --- a/src/lib/pages/Dashboard/Settings/index.tsx +++ b/src/lib/pages/Dashboard/Settings/index.tsx @@ -651,6 +651,7 @@ const Settings = () => { + setShowBackupDialog(false)} maxWidth="sm" fullWidth> {t('backup_dialog_title')} diff --git a/src/lib/pages/Dashboard/Transfers/index.tsx b/src/lib/pages/Dashboard/Transfers/index.tsx new file mode 100644 index 0000000..11009a3 --- /dev/null +++ b/src/lib/pages/Dashboard/Transfers/index.tsx @@ -0,0 +1,30 @@ +/** + * Transfers — unified peer-to-peer surface that consolidates PeerPay + * (Payments) and PeerToken (Tokens) into one page with two tabs. Replaces the + * former separate "Payments" and "Peer Tokens" sidebar entries; the Assets + * page is now purely for viewing holdings. + * + * Each tab renders its existing page component unchanged. We conditionally + * mount (rather than hide) so only the active surface polls its MessageBox + * inbox — switching tabs reloads that tab's state, which both pages already + * do on mount. + */ +import React, { useState } from 'react' +import { Box, Tabs, Tab } from '@mui/material' +import Payments from '../Payments' +import PeerTokens from '../PeerTokens' + +export default function Transfers() { + const [tab, setTab] = useState(0) + return ( + + + setTab(v)} aria-label="transfers tabs"> + + + + + {tab === 0 ? : } + + ) +} diff --git a/src/lib/pages/Dashboard/index.tsx b/src/lib/pages/Dashboard/index.tsx index ac198ad..6ab5087 100644 --- a/src/lib/pages/Dashboard/index.tsx +++ b/src/lib/pages/Dashboard/index.tsx @@ -21,7 +21,7 @@ import App from './App/Index'; // Assuming index.tsx or similar import Settings from './Settings'; // Assuming index.tsx or similar import Security from './Security'; // Assuming index.tsx or similar import { UserContext } from '../../UserContext'; -import Payments from './Payments'; +import Transfers from './Transfers'; import LegacyBridge from './LegacyBridge'; // Note: These might still be .jsx files and need refactoring later import AppAccess from './AppAccess'; // Assuming index.jsx or similar @@ -30,6 +30,8 @@ import ProtocolAccess from './ProtocolAccess'; // Assuming index.jsx or similar import CounterpartyAccess from './CounterpartyAccess'; // Assuming index.jsx or similar import CertificateAccess from './CertificateAccess'; // Assuming index.jsx or similar import { WalletContext } from '../../WalletContext'; +import BasketsPage from './BasketsPage'; +import AssetsPage from './AssetsPage'; // @ts-expect-error - Type issues with makeStyles const useStyles = makeStyles(style, { name: 'Dashboard' @@ -112,6 +114,14 @@ export default function Dashboard() {
+ + {/* Existing Redirects */} @@ -123,8 +133,12 @@ export default function Dashboard() { /> + {/* Legacy path — Peer Tokens is now the Tokens tab under Transfers. */} + + + { // ---- Runtime state ---- private _managers: WalletServiceSnapshot['managers'] = {} private _wallet?: WalletInterface + private _stas?: StasServices private _settings: WalletSettings = DEFAULT_SETTINGS private _activeProfile: WalletProfile | null = null private _snapshotLoaded = false @@ -163,6 +217,8 @@ export class WalletService extends EventEmittable { get adminOriginator() { return this._adminOriginator } get managers() { return this._managers } get wallet() { return this._wallet } + /** STAS BRC-42 services (ownership recognition + receive-key derivation). */ + get stas() { return this._stas } get settings() { return this._settings } get activeProfile() { return this._activeProfile } get snapshotLoaded() { return this._snapshotLoaded } @@ -185,6 +241,7 @@ export class WalletService extends EventEmittable { adminOriginator: this._adminOriginator, managers: this._managers, wallet: this._wallet, + stas: this._stas, settings: this._settings, activeProfile: this._activeProfile, snapshotLoaded: this._snapshotLoaded, @@ -527,6 +584,94 @@ export class WalletService extends EventEmittable { } this._wallet = wallet + // STAS BRC-42 services — ownership recognition + receive-key derivation, + // plus the Task-4 discovery loop (WoC scan -> internalizeAction). + const stasKeyDeriver = new StasKeyDeriver(wallet, keyDeriver.identityKey, chain) + const stasRegistration = new StasRegistration(wallet, keyDeriver.identityKey, chain) + const stasTransfer = new StasTransferService(wallet, keyDeriver.identityKey, chain) + + // DSTAS transfer service (F3) — shares the STAS BRC-42 receive + // namespace, builds the new output via the SDK's pure + // buildDstasLockingScript, and assembles the DSTAS unlocking + // script byte-for-byte to match the template's witness format. + const dstasTransfer = new DstasTransferService(wallet, keyDeriver.identityKey, chain) + + // BSV-21 services — separate BRC-42 namespace, 1Sat REST indexer, + // standard P2PKH unlock path. + const bsv21KeyDeriver = new BSV21KeyDeriver(wallet, keyDeriver.identityKey, chain) + const bsv21Indexer = new OneSatIndexerClient({ chain }) + const bsv21Registration = new BSV21Registration(wallet, keyDeriver.identityKey, chain) + const bsv21Transfer = new BSV21TransferService({ + wallet, + identityKey: keyDeriver.identityKey, + chain, + deriver: bsv21KeyDeriver, + indexer: bsv21Indexer, + }) + + // Token-protocol adapter registry. Order matters: STAS's prefix sniff + // is cheap and unambiguous, DSTAS's SDK reader next, BSV-21's ord + // envelope last (also cheap but distinct prefix). + const tokens = new TokenProtocolRegistry() + tokens.register(new StasProtocolAdapter(stasTransfer)) + tokens.register(new DstasProtocolAdapter(dstasTransfer)) + tokens.register(new BSV21ProtocolAdapter(bsv21Transfer)) + + // Token discovery — WhatsOnChain is the single source for all three + // standards: STAS (by base58 address) and DSTAS (by owner hash160) ride + // StasDiscoveryService, BSV-21 rides BSV21DiscoveryService, all fed by + // the same WocTokenIndexerClient. + const wocIndexer = new WocTokenIndexerClient({ chain }) + const backToGenesis = new BackToGenesisClient({ chain }) + + const stasDiscovery = new StasDiscoveryService({ + deriver: stasKeyDeriver, + indexer: wocIndexer, + registration: stasRegistration, + wallet, + registry: tokens, + }) + const bsv21Discovery = new BSV21DiscoveryService({ + deriver: bsv21KeyDeriver, + indexer: wocIndexer, + registration: bsv21Registration, + wallet, + }) + + // Peer-token client (token analog of PeerPay). Uses the same raw + // `wallet` the token services use, so signing/derivation namespaces + // match. Each adapter reuses the existing transfer-service building + // blocks; the BRC-29 owner derivation lives inside the adapters. + const peerTokens = new PeerTokenClient({ + messageBoxHost: this._messageBoxUrl || MESSAGEBOX_HOST, + walletClient: wallet, + originator: this._adminOriginator, + adapters: [ + new StasTokenSettlementAdapter(wallet, keyDeriver.identityKey, chain), + new Bsv21TokenSettlementAdapter({ + wallet, + identityKey: keyDeriver.identityKey, + chain, + deriver: bsv21KeyDeriver, + indexer: bsv21Indexer, + }), + new DstasTokenSettlementAdapter(wallet, keyDeriver.identityKey, chain), + ], + }) + + this._stas = { + keyDeriver: stasKeyDeriver, + ownership: new StasOwnershipService(stasKeyDeriver), + discovery: stasDiscovery, + transfer: stasTransfer, + tokens, + bsv21KeyDeriver, + bsv21Discovery, + bsv21Indexer, + backToGenesis, + peerTokens, + } + // Load settings try { const userSettings = await (wallet as any).settingsManager?.get() diff --git a/src/lib/services/stas/StasDiscoveryService.ts b/src/lib/services/stas/StasDiscoveryService.ts new file mode 100644 index 0000000..84e02b6 --- /dev/null +++ b/src/lib/services/stas/StasDiscoveryService.ts @@ -0,0 +1,463 @@ +/** + * StasDiscoveryService — the renderer-only orchestrator that closes the + * receive loop. + * + * enumerate derived owner addresses + * → scan WoC for UTXOs at each + * → fetch each candidate tx via wallet.getServices() to read its script + * → parse as DSTAS and match owner field + * → register via StasRegistration (confirmed-only MVP) + * → return a structured ScanResult + * + * No timer; one scan per invocation. Auto-fired on wallet ready, and re-fired + * by the dev-only debug panel button. + */ + +import { Transaction } from '@bsv/sdk'; +import { Address, fromHex } from 'dxs-bsv-token-sdk/bsv'; +import { STAS_GAP_LIMIT } from './constants'; +import type { ParsedDstas } from './dstasParser'; +import type { StasKeyDeriver } from './StasKeyDeriver'; +import type { StasRegistration } from './StasRegistration'; +import type { ScanProgressFn, WocUtxo } from '../tokens/woc/WocTokenIndexerClient'; +import { stasQuery } from './stasIpc'; +import { TOKEN_BASKETS } from '../../constants/baskets'; +import type { TokenProtocolRegistry, ParsedTokenOutput } from '../tokens'; + +/** + * Adapter-shaped parsed token output the legacy registration expects. + * Maps the cross-protocol `ParsedTokenOutput` back onto the existing + * `ParsedDstas`-plus-symbol shape so we don't have to rewrite + * StasRegistration's payload contract in this PR. + */ +function toRichParsed(parsed: ParsedTokenOutput): ParsedDstas & { symbol?: string } { + return { + ownerFieldHash160: parsed.ownerFieldHash160, + tokenId: parsed.tokenId, + freezeEnabled: parsed.freezeEnabled ?? false, + confiscationEnabled: parsed.confiscationEnabled ?? false, + flagsHex: parsed.flagsHex ?? '', + serviceFields: parsed.serviceFields ?? [], + // DSTAS-spend prerequisite fields. The cross-protocol adapter shape + // doesn't carry these — registration only needs ownership/tokenId + // metadata — so default to empty/inert values here. The transfer + // path goes back through `parseDstasLockingScript` directly for the + // source UTXO it's about to spend. + optionalData: [], + actionData: {}, + frozen: false, + symbol: parsed.symbol, + }; +} + +export interface ScanResult { + scannedAddresses: number; + /** Total UTXOs the indexer returned across all scanned addresses. */ + candidates: number; + /** Candidates whose locking script parsed as DSTAS. */ + dstas: number; + /** DSTAS UTXOs whose owner field matched a derived key. */ + ownedAndDstas: number; + registered: number; + /** Owned DSTAS that we deferred (unconfirmed / no merkle proof yet). */ + deferred: number; + skippedAlreadyKnown: number; + errors: Array<{ txid?: string; vout?: number; message: string }>; + /** Set when registration succeeded — outpoints + token info for the UI. */ + registeredOutpoints: Array<{ txid: string; vout: number; tokenId: string }>; + /** + * Backfill stat — outputs we flipped from spendable=false → true on this + * scan. Closes the wallet-toolbox conservative default for any STAS + * registered before the auto-flip-at-register fix landed. + */ + spendableFlipped?: number; +} + +/** + * Per-address token indexer the discovery loop pulls from. Satisfied by + * `WocTokenIndexerClient`, which serves STAS (by base58 address) and DSTAS + * (by owner hash160) from the same host. + */ +export interface StasDiscoveryIndexer { + getUtxosForAddresses( + addresses: string[], + opts?: { onProgress?: ScanProgressFn } + ): Promise>; + getDstasUtxosForOwners( + ownerHash160s: string[], + opts?: { onProgress?: ScanProgressFn } + ): Promise>; +} + +/** What a scan is doing right now, for a caller that wants to show progress. */ +export interface ScanProgress { + phase: 'stas' | 'dstas' | 'register'; + done: number; + total: number; +} + +export interface ScanOptions { + onProgress?: (p: ScanProgress) => void; +} + +export interface StasDiscoveryDeps { + deriver: StasKeyDeriver; + indexer: StasDiscoveryIndexer; + registration: StasRegistration; + /** Wallet exposing `getServices()` (wallet-toolbox Wallet). */ + wallet: any; + /** + * Token-protocol adapters, in resolution order. Each candidate locking + * script is offered to every adapter; the first that recognises it + * decides the protocol + basket the UTXO is registered under. + */ + registry: TokenProtocolRegistry; + gapLimit?: number; +} + +export interface RegisterByTxidResult { + txid: string; + registered: number; + outputs: Array<{ + vout: number; + matched: boolean; + /** When matched=true: the recv-N keyIndex that owns the output. */ + keyIndex?: number; + /** When matched=true and register failed: reason string. */ + reason?: string; + /** Was the wallet successful in registering it? */ + ok?: boolean; + }>; + /** Error before per-output processing started (e.g. tx not found). */ + error?: string; +} + +export class StasDiscoveryService { + constructor(private readonly deps: StasDiscoveryDeps) {} + + /** + * DEMO-ONLY fast-path: register a STAS UTXO directly by txid. + * + * The PRIMARY discovery mechanism is `scan()` — enumerate derived + * receive addresses, query the STAS-aware indexer (Bitails) per-address + * for owned UTXOs, parse + register. That covers organic receive without + * the sender having to tell us anything beyond the recipient address. + * + * This method exists so a colocated mint flow (dex-shell after a faucet + * mint) can skip the indexer round-trip and get immediate UI feedback — + * the wallet fetches the tx directly, parses outputs, and internalizes + * matches. Useful too as a fallback when the address-based scan is + * unavailable (e.g. WoC doesn't index custom-script outputs by address). + */ + async registerByTxid(txid: string): Promise { + const out: RegisterByTxidResult = { txid, registered: 0, outputs: [] }; + const services: any = (this.deps.wallet as any).getServices?.(); + if (!services) { + out.error = 'wallet.getServices() unavailable'; + return out; + } + let rawTxRes: any; + try { + rawTxRes = await services.getRawTx(txid); + } catch (err) { + out.error = `getRawTx failed: ${err instanceof Error ? err.message : String(err)}`; + return out; + } + if (!rawTxRes?.rawTx) { + out.error = rawTxRes?.error?.message ?? 'getRawTx returned no rawTx'; + return out; + } + let tx: any; + try { + tx = Transaction.fromBinary(rawTxRes.rawTx as number[]); + } catch (err) { + out.error = `tx parse failed: ${err instanceof Error ? err.message : String(err)}`; + return out; + } + + const hwm = await this.deps.deriver.getHighWaterMark(); + const gap = this.deps.gapLimit ?? STAS_GAP_LIMIT; + const ownerMap = await this.deps.deriver.enumerateOwnerFields( + hwm > 0 ? hwm + gap : Math.min(gap, 5) + ); + + for (let vout = 0; vout < tx.outputs.length; vout++) { + const txout = tx.outputs[vout]; + const lockingScriptHex: string = txout.lockingScript.toHex(); + + // Ask the registry: which protocol (if any) recognises this script? + // STAS / DSTAS adapters are tried in registration order; the first + // match wins. Each adapter returns its own parsed payload. + const match = await this.deps.registry.find(lockingScriptHex, { + txid, + vout, + wallet: this.deps.wallet, + }); + if (!match) { + out.outputs.push({ vout, matched: false }); + continue; + } + + const keyIndex = ownerMap.get(match.parsed.ownerFieldHash160); + if (keyIndex === undefined) { + out.outputs.push({ vout, matched: false }); + continue; + } + + const reg = await this.deps.registration.register({ + txid, + vout, + tokenSatoshis: txout.satoshis ?? 0, + ownerFieldHash160: match.parsed.ownerFieldHash160, + brc42KeyId: `recv ${keyIndex}`, + parsed: toRichParsed(match.parsed), + protocol: { id: match.adapter.id, basketName: match.adapter.basketName }, + }); + const ok = !!reg.registered; + if (ok) out.registered++; + out.outputs.push({ + vout, + matched: true, + keyIndex, + ok, + reason: reg.reason, + }); + } + return out; + } + + async scan(opts: ScanOptions = {}): Promise { + const result: ScanResult = { + scannedAddresses: 0, + candidates: 0, + dstas: 0, + ownedAndDstas: 0, + registered: 0, + deferred: 0, + skippedAlreadyKnown: 0, + errors: [], + registeredOutpoints: [], + }; + const gap = this.deps.gapLimit ?? STAS_GAP_LIMIT; + const identityKey = this.deps.deriver.identityKey; + const chain = this.deps.deriver.chain; + + // 1. Enumerate derived owner fields (hash160 -> keyIndex). Memoized in the + // deriver, so repeated scans are cheap after the first. + // + // Bootstrap mode: when hwm === 0 no receive context has ever been issued, + // so a full BIP-32-style gap scan is pure waste (and floods WoC). Cap the + // effective range at a small bootstrap window — enough to cover the + // "send to recv 1..N without preparation" case but cheap on bandwidth. + const hwm = await this.deps.deriver.getHighWaterMark(); + const bootstrapGap = 5; + const effectiveUpTo = hwm > 0 ? hwm + gap : Math.min(bootstrapGap, gap); + const ownerMap = await this.deps.deriver.enumerateOwnerFields(effectiveUpTo); + + // 2. Convert each hash160 to a base58 address for WoC. + const addressToHash = new Map(); + for (const hash160Hex of ownerMap.keys()) { + try { + const address = new Address(fromHex(hash160Hex)).Value as string; + addressToHash.set(address, hash160Hex); + } catch { + // Skip undecodable owner fields; should not happen in practice. + } + } + result.scannedAddresses = addressToHash.size; + + // 3. WOC token UTXO scan. STAS is queried per base58 address; DSTAS per + // owner hash160 (WOC's DSTAS endpoint keys on the raw hash160, not + // base58). Both are merged into one work-list of {owner, keyIndex, + // utxos} so the per-UTXO registration loop below is shared. + const addresses = [...addressToHash.keys()]; + const stasScanned = await this.deps.indexer.getUtxosForAddresses(addresses, { + onProgress: (done, total) => opts.onProgress?.({ phase: 'stas', done, total }), + }); + + type OwnerUtxos = { + ownerHash160Hex: string | undefined; + ownerKeyIndex: number | undefined; + utxos: WocUtxo[]; + }; + const work: OwnerUtxos[] = stasScanned.map(({ address, utxos }) => { + const owner = addressToHash.get(address); + return { + ownerHash160Hex: owner, + ownerKeyIndex: owner ? ownerMap.get(owner) : undefined, + utxos, + }; + }); + + { + const dstasScanned = await this.deps.indexer.getDstasUtxosForOwners([...ownerMap.keys()], { + onProgress: (done, total) => opts.onProgress?.({ phase: 'dstas', done, total }), + }); + for (const { ownerHash160, utxos } of dstasScanned) { + if (utxos.length === 0) continue; + work.push({ + ownerHash160Hex: ownerHash160, + ownerKeyIndex: ownerMap.get(ownerHash160), + utxos, + }); + } + } + + // 4. Walk each UTXO: parse the output script (from the indexer's + // scriptHex when present, else fetch the tx), match ownership, register. + const services = (this.deps.wallet as any).getServices?.(); + if (!services) { + result.errors.push({ message: 'wallet.getServices() unavailable' }); + return result; + } + const txCache = new Map(); + + // Each work entry is bound to one owner hash160 by construction (the + // indexer was queried per-derived-address / per-owner). That mapping is + // the ownership fallback: if an adapter's parse can't recover an owner + // hash160, the binding still tells us which key owns the UTXO. + for (const { ownerHash160Hex, ownerKeyIndex, utxos } of work) { + for (const utxo of utxos) { + result.candidates++; + try { + // Idempotency pre-check — saves fetching tx/proof for known outpoints. + // Counts already-known UTXOs into dstas + ownedAndDstas too, so the + // panel reflects "tokens the wallet recognises at the scanned range" + // rather than just "newly registered this scan". Field names are + // legacy STAS-era; treat as "recognised tokens" / "matched to a key". + try { + const existing = await stasQuery(identityKey, chain, 'findStasOutputByOutpoint', [utxo.txid, utxo.vout]); + if (existing) { + result.dstas++; + result.ownedAndDstas++; + result.skippedAlreadyKnown++; + continue; + } + } catch { + // Channel error: best-effort; let registration handle the duplicate. + } + + // Prefer the indexer-supplied locking script (WOC `?script=true`) + // to skip a per-txid getRawTx just for parsing. Registration still + // fetches the BEEF / merkle proof via wallet.getServices() below. + let lockingScriptHex: string; + if (utxo.scriptHex) { + lockingScriptHex = utxo.scriptHex; + } else { + // Fetch tx once per txid. + let tx = txCache.get(utxo.txid); + if (!tx) { + const rawTxRes = await services.getRawTx(utxo.txid); + if (!rawTxRes?.rawTx) { + result.errors.push({ + txid: utxo.txid, + vout: utxo.vout, + message: rawTxRes?.error?.message ?? 'getRawTx returned no rawTx', + }); + continue; + } + tx = Transaction.fromBinary(rawTxRes.rawTx as number[]); + txCache.set(utxo.txid, tx); + } + + const out = tx.outputs[utxo.vout]; + if (!out) { + result.errors.push({ + txid: utxo.txid, + vout: utxo.vout, + message: 'output index out of range', + }); + continue; + } + lockingScriptHex = out.lockingScript.toHex(); + } + + // Ask the registry to recognise the script. Each adapter is asked + // in registration order; the first that returns a parsed payload + // owns the registration (and decides the destination basket). + const match = await this.deps.registry.find(lockingScriptHex, { + txid: utxo.txid, + vout: utxo.vout, + wallet: this.deps.wallet, + }); + if (!match) continue; + + // Ownership: the script's owner field is authoritative when the + // adapter recovered one (DSTAS / classic STAS — both always do). + // The indexer-address binding is only used as a fallback for + // adapters that can't recover an owner field from the script + // bytes alone — important defense: if an adapter DID parse an + // owner field and it doesn't match any derived key, the UTXO is + // NOT ours, even when the indexer places it at our address (e.g. + // a malicious sender forges the address-binding side). + const parsedOwner = match.parsed.ownerFieldHash160; + const matchedOwnerHash160 = parsedOwner || ownerHash160Hex || ''; + const keyIndex = parsedOwner + ? ownerMap.get(parsedOwner) + : ownerKeyIndex; + + result.dstas++; + if (keyIndex === undefined) continue; + result.ownedAndDstas++; + + // Mempool tolerance: previously this branch deferred when the + // indexer reported height 0. Bitails surfaces unconfirmed STAS too, + // and Task 4c's buildChainedAtomicBeef walks back through inputs to + // a confirmed ancestor, so mempool UTXOs are no longer special-cased. + + const reg = await this.deps.registration.register({ + txid: utxo.txid, + vout: utxo.vout, + tokenSatoshis: utxo.value, + ownerFieldHash160: matchedOwnerHash160, + brc42KeyId: `recv ${keyIndex}`, + parsed: toRichParsed(match.parsed), + protocol: { + id: match.adapter.id, + basketName: match.adapter.basketName, + }, + }); + + if (reg.registered) { + result.registered++; + result.registeredOutpoints.push({ + txid: utxo.txid, + vout: utxo.vout, + tokenId: match.parsed.tokenId, + }); + } else if (reg.reason === 'already registered') { + result.skippedAlreadyKnown++; + } else if (reg.reason?.includes('merkle proof') || reg.reason?.includes('deferred')) { + result.deferred++; + } else if (reg.reason) { + result.errors.push({ txid: utxo.txid, vout: utxo.vout, message: reg.reason }); + } + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + result.errors.push({ txid: utxo.txid, vout: utxo.vout, message }); + } + } + } + + // Backfill: flip spendable=true on every token basket's outputs that are + // still marked false. Runs once per protocol so DSTAS holdings (now in + // their own basket) get the same treatment classic STAS used to get. + try { + let total = 0; + for (const basket of TOKEN_BASKETS) { + const bf: any = await stasQuery( + identityKey, + chain, + 'backfillSpendableForBasket', + [basket] + ); + if (bf && typeof bf.updated === 'number') total += bf.updated; + } + result.spendableFlipped = total; + } catch { + /* best effort */ + } + + return result; + } +} diff --git a/src/lib/services/stas/StasKeyDeriver.ts b/src/lib/services/stas/StasKeyDeriver.ts new file mode 100644 index 0000000..5d56424 --- /dev/null +++ b/src/lib/services/stas/StasKeyDeriver.ts @@ -0,0 +1,118 @@ +/** + * StasKeyDeriver — BRC-42 derivation of STAS receive keys. + * + * Derives owner keys via `wallet.getPublicKey` (public keys only — safe to call + * from the renderer) and manages the monotonic receive-key counter through the + * `stas:query` IPC channel (the `stas_receive_contexts` table). + * + * Derivation is pure and deterministic, so `enumerateOwnerFields` is memoized + * and only extended as the scan range grows. + */ + +import type { WalletInterface } from '@bsv/sdk'; +import { hash160, toHex, fromHex } from 'dxs-bsv-token-sdk/bsv'; +import { STAS_PROTOCOL_ID, STAS_COUNTERPARTY, stasKeyId } from './constants'; + +export interface DerivedReceiveKey { + index: number; + keyId: string; + /** Compressed public key, hex. */ + publicKey: string; + /** hash160(publicKey), hex — the DSTAS owner field. */ + ownerFieldHash160: string; +} + +export interface ReceiveContextRow { + profileIdentityKey: string; + keyIndex: number; + keyId: string; + ownerFieldHash160: string; + derivedPublicKey: string; + createdAt: string; +} + +export class StasKeyDeriver { + private readonly _ownerFields = new Map(); + private _enumeratedUpTo = 0; + + constructor( + private readonly wallet: WalletInterface, + private readonly _identityKey: string, + private readonly _chain: 'main' | 'test' + ) {} + + /** Identity key of the wallet root (hex). */ + get identityKey(): string { return this._identityKey; } + /** Chain this deriver is scoped to. */ + get chain(): 'main' | 'test' { return this._chain; } + + /** Derive the Nth receive key. Pure — no DB access. */ + async deriveReceiveKey(index: number): Promise { + const keyId = stasKeyId(index); + const { publicKey } = await this.wallet.getPublicKey({ + protocolID: STAS_PROTOCOL_ID, + keyID: keyId, + counterparty: STAS_COUNTERPARTY, + }); + const ownerFieldHash160 = toHex(hash160(fromHex(publicKey))); + return { index, keyId, publicKey, ownerFieldHash160 }; + } + + /** + * Owner-field -> keyIndex map for `recv 1..upTo`, memoized. BRC-42 derivation + * is deterministic, so the cache is only ever extended. + */ + async enumerateOwnerFields(upTo: number): Promise> { + for (let i = this._enumeratedUpTo + 1; i <= upTo; i++) { + const k = await this.deriveReceiveKey(i); + this._ownerFields.set(k.ownerFieldHash160, i); + } + if (upTo > this._enumeratedUpTo) this._enumeratedUpTo = upTo; + return this._ownerFields; + } + + /** Highest issued receive-key index (0 if none / if the STAS query channel is unavailable). */ + async getHighWaterMark(): Promise { + const res = await this.query('getReceiveHighWaterMark', [this._identityKey]); + return res === undefined ? 0 : (res as number); + } + + /** Derive and persist the next receive context; returns the stored row. */ + async createNextReceiveContext(): Promise { + // Pre-check the IPC channel directly. The previous `if (res === undefined)` + // check after the insert was a false positive — INSERT queries return void + // through the IPC layer, so a successful write yields `res.result === undefined` + // (same shape as channel-absent). A direct channel probe is unambiguous. + if (typeof window === 'undefined' || !(window as any).electronAPI?.stas) { + throw new Error('STAS query channel unavailable — cannot persist receive context'); + } + const next = (await this.getHighWaterMark()) + 1; + const k = await this.deriveReceiveKey(next); + const row: ReceiveContextRow = { + profileIdentityKey: this._identityKey, + keyIndex: next, + keyId: k.keyId, + ownerFieldHash160: k.ownerFieldHash160, + derivedPublicKey: k.publicKey, + createdAt: new Date().toISOString(), + }; + await this.query('insertReceiveContext', [row]); + return row; + } + + /** + * Invoke a `stas:query` over IPC. Returns `undefined` when the channel is not + * present (non-Electron environments such as unit tests); throws on a query + * error reported by the main process. + */ + private async query(method: string, args: any[]): Promise { + const api = + typeof window !== 'undefined' ? (window as any).electronAPI?.stas : undefined; + if (!api) return undefined; + const res = await api.query(this._identityKey, this.chain, method, args); + if (!res || !res.success) { + throw new Error(`stas:query ${method} failed: ${res && res.error}`); + } + return res.result; + } +} diff --git a/src/lib/services/stas/StasOwnershipService.ts b/src/lib/services/stas/StasOwnershipService.ts new file mode 100644 index 0000000..bfd8398 --- /dev/null +++ b/src/lib/services/stas/StasOwnershipService.ts @@ -0,0 +1,48 @@ +/** + * StasOwnershipService — recognises whether a DSTAS locking script's owner + * field belongs to one of the wallet's BRC-42-derived keys. + * + * Scans derived owner keys from `recv 1` up to the persisted high-water mark + * plus a gap limit, matching the parsed owner field by hash160. + */ + +import { StasKeyDeriver } from './StasKeyDeriver'; +import { parseDstasLockingScript } from './dstasParser'; +import { STAS_GAP_LIMIT } from './constants'; + +export interface OwnershipResult { + owned: boolean; + /** The receive-key index that owns the output, when `owned` is true. */ + keyIndex?: number; +} + +export class StasOwnershipService { + constructor( + private readonly deriver: StasKeyDeriver, + private readonly gapLimit: number = STAS_GAP_LIMIT + ) {} + + /** + * Is this DSTAS locking script owned by a wallet-derived key? + * + * @param lockingScriptHex the candidate locking script, hex + * @param highWaterMark optional explicit high-water mark; when omitted it + * is read from the persisted receive contexts + */ + async isOwnedByWallet( + lockingScriptHex: string, + highWaterMark?: number + ): Promise { + const parsed = parseDstasLockingScript(lockingScriptHex); + if (!parsed) return { owned: false }; + + const hwm = + highWaterMark !== undefined + ? highWaterMark + : await this.deriver.getHighWaterMark(); + const ownerFields = await this.deriver.enumerateOwnerFields(hwm + this.gapLimit); + + const keyIndex = ownerFields.get(parsed.ownerFieldHash160); + return keyIndex !== undefined ? { owned: true, keyIndex } : { owned: false }; + } +} diff --git a/src/lib/services/stas/StasRegistration.ts b/src/lib/services/stas/StasRegistration.ts new file mode 100644 index 0000000..e756d85 --- /dev/null +++ b/src/lib/services/stas/StasRegistration.ts @@ -0,0 +1,265 @@ +/** + * StasRegistration — turn a discovered STAS UTXO into a wallet-recognised + * output via `internalizeAction` (basket insertion). + * + * Flow: + * 1. defensive idempotency check via stas:query findStasOutputByOutpoint + * 2. build a chained AtomicBEEF that walks back through inputs until every + * leaf has a merkle proof — so mempool txs work too (see OQ-8 in + * notes/OPEN-QUESTIONS.md for the rationale) + * 3. `wallet.internalizeAction({ outputs: [{ protocol: 'basket insertion', ... }] })` + * 4. link the satellite rows (stas_tokens + stas_outputs) to the new + * wallet-toolbox `outputs.outputId` + */ + +import type { AtomicBEEF, WalletInterface } from '@bsv/sdk'; +import { STAS_BASKET } from '../../constants/baskets'; +import { buildChainedAtomicBeef } from './buildChainedAtomicBeef'; +import { verifyAndPersistOnReceive } from '../tokens/verifyOnReceive'; +import type { ParsedDstas } from './dstasParser'; + +/** Classic-STAS parsed payload extends ParsedDstas with optional symbol. */ +type RichParsed = ParsedDstas & { symbol?: string }; + +/** + * Minimal protocol descriptor consumed by registration. Defined as a + * primitive shape (id + basketName) rather than importing the full + * `TokenProtocolAdapter` so the stas/ layer doesn't depend on the + * tokens/ layer that wraps it. + */ +export interface RegistrationProtocol { + id: 'stas' | 'dstas' | 'bsv-21'; + basketName: string; +} + +const DEFAULT_PROTOCOL: RegistrationProtocol = { + id: 'stas', + basketName: STAS_BASKET, +}; + +export interface RegisterStasArgs { + txid: string; + vout: number; + /** Satoshis on the UTXO (from the indexer scan). */ + tokenSatoshis: number; + /** hash160 of the BRC-42-derived owner key, hex. */ + ownerFieldHash160: string; + /** BRC-42 keyID, e.g. `"recv 7"`. */ + brc42KeyId: string; + /** Parsed DSTAS fields. Classic STAS also carries an optional `symbol`. */ + parsed: RichParsed; + /** + * Protocol descriptor — chooses the destination basket and stamps + * `protocol` on the satellite rows. Defaults to classic STAS for + * legacy callers that haven't been wired through the registry yet. + */ + protocol?: RegistrationProtocol; + /** + * Optional pre-built AtomicBEEF to internalize. Used by the peer-receive + * path, which already holds the signed transfer BEEF and must NOT re-fetch + * a possibly-unpropagated tx from the network. When omitted, a chained + * AtomicBEEF is assembled from `txid` (the discovery default). + */ + atomicBeef?: AtomicBEEF; + /** + * Skip the internalizeAction step and only link the satellite tables. Used + * when the output's basket was already declared at createAction time (a + * sender's own token-change), so the wallet-toolbox output row already exists. + */ + skipInternalize?: boolean; +} + +export interface RegisterStasResult { + registered: boolean; + txid: string; + vout: number; + outputId?: number; + /** Set when registered=false: human-readable reason. */ + reason?: string; +} + +const ORIGINATOR = 'admin.stas-discovery'; + +export class StasRegistration { + constructor( + private readonly wallet: WalletInterface, + private readonly identityKey: string, + private readonly chain: 'main' | 'test' + ) {} + + async register(args: RegisterStasArgs): Promise { + const { txid, vout, parsed, brc42KeyId, ownerFieldHash160, tokenSatoshis } = args; + const protocol = args.protocol ?? DEFAULT_PROTOCOL; + + // 1. Idempotency — skip outpoints that already live in stas_outputs. + try { + const existing = await this.stasQuery('findStasOutputByOutpoint', [txid, vout]); + if (existing) { + return { + registered: false, + txid, + vout, + outputId: existing.outputId, + reason: 'already registered', + }; + } + } catch (err) { + // Query channel missing (e.g. unit tests without IPC) — proceed cautiously. + if (!isQueryUnavailable(err)) throw err; + } + + // 2. Build a chained AtomicBEEF. Walks back through inputs until every + // leaf input has a merkle proof; lets us internalize mempool STAS by + // chaining the target tx + its parents to a confirmed source. + // Peer-receive supplies the BEEF directly (already delivered) so we + // don't re-fetch a possibly-unpropagated tx. + // When skipInternalize is set, the BEEF is never used (we don't + // internalize), so DON'T build it — building it would re-fetch the + // just-broadcast tx from WoC and 404, failing the whole registration. + let atomicBeef: AtomicBEEF = args.atomicBeef ?? []; + if (args.skipInternalize !== true && atomicBeef.length === 0) { + try { + const built = await buildChainedAtomicBeef({ wallet: this.wallet, txid }); + atomicBeef = built.atomicBeef; + } catch (err) { + return { + registered: false, + txid, + vout, + reason: `chained BEEF assembly failed: ${err instanceof Error ? err.message : String(err)}`, + }; + } + } + + // 4. internalizeAction (basket insertion). Skipped when the caller already + // declared the output's basket at createAction time (e.g. a sender's own + // token-change) — internalizing it again would conflict; we only need the + // satellite linkage below. + const customInstructions = JSON.stringify({ + tokenId: parsed.tokenId, + brc42KeyId, + flagsHex: parsed.flagsHex, + serviceFields: parsed.serviceFields, + }); + if (args.skipInternalize !== true) { + try { + await this.wallet.internalizeAction( + { + tx: atomicBeef, + outputs: [ + { + outputIndex: vout, + protocol: 'basket insertion', + insertionRemittance: { + basket: protocol.basketName, + customInstructions, + tags: [protocol.id], + }, + }, + ], + // Display-cased label — preserves the original "STAS discovery" + // wording for STAS while staying protocol-aware for the others. + description: `${ + protocol.id === 'bsv-21' + ? 'BSV-21' + : protocol.id.toUpperCase() + } discovery`, + seekPermission: false, + }, + ORIGINATOR + ); + } catch (err) { + return { + registered: false, + txid, + vout, + reason: `internalizeAction failed: ${err instanceof Error ? err.message : String(err)}`, + }; + } + } + + // 5. Link satellite tables. The wallet-toolbox `outputs` row was created + // inside internalizeAction (or by the caller's createAction basket + // declaration when skipInternalize); we look it up by outpoint to populate ours. + let outputId: number | undefined; + try { + outputId = await this.stasQuery('findOutputIdByOutpoint', [txid, vout]); + if (outputId) { + const now = new Date().toISOString(); + await this.stasQuery('upsertStasToken', [ + { + tokenId: parsed.tokenId, + symbol: (parsed as RichParsed).symbol ?? 'STAS', + name: undefined, + satoshisPerToken: 1, + freezeEnabled: parsed.freezeEnabled, + confiscationEnabled: parsed.confiscationEnabled, + // redemptionPkh remains the parsed value for DSTAS; classic STAS + // doesn't carry one in the engine, so we leave it null-ish. + redemptionPkh: parsed.tokenId === '' ? undefined : parsed.tokenId, + issuerIdentityKey: undefined, + flagsHex: parsed.flagsHex, + createdAt: now, + protocol: protocol.id, + }, + ]); + await this.stasQuery('insertStasOutput', [ + { + outputId, + tokenId: parsed.tokenId, + brc42KeyId, + ownerFieldHash160, + tokenSatoshis, + frozen: false, + confiscated: false, + serviceFieldsJson: JSON.stringify(parsed.serviceFields), + createdAt: now, + updatedAt: now, + protocol: protocol.id, + }, + ]); + // STAS outputs land with `spendable=false` because wallet-toolbox + // can't recognise the custom script as one it knows how to unlock. + // We sign externally via the BRC-42 path, so the flag is a false + // negative — flip it now so the user can transfer the UTXO without + // an extra preflight step at send-time. + await this.stasQuery('setOutputSpendable', [outputId, true]); + } + } catch (err) { + // The token is internalized regardless; satellite linkage is best-effort. + // Log but report registered=true so the discovery loop does not retry. + if (!isQueryUnavailable(err)) { + // eslint-disable-next-line no-console + console.warn(`[StasRegistration] satellite linkage failed for ${txid}:${vout}`, err); + } + } + + // Verify provenance the moment the token is ours — covers both the discovery + // scan and peer-accept paths (both land here). Fire-and-forget; never blocks + // the receive. `protocol.id` is 'stas' | 'dstas' | 'bsv-21'. + verifyAndPersistOnReceive(this.identityKey, this.chain, { txid, vout, protocol: protocol.id }); + + return { registered: true, txid, vout, outputId }; + } + + private async stasQuery(method: string, args: any[]): Promise { + const api = + typeof window !== 'undefined' ? (window as any).electronAPI?.stas : undefined; + if (!api) { + throw new QueryUnavailableError('STAS query channel unavailable'); + } + const res = await api.query(this.identityKey, this.chain, method, args); + if (!res || !res.success) { + throw new Error(`stas:query ${method} failed: ${res && res.error}`); + } + return res.result; + } +} + +class QueryUnavailableError extends Error { + readonly _queryUnavailable = true; +} + +function isQueryUnavailable(err: unknown): boolean { + return !!err && typeof err === 'object' && (err as any)._queryUnavailable === true; +} diff --git a/src/lib/services/stas/StasTransferService.ts b/src/lib/services/stas/StasTransferService.ts new file mode 100644 index 0000000..c0f577b --- /dev/null +++ b/src/lib/services/stas/StasTransferService.ts @@ -0,0 +1,580 @@ +/** + * StasTransferService — STAS transfer via createAction + signAction. + * + * The STAS engine assumes exactly 2 outputs in the transfer tx: + * vout 0 = new STAS to recipient + * vout 1 = BSV change back to funder + * + * wallet-toolbox's `generateChange` normally adds fragmentation outputs to + * top up the change basket toward `numberOfDesiredUTXOs` (default 144). To + * keep the tx at exactly 2 outputs, we LOWER the basket target to 0 before + * createAction (with `randomizeOutputs: false`), then restore it afterward. + * + * Signing: + * - STAS input (our outpoint): externally via `wallet.createSignature` with + * the BRC-42 derivation that owns the STAS. + * - BSV input (wallet-owned): the wallet signs it internally during signAction. + */ + +import type { WalletInterface } from '@bsv/sdk'; +import { Beef } from '@bsv/sdk'; +import { STAS_PROTOCOL_ID, STAS_COUNTERPARTY } from './constants'; +import { STAS_BASKET } from '../../constants/baskets'; +import { stasQuery } from './stasIpc'; +import { buildChainedAtomicBeef } from './buildChainedAtomicBeef'; +import { StasRegistration } from './StasRegistration'; +import { parseClassicStasMetadata } from './parseClassicStasMetadata'; +import { tokenLog } from '../tokens/tokenLog'; + +async function loadStasDeps(): Promise<{ + bsv: any; + stasInternals: any; + SIGHASH: number; +}> { + const bsvMod: any = await import('bsv'); + const bsv = bsvMod.default ?? bsvMod; + const stasInternalsMod: any = await import('stas-js/lib/stas.js'); + const stasInternals = stasInternalsMod.default ?? stasInternalsMod; + return { bsv, stasInternals, SIGHASH: stasInternals.sighash }; +} + +const ORIGINATOR = 'admin.stas-transfer'; + +export interface StasTransferArgs { + source: { + txid: string; + vout: number; + scriptHex: string; + satoshis: number; + brc42KeyId: string; + /** + * Optional owner-key derivation override for signing the STAS input. + * Defaults to the self-owned scheme (protocolID STAS_PROTOCOL_ID, + * keyID `brc42KeyId`, counterparty 'self'). A token received over a + * peer channel (BRC-29) is owned under a derivation keyed to the SENDER, + * so re-spending it requires `keyID = " "` and + * `counterparty = senderIdentityKey`. Supplying this makes such tokens + * spendable without changing the default self-custody path. + */ + owner?: { + protocolID?: [number, string]; + keyID: string; + counterparty: string; + /** True for a BRC-29-received token: derive the recipient's OWN key. */ + forSelf?: boolean; + }; + }; + recipientAddress: string; + /** + * Token amount (satoshis) to send to the recipient. Defaults to the full + * `source.satoshis` (1-to-1 transfer). When less than the full value, the + * service performs a SPLIT: a recipient STAS output of `amount` plus a + * sender token-change STAS output of the remainder (to `senderChangeHash160`). + */ + amount?: number; + /** + * Owner pkh (hex) for the sender's token-change STAS output. Required when + * `amount` < `source.satoshis`. Derived from the sender's own STAS receive + * key so the change is self-custodied and re-discoverable. + */ + senderChangeHash160?: string; + /** + * BRC-42 keyId of the sender's token-change receive key. Declared in the + * change output's customInstructions so the wallet tracks the output at + * creation time (mirrors BSV-21 token-change), which is what lets the + * satellite linkage find its output row. + */ + senderChangeKeyId?: string; + /** Token id for the change output's customInstructions (display/tracking). */ + tokenId?: string; +} + +export interface StasTransferResult { + ok: boolean; + txid?: string; + reason?: string; + /** Signed AtomicBEEF of the transfer (from signAction) — for peer delivery. */ + beef?: number[]; +} + +export class StasTransferService { + constructor( + private readonly wallet: WalletInterface, + private readonly identityKey: string, + private readonly chain: 'main' | 'test' + ) {} + + async transfer(args: StasTransferArgs): Promise { + const { source, recipientAddress } = args; + + let bsv: any, stasInternals: any, SIGHASH: number; + try { + ({ bsv, stasInternals, SIGHASH } = await loadStasDeps()); + } catch (err) { + return { ok: false, reason: `load stas-js/bsv failed: ${errMsg(err)}` }; + } + + const { updateStasScript, partialSTASUnlockingScript, getVersion } = stasInternals; + + // Effective owner-key derivation. Defaults to the self-owned scheme; a + // BRC-29 peer-received token overrides keyID + counterparty so it stays + // spendable. + const ownerDerivation = { + protocolID: (source.owner?.protocolID ?? STAS_PROTOCOL_ID) as any, + keyID: source.owner?.keyID ?? source.brc42KeyId, + counterparty: (source.owner?.counterparty ?? STAS_COUNTERPARTY) as any, + // BRC-29-received tokens are owned by OUR key in the shared derivation — + // derive the pubkey with forSelf:true so it matches the on-chain owner. + forSelf: source.owner?.forSelf === true, + }; + + // 1. Owner pubkey via BRC-42 derivation. + let ownerPubKey: any; + try { + const { publicKey } = await this.wallet.getPublicKey( + { + protocolID: ownerDerivation.protocolID, + keyID: ownerDerivation.keyID, + counterparty: ownerDerivation.counterparty, + forSelf: ownerDerivation.forSelf, + } as any, + ORIGINATOR + ); + ownerPubKey = bsv.PublicKey.fromString(publicKey); + } catch (err) { + return { ok: false, reason: `getPublicKey: ${errMsg(err)}` }; + } + + // Diagnostic: does our signing key actually own this UTXO? Compare the + // hash160 of the derived owner pubkey to the owner pkh baked in the source + // script (76a914 …). A mismatch = wrong brc42KeyId/counterparty. + try { + const derivedOwnerPkh = bsv.crypto.Hash.sha256ripemd160(ownerPubKey.toBuffer()).toString('hex'); + const sourceOwnerPkh = source.scriptHex.substring(6, 46); + tokenLog.debug('[stas-transfer] OWNER CHECK — keyID:', ownerDerivation.keyID, + 'counterparty:', ownerDerivation.counterparty, + '| derived pkh:', derivedOwnerPkh, '| source owner pkh:', sourceOwnerPkh, + '| MATCH:', derivedOwnerPkh === sourceOwnerPkh); + } catch { /* never block on diagnostics */ } + + // 2. Recipient hash160. + let recipientPkhHex: string; + try { + const addr = bsv.Address.fromString(recipientAddress); + recipientPkhHex = addr.hashBuffer.toString('hex'); + } catch (err) { + return { ok: false, reason: `invalid recipient: ${errMsg(err)}` }; + } + + // 3. Validate the source is a classic STAS shape. stas-js's updateStasScript + // enforces this internally, but its error message ("Invalid STAS script") + // doesn't tell the caller *why*. Pre-check so the failure mode is + // actionable — most often the user picked a DSTAS UTXO (different + // engine), or the lockingScript wasn't surfaced by listStasOutputs. + const sh = source.scriptHex; + if (typeof sh !== 'string' || sh.length < 56) { + return { + ok: false, + reason: `source.scriptHex missing or too short (type=${typeof sh}, length=${sh?.length ?? 0})`, + }; + } + if (!sh.startsWith('76a914')) { + return { + ok: false, + reason: `source isn't a classic STAS script — prefix is "${sh.substring(0, 20)}…". For DSTAS UTXOs the dispatch should route via DstasTransferService — if you reached this branch, the protocol-aware dispatch upstream is bypassed.`, + }; + } + if (sh.substring(46, 52) !== '88ac69') { + return { + ok: false, + reason: `source isn't a classic STAS script — engine marker missing at offset 46 (got "${sh.substring(46, 52)}", expected "88ac69")`, + }; + } + + // 3b. Resolve send amount vs. token-change (SPLIT). Full-value send keeps + // the original 1-output path byte-for-byte; a partial send adds a + // second STAS output carrying the remainder back to the sender. + const sendAmt = args.amount ?? source.satoshis; + const changeAmt = source.satoshis - sendAmt; + if (!Number.isInteger(sendAmt) || sendAmt < 1) { + return { ok: false, reason: `invalid amount ${sendAmt} (must be a positive integer ≤ ${source.satoshis})` }; + } + if (changeAmt < 0) { + return { ok: false, reason: `amount ${sendAmt} exceeds the token UTXO value ${source.satoshis}` }; + } + if (changeAmt > 0 && !args.senderChangeHash160) { + return { ok: false, reason: 'partial transfer requires senderChangeHash160 for the token-change output' }; + } + + // 4. Build new STAS locking script(s): recipient + (optional) sender change. + let newStasScriptHex: string; + let changeStasScriptHex: string | null = null; + let stasVersion: number; + try { + newStasScriptHex = updateStasScript(recipientPkhHex, sh); + if (changeAmt > 0 && args.senderChangeHash160) { + changeStasScriptHex = updateStasScript(args.senderChangeHash160, sh); + } + stasVersion = getVersion(sh); + } catch (err) { + return { + ok: false, + reason: `script build: ${errMsg(err)} (prefix ${sh.substring(0, 32)}…)`, + }; + } + + // ---- diagnostic: surface the field-level expectations engine eval cares about ---- + try { + const sourceOwnerPkh = sh.substring(6, 46); + const newOwnerPkh = newStasScriptHex.substring(6, 46); + const headSame = newStasScriptHex.substring(0, 6) === sh.substring(0, 6); + const tailSame = newStasScriptHex.substring(46) === sh.substring(46); + const lengthSame = newStasScriptHex.length === sh.length; + tokenLog.debug('[stas-transfer] source pkh →', sourceOwnerPkh); + tokenLog.debug('[stas-transfer] new pkh →', newOwnerPkh, '(matches recipient:', newOwnerPkh === recipientPkhHex, ')'); + tokenLog.debug('[stas-transfer] source.satoshis =', source.satoshis); + tokenLog.debug('[stas-transfer] stas version =', stasVersion); + tokenLog.debug('[stas-transfer] new script invariants — length same:', lengthSame, '· head same:', headSame, '· tail same:', tailSame); + if (!tailSame) { + // Surface the first diverging byte if the engine/tail isn't preserved. + const len = Math.min(newStasScriptHex.length, sh.length); + let firstDiff = -1; + for (let i = 46; i < len; i++) { + if (newStasScriptHex[i] !== sh[i]) { firstDiff = i; break; } + } + tokenLog.debug('[stas-transfer] first diverging hex index past owner-pkh:', firstDiff, + firstDiff >= 0 ? `(source="${sh.substring(firstDiff, firstDiff + 12)}…" new="${newStasScriptHex.substring(firstDiff, firstDiff + 12)}…")` : ''); + } + } catch { /* never block on logging */ } + + // 4. Build inputBEEF (Services + WoC fallback). + let inputBEEF: number[]; + try { + const built = await buildChainedAtomicBeef({ wallet: this.wallet, txid: source.txid }); + inputBEEF = built.beef; + } catch (err) { + return { ok: false, reason: `inputBEEF assembly: ${errMsg(err)}` }; + } + + // 5. Flip STAS outputs.spendable=true so createAction will accept it. + try { + const outputId: number | null = await stasQuery( + this.identityKey, + this.chain, + 'findOutputIdByOutpoint', + [source.txid, source.vout] + ); + if (outputId) { + await stasQuery(this.identityKey, this.chain, 'setOutputSpendable', [outputId, true]); + } + } catch { + /* best effort */ + } + + // 6. Lower the default basket's numberOfDesiredUTXOs to 0 to suppress + // change fragmentation. Save the previous value to restore after. + let previousBasketTarget: number | null = null; + try { + const res: any = await stasQuery( + this.identityKey, + this.chain, + 'setDefaultBasketUTXOTarget', + [0] + ); + previousBasketTarget = res?.previous ?? null; + tokenLog.debug('[stas-transfer] basket UTXO target: previous=', previousBasketTarget, 'set to 0; updated rows=', res?.updated); + } catch (err) { + tokenLog.warn( + '[stas-transfer] setDefaultBasketUTXOTarget failed — fragmentation will likely break the engine. ' + + 'Likely cause: stale dist-electron build. Fully restart `npm run dev`. Underlying error:', + err + ); + } + + // From here, ensure we restore the basket target on every exit path. + const restoreBasket = async () => { + if (previousBasketTarget != null) { + try { + await stasQuery( + this.identityKey, + this.chain, + 'setDefaultBasketUTXOTarget', + [previousBasketTarget] + ); + } catch { + /* best effort */ + } + } + }; + + try { + // 7. createAction. Wallet auto-funds (1 BSV input from default basket) + // + 1 change output (target=0 + balancing). + let createRes: any; + try { + createRes = await this.wallet.createAction( + { + labels: ['peertoken'], + inputBEEF, + inputs: [ + { + outpoint: `${source.txid}.${source.vout}`, + unlockingScriptLength: 4500, + inputDescription: 'STAS being transferred', + }, + ], + outputs: [ + { + lockingScript: newStasScriptHex, + satoshis: sendAmt, + outputDescription: 'STAS to recipient', + }, + ...(changeStasScriptHex != null + ? [{ + lockingScript: changeStasScriptHex, + satoshis: changeAmt, + outputDescription: 'STAS token change', + // Declare the basket at creation so the wallet tracks this + // self-owned output natively (mirrors BSV-21 token-change); + // the satellite linkage then finds its output row. + basket: STAS_BASKET, + customInstructions: JSON.stringify({ + brc42KeyId: args.senderChangeKeyId, + tokenId: args.tokenId, + }), + tags: ['stas'], + }] + : []), + ], + description: 'STAS transfer', + options: { + // Note: acceptDelayedBroadcast not set to false here, otherwise + // the wallet errors with "Undelayed createAction or signAction + // results require review" when prior failed attempts are queued. + // Let the wallet queue + monitor worker handle broadcast. + randomizeOutputs: false, + }, + } as any, + ORIGINATOR + ); + } catch (err) { + return { ok: false, reason: `createAction: ${errMsg(err)}` }; + } + + const signable = createRes?.signableTransaction; + if (!signable || !signable.tx) { + return { ok: false, reason: 'createAction did not return signableTransaction' }; + } + + // 8. Parse signable.tx (AtomicBEEF) → extract atomic tx → bsv-js Transaction. + let tx: any; + try { + const beef = Beef.fromBinary(signable.tx); + const atomicTxid = (beef as any).atomicTxid as string | undefined; + if (!atomicTxid) { + return { ok: false, reason: 'signable BEEF has no atomic txid' }; + } + const btx = beef.findTxid(atomicTxid); + if (!btx?.tx) { + return { ok: false, reason: `signable BEEF missing atomic tx ${atomicTxid}` }; + } + const rawTxBytes = btx.tx.toBinary(); + tx = new bsv.Transaction(Buffer.from(rawTxBytes).toString('hex')); + tx.inputs[0].output = new bsv.Transaction.Output({ + script: bsv.Script.fromHex(source.scriptHex), + satoshis: source.satoshis, + }); + } catch (err) { + return { ok: false, reason: `parse signable tx: ${errMsg(err)}` }; + } + + tokenLog.debug('[stas-transfer] tx.inputs.length=', tx.inputs.length); + for (let i = 0; i < tx.inputs.length; i++) { + const inp = tx.inputs[i]; + const prevTxidHex = + typeof inp.prevTxId === 'string' + ? inp.prevTxId + : Buffer.from(inp.prevTxId).toString('hex'); + const tag = i === 0 ? '(STAS)' : i === tx.inputs.length - 1 ? '(funding-last)' : '(extra)'; + tokenLog.debug(` in ${i} ${tag}: ${prevTxidHex.substring(0, 16)}…:${inp.outputIndex}`); + } + tokenLog.debug('[stas-transfer] outputs.length=', tx.outputs.length); + for (let v = 0; v < tx.outputs.length; v++) { + tokenLog.debug(` out ${v}: ${tx.outputs[v].satoshis} sats, len=${tx.outputs[v].script.toHex().length / 2}`); + } + + // The classic STAS engine encodes exactly ONE funding outpoint into the + // unlock witness (input 0 is the STAS being spent; the funding input is + // the wallet's BSV). If the default basket only holds fragments smaller + // than the fee, wallet-toolbox combines several — which the engine can't + // accept, and you get a cryptic "OP_EQUALVERIFY required equal" deep in + // script eval. Fail clean with actionable guidance instead. (Mirrors the + // DSTAS check in DstasTransferService.) + const fundingInputCount = tx.inputs.length - 1; + if (fundingInputCount < 1) { + return { ok: false, reason: 'no BSV funding input found in the assembled tx' }; + } + if (fundingInputCount > 1) { + return { + ok: false, + reason: + `STAS transfer requires exactly one BSV funding input, but the wallet ` + + `combined ${fundingInputCount} from the default basket — your BSV is ` + + `fragmented into amounts smaller than the fee. Consolidate by sending a ` + + `small BSV payment to yourself (or top up with one larger UTXO of a few ` + + `thousand sats), then retry the send.`, + }; + } + + // 9. Payment segment = the wallet's added change output (now at vout 1). + let paymentSegment: { satoshis: number; publicKey: string } | null = null; + for (let v = 1; v < tx.outputs.length; v++) { + const sHex = tx.outputs[v].script.toHex(); + if (sHex.startsWith('76a914') && sHex.endsWith('88ac') && sHex.length === 50) { + paymentSegment = { satoshis: tx.outputs[v].satoshis, publicKey: sHex.substring(6, 46) }; + break; + } + } + + // 10. partialSTASUnlockingScript fills tx.inputs[0].script with engine push-data. + try { + partialSTASUnlockingScript( + tx, + [ + { satoshis: sendAmt, publicKey: recipientPkhHex }, + changeStasScriptHex != null && args.senderChangeHash160 + ? { satoshis: changeAmt, publicKey: args.senderChangeHash160 } + : null, + paymentSegment, + ], + stasVersion, + paymentSegment === null + ); + } catch (err) { + return { ok: false, reason: `partial unlocking: ${errMsg(err)}` }; + } + + // 11. Sighash for input 0 + sign via wallet.createSignature. + let sigHex: string; + try { + const sourceLocking = bsv.Script.fromHex(source.scriptHex); + const satsBN = new bsv.crypto.BN(source.satoshis); + const preimage = bsv.Transaction.sighash.sighashPreimage( + tx, SIGHASH, 0, sourceLocking, satsBN + ); + const digestBuf = bsv.crypto.Hash.sha256sha256(preimage); + const digestBytes = Array.from(digestBuf as Buffer) as number[]; + + const sigRes = await this.wallet.createSignature( + { + protocolID: ownerDerivation.protocolID, + keyID: ownerDerivation.keyID, + counterparty: ownerDerivation.counterparty, + hashToDirectlySign: digestBytes, + } as any, + ORIGINATOR + ); + sigHex = toHex(sigRes.signature) + SIGHASH.toString(16).padStart(2, '0'); + } catch (err) { + return { ok: false, reason: `sighash/sign: ${errMsg(err)}` }; + } + + // 12. Final unlocking script. + let unlockingScriptHex: string; + try { + const partialASM = tx.inputs[0].script.toASM(); + const finalASM = `${partialASM} ${sigHex} ${ownerPubKey.toString('hex')}`; + unlockingScriptHex = bsv.Script.fromASM(finalASM).toHex(); + } catch (err) { + return { ok: false, reason: `unlocking assembly: ${errMsg(err)}` }; + } + + // 13. signAction. No acceptDelayedBroadcast override — the wallet + // queues and the monitor worker broadcasts asynchronously. The + // monitor's TaskSendWaiting handles relay + retry + WoC fallback. + let signResp: any; + try { + signResp = await this.wallet.signAction( + { + reference: signable.reference, + spends: { 0: { unlockingScript: unlockingScriptHex } }, + } as any, + ORIGINATOR + ); + } catch (err) { + return { ok: false, reason: `signAction: ${errMsg(err)}` }; + } + + tokenLog.debug('[stas-transfer] signAction result:', signResp); + + // signAction returns txid as soon as the tx is finalized, regardless of + // whether broadcast succeeded. Inspect sendWithResults to see if any + // input/output was rejected by mAPI. Surface real broadcast failures. + const sendResults: any[] = Array.isArray(signResp?.sendWithResults) + ? signResp.sendWithResults + : []; + const failed = sendResults.find((r) => r?.status === 'failed'); + if (failed) { + return { + ok: false, + reason: `broadcast failed: ${JSON.stringify(failed)} (txid was ${signResp?.txid})`, + }; + } + + const wocBase = this.chain === 'main' ? 'https://whatsonchain.com/tx/' : 'https://test.whatsonchain.com/tx/'; + tokenLog.info(`[stas-transfer] BROADCAST ✓ txid: ${signResp?.txid} ${wocBase}${signResp?.txid}`); + + // 14. Link the sender's token-change output (vout 1 — outputs are not + // randomized) into the satellite tables. The Assets view reads STAS + // holdings from `listStasOutputs`, NOT from the basket, so without + // this the remainder of a partial send stays invisible until a + // discovery scan happens to pick it back up off the chain — even + // though we minted the output ourselves and know everything about it. + // `skipInternalize` because createAction already declared its basket. + // Idempotent, so a caller that registers the change itself (the peer + // settlement adapter does) simply gets 'already registered'. + if (changeStasScriptHex != null && args.senderChangeHash160 && signResp?.txid) { + try { + const meta = parseClassicStasMetadata(source.scriptHex); + const r = await new StasRegistration(this.wallet, this.identityKey, this.chain).register({ + txid: signResp.txid, + vout: 1, + tokenSatoshis: changeAmt, + ownerFieldHash160: args.senderChangeHash160, + brc42KeyId: args.senderChangeKeyId ?? source.brc42KeyId, + parsed: { + tokenId: args.tokenId ?? '', + ownerFieldHash160: args.senderChangeHash160, + symbol: meta?.symbol ?? undefined, + flagsHex: meta?.flagsHex ?? '', + serviceFields: [], optionalData: [], + freezeEnabled: false, confiscationEnabled: false, frozen: false, actionData: {}, + } as any, + protocol: { id: 'stas', basketName: STAS_BASKET }, + skipInternalize: true, + }); + if (!r.registered && r.reason !== 'already registered') { + tokenLog.warn(`[stas-transfer] token-change NOT registered: ${r.reason} (scan will recover)`); + } + } catch (err) { + // Best-effort: the output exists on-chain and in the basket either + // way, and a scan re-registers it. Never fail a broadcast tx here. + tokenLog.warn(`[stas-transfer] token-change registration threw: ${errMsg(err)} (scan will recover)`); + } + } + + return { ok: true, txid: signResp?.txid, beef: signResp?.tx }; + } finally { + await restoreBasket(); + } + } +} + +function errMsg(err: unknown): string { + return err instanceof Error ? err.message : String(err); +} + +function toHex(bytes: number[] | Uint8Array): string { + const arr = Array.isArray(bytes) ? bytes : Array.from(bytes); + return arr.map((b) => b.toString(16).padStart(2, '0')).join(''); +} diff --git a/src/lib/services/stas/buildChainedAtomicBeef.ts b/src/lib/services/stas/buildChainedAtomicBeef.ts new file mode 100644 index 0000000..3337d6b --- /dev/null +++ b/src/lib/services/stas/buildChainedAtomicBeef.ts @@ -0,0 +1,208 @@ +/** + * buildChainedAtomicBeef — assemble an AtomicBEEF for a target txid even when + * the target itself is unconfirmed (mempool). + * + * Why this exists. `wallet.internalizeAction(...)` ultimately calls + * `Beef.verify(chainTracker, false)` from `@bsv/sdk`. That validator does NOT + * require every tx in the BEEF to have its own merkle proof — a tx with full + * rawTx but no proof is accepted **as long as its inputs chain back to a + * confirmed bump somewhere in the BEEF**. The hardcoded `allowTxidOnly: false` + * in wallet-toolbox only rejects txid-only entries (hash-only, no bytes), not + * proof-less full rawTx entries. + * + * Net: to internalize a mempool STAS, we need to bundle the target tx PLUS its + * input ancestry recursively until every leaf input has a merkle proof (or is + * coinbase). For a typical Issue tx still in mempool the chain is short: + * Issue (mempool) → Contract (mempool) → Funding (confirmed, has proof). + * + * Recursion is capped (default 10 hops) — STAS chains stay short in practice, + * the cap protects against pathological inputs. + */ + +import { Beef, MerklePath, Transaction, type WalletInterface } from '@bsv/sdk'; +import { wocFetch } from '../../utils/RateLimitedFetch'; + +const WOC_BASE = 'https://api.whatsonchain.com/v1/bsv/main'; + +function hexToBytes(hex: string): number[] { + const out: number[] = []; + for (let i = 0; i < hex.length; i += 2) { + out.push(parseInt(hex.substring(i, i + 2), 16)); + } + return out; +} + +async function fetchRawTxFromWoc(txid: string): Promise { + try { + const res = await wocFetch.fetch(`${WOC_BASE}/tx/${txid}/hex`); + if (!res.ok) return null; + const hex = (await res.text()).trim(); + if (!/^[0-9a-f]+$/i.test(hex)) return null; + return hexToBytes(hex); + } catch { + return null; + } +} + +async function fetchMerklePathFromWoc(txid: string): Promise { + try { + // WoC's "tsc" proof variant; we convert to BUMP via the SDK. + const res = await wocFetch.fetch(`${WOC_BASE}/tx/${txid}/proof/tsc`); + if (!res.ok) return null; + const arr = await res.json(); + const tsc = Array.isArray(arr) ? arr[0] : arr; + if (!tsc || typeof tsc.index !== 'number' || !Array.isArray(tsc.nodes)) return null; + // Build a minimal BUMP path: 1 level if a single coinbase, otherwise + // walk the nodes from leaf upward. The SDK provides no TSC->BUMP + // helper, so we construct the path[]] structure by hand: level 0 has + // the txid at `index`; each subsequent level walks up halving the + // index. The tsc.nodes give us the sibling hashes per level. + const path: any[] = [ + [{ offset: tsc.index, hash: txid, txid: true }], + ]; + let idx = tsc.index; + for (const node of tsc.nodes) { + const siblingOffset = idx ^ 1; + const hashHex = typeof node === 'string' ? node : node?.hash; + // '*' means "duplicate the other side" — we omit then. + if (hashHex && hashHex !== '*') { + path.push([{ offset: siblingOffset, hash: hashHex }]); + } + idx >>= 1; + } + const blockHeight = + typeof tsc.blockHeight === 'number' + ? tsc.blockHeight + : typeof tsc.height === 'number' + ? tsc.height + : 0; + return new MerklePath(blockHeight, path as any); + } catch { + return null; + } +} + +const COINBASE_TXID = + '0000000000000000000000000000000000000000000000000000000000000000'; + +export interface BuildChainedBeefArgs { + wallet: WalletInterface; + /** Target txid to internalize. */ + txid: string; + /** Max input-chain hops to walk back before giving up. Default 10. */ + maxDepth?: number; +} + +export interface BuildChainedBeefResult { + /** AtomicBEEF bytes ready for `internalizeAction(tx: ...)`. */ + atomicBeef: number[]; + /** + * Plain BEEF bytes (no AtomicBEEF prefix) ready for `createAction(inputBEEF: ...)`. + * Same payload as `atomicBeef` minus the BRC-95 prefix + atomic txid. + */ + beef: number[]; + /** Total txs included in the BEEF (target + ancestors). */ + txCount: number; + /** + * Number of input-chain hops walked. `0` = target tx had its own merkle path. + * Useful for telemetry and detecting "this took a while". + */ + depth: number; +} + +/** + * Build an AtomicBEEF for `txid`. Walks the input chain backwards as needed + * until every leaf has a merkle proof. Throws if the chain exceeds `maxDepth` + * or any required tx cannot be fetched. + */ +export async function buildChainedAtomicBeef( + args: BuildChainedBeefArgs +): Promise { + const maxDepth = args.maxDepth ?? 10; + const services: any = (args.wallet as any).getServices?.(); + if (!services) { + throw new Error('wallet.getServices() unavailable'); + } + + const beef = new Beef(); + const seen = new Set(); + let maxDepthSeen = 0; + + async function walk(currentTxid: string, depth: number): Promise { + if (depth > maxDepth) { + throw new Error( + `chained BEEF: input-chain depth exceeded ${maxDepth} hops at ${currentTxid}` + ); + } + if (seen.has(currentTxid)) return; + seen.add(currentTxid); + if (depth > maxDepthSeen) maxDepthSeen = depth; + + // 1. fetch rawTx — Services first, then WoC fallback. Some txs the + // wallet has touched via internalize don't reappear through + // Services.getRawTx; WoC has them as long as they're on chain. + let rawTxBytes: number[] | null = null; + try { + const r = await services.getRawTx(currentTxid); + if (r?.rawTx) rawTxBytes = r.rawTx as number[]; + } catch { + /* fall through to WoC */ + } + if (!rawTxBytes) { + rawTxBytes = await fetchRawTxFromWoc(currentTxid); + } + if (!rawTxBytes) { + throw new Error( + `chained BEEF: no rawTx for ${currentTxid} (neither Services nor WoC returned bytes)` + ); + } + + const tx = Transaction.fromBinary(rawTxBytes); + + // 2. try to get a merkle proof — Services first, then WoC. + let mp: MerklePath | undefined; + try { + const mpRes: any = await services.getMerklePath(currentTxid); + if (mpRes?.merklePath) { + mp = mpRes.merklePath as MerklePath; + } + } catch { + /* fall through */ + } + if (!mp) { + const fallback = await fetchMerklePathFromWoc(currentTxid); + if (fallback) mp = fallback; + } + + if (mp) { + // Confirmed leaf: attach the proof and stop recursion on this branch. + tx.merklePath = mp; + beef.mergeTransaction(tx); + return; + } + + // Mempool: add the rawTx with no proof, then chain back through inputs. + beef.mergeTransaction(tx); + + for (const input of tx.inputs) { + const sourceTxid: string | undefined = + (input as any).sourceTXID ?? input.sourceTransaction?.id('hex'); + if (!sourceTxid) { + throw new Error( + `chained BEEF: input on ${currentTxid} has no source txid` + ); + } + if (sourceTxid === COINBASE_TXID) continue; + await walk(sourceTxid, depth + 1); + } + } + + await walk(args.txid, 0); + + return { + atomicBeef: beef.toBinaryAtomic(args.txid), + beef: beef.toBinary(), + txCount: seen.size, + depth: maxDepthSeen, + }; +} diff --git a/src/lib/services/stas/constants.ts b/src/lib/services/stas/constants.ts new file mode 100644 index 0000000..78088f4 --- /dev/null +++ b/src/lib/services/stas/constants.ts @@ -0,0 +1,30 @@ +/** + * BRC-42 derivation scheme for STAS owner keys. + * + * Receive keys are derived deterministically so a resync can regenerate every + * key from just the persisted high-water mark. The token id is recorded after + * discovery — never baked into the keyID — so a never-before-seen token is + * still discoverable. + */ + +/** BRC-42 protocol: security level 2, stable protocol-string namespace. */ +export const STAS_PROTOCOL_ID = [2, 'stas token ownership'] as [2, string]; + +/** STAS owner keys are self-owned. */ +export const STAS_COUNTERPARTY = 'self'; + +/** keyID for the Nth receive key — a monotonic counter, 1-based. */ +export const stasKeyId = (index: number): string => `recv ${index}`; + +/** + * Default gap limit for ownership scans beyond the high-water mark. + * + * BIP-44's standard gap of 20. Kept deliberately modest because discovery + * migrated to WhatsOnChain, where every gap address costs TWO rate-limited + * network calls (STAS `?script=true` + DSTAS-by-hash160). The old value of 100 + * meant a scan of `hwm + 100` addresses × 2 endpoints = 200+ WOC requests at + * 2 req/s, which reliably tripped WOC's 429 throttle — and a 429'd address + * degrades to "empty", risking missed tokens. Tokens land at *issued* + * addresses (≤ hwm), so a 20-address gap beyond hwm is ample coverage. + */ +export const STAS_GAP_LIMIT = 20; diff --git a/src/lib/services/stas/dstasParser.ts b/src/lib/services/stas/dstasParser.ts new file mode 100644 index 0000000..bebd0db --- /dev/null +++ b/src/lib/services/stas/dstasParser.ts @@ -0,0 +1,95 @@ +/** + * DSTAS locking-script parser. + * + * The single import site of `dxs-bsv-token-sdk` for ownership recognition — + * the rest of bsv-desktop works against the normalized `ParsedDstas` shape and + * never touches the SDK's reader types directly. + */ + +import { ScriptType, toHex } from 'dxs-bsv-token-sdk/bsv'; +// `LockingScriptReader` is namespace-imported from the SDK's leaf module +// because Rollup's CommonJS plugin refuses to surface it as a named ESM +// export — neither the `/bsv` aggregator (which uses `__exportStar` to +// forward from ./script) nor the leaf module (which uses the canonical +// `exports.X = X` pattern) trip its static-named-export detection. Vite +// dev (esbuild pre-bundle) sees it; Vite prod (Rollup) doesn't. +// +// The namespace import works because it doesn't ask Rollup to verify any +// specific named export — the bundle just gets the whole module object +// and we pluck the property at module init time. The leaf sub-path is +// whitelisted in the SDK's `exports` field (vendor/.../package.json). +import * as LockingScriptReaderModule from 'dxs-bsv-token-sdk/script/read/locking-script-reader'; +const { LockingScriptReader } = LockingScriptReaderModule; + +export interface ParsedDstas { + /** 20-byte owner field (PKH), hex — what ownership recognition matches on. */ + ownerFieldHash160: string; + /** Redemption / protoID PKH (the token id), hex. */ + tokenId: string; + freezeEnabled: boolean; + confiscationEnabled: boolean; + /** Raw flags region, hex. */ + flagsHex: string; + /** Service-field byte regions, hex. */ + serviceFields: string[]; + /** + * Optional-data region, hex per entry. DSTAS_SCRIPT_INVARIANTS.md §7 + * requires byte-exact propagation onto descendant DSTAS outputs that + * continue the same asset leg — losing this on a transfer breaks + * subsequent spend validation. Required for DSTAS send. + */ + optionalData: string[]; + /** + * Action-data field token. For a freshly-issued or post-transfer DSTAS, + * this is `{ opCode: OP_0 }` (no action) or `{ opCode: OP_2 }` (frozen). + * Surface both shapes — `data` for non-empty action bytes, + * `opCode` for sentinel opcodes — so the transfer builder can echo it + * or substitute the neutral `OP_0` marker for a fresh transfer. + */ + actionData: { data?: string; opCode?: number }; + /** True iff the action-data marker indicates frozen state (OP_2 or 0x02 prefix). */ + frozen: boolean; +} + +/** + * Parse a locking script as DSTAS. Returns `null` — never throws — for any + * script that is not DSTAS or whose owner field is not a 20-byte PKH (other + * identity-field shapes are not wallet-recognisable and are treated as foreign). + */ +export function parseDstasLockingScript(scriptHex: string): ParsedDstas | null { + let reader: any; + try { + reader = LockingScriptReader.readHex(scriptHex); + } catch { + return null; + } + if (!reader || reader.ScriptType !== ScriptType.dstas) return null; + + const d = reader.Dstas; + if (!d || !d.Owner || d.Owner.length !== 20) return null; + + // DSTAS action-data semantics per DSTAS_LOCKING_TEMPLATE_NOTES.md: + // - OP_0 (0x00) → empty action, not frozen + // - OP_2 (0x52) → empty action, frozen + // - bytes prefixed 0x02 → non-empty action, frozen + // - other bytes → non-empty action, not frozen + const actionDataRaw: Uint8Array | undefined = d.ActionDataRaw; + const actionDataOpCode: number | undefined = d.ActionDataOpCode; + const frozen = + actionDataOpCode === 0x52 || + (!!actionDataRaw && actionDataRaw.length > 0 && actionDataRaw[0] === 0x02); + + return { + ownerFieldHash160: toHex(d.Owner), + tokenId: toHex(d.Redemption), + freezeEnabled: !!d.FreezeEnabled, + confiscationEnabled: !!d.ConfiscationEnabled, + flagsHex: toHex(d.Flags), + serviceFields: (d.ServiceFields || []).map((f: any) => toHex(f)), + optionalData: (d.OptionalData || []).map((b: any) => toHex(b)), + actionData: actionDataRaw + ? { data: toHex(actionDataRaw) } + : { opCode: actionDataOpCode }, + frozen, + }; +} diff --git a/src/lib/services/stas/findCreateContractTxid.ts b/src/lib/services/stas/findCreateContractTxid.ts new file mode 100644 index 0000000..80a6172 --- /dev/null +++ b/src/lib/services/stas/findCreateContractTxid.ts @@ -0,0 +1,143 @@ +/** + * findCreateContractTxid — walk back the input[0] chain from a STAS UTXO until + * the parent's source output is NOT a STAS script. That `current` tx is the + * issuer's CreateContract — its txid is the canonical tokenId for the lineage. + * + * Classic STAS doesn't carry an explicit tokenId in the locking script. Every + * UTXO in the same issuance lineage chains back to the same CreateContract, + * so the contract txid is the natural identifier — stable across transfers + * and identical for all UTXOs ever issued from that contract. + * + * Performance: each step is one rawTx fetch. For most demos chains are ≤ 5 + * deep so we stay under ~10 fetches. Falls back to WoC when wallet Services + * doesn't have the rawTx (e.g., for ancestors the wallet never internalised). + */ + +import { Transaction, type WalletInterface } from '@bsv/sdk'; +import { wocFetch } from '../../utils/RateLimitedFetch'; + +const WOC_BASE = 'https://api.whatsonchain.com/v1/bsv/main'; +const DEFAULT_MAX_DEPTH = 30; + +function hexToBytes(hex: string): number[] { + const out: number[] = []; + for (let i = 0; i < hex.length; i += 2) { + out.push(parseInt(hex.substring(i, i + 2), 16)); + } + return out; +} + +async function fetchRawTx( + wallet: WalletInterface, + txid: string +): Promise { + const services: any = (wallet as any).getServices?.(); + if (services) { + try { + const r = await services.getRawTx(txid); + if (r?.rawTx) return r.rawTx as number[]; + } catch { + /* fall through */ + } + } + try { + const res = await wocFetch.fetch(`${WOC_BASE}/tx/${txid}/hex`); + if (!res.ok) return null; + const hex = (await res.text()).trim(); + if (!/^[0-9a-f]+$/i.test(hex)) return null; + return hexToBytes(hex); + } catch { + return null; + } +} + +/** + * Classic-STAS heuristic: P2PKH-like prefix (`76 a9 14 <20-byte pkh>`), + * followed by `88 ac` (OP_EQUALVERIFY OP_CHECKSIG), then `69` (OP_VERIFY). + * Real STAS engines extend far past this; we only need to detect the prefix. + */ +function isStasScript(scriptHex: string): boolean { + if (typeof scriptHex !== 'string' || scriptHex.length < 56) return false; + if (!scriptHex.startsWith('76a914')) return false; + return scriptHex.substring(46, 52) === '88ac69'; +} + +export interface FindCreateContractArgs { + wallet: WalletInterface; + txid: string; + maxDepth?: number; +} + +export interface FindCreateContractResult { + /** The CreateContract txid (canonical classic-STAS tokenId). */ + tokenId: string | null; + /** Number of input-chain hops walked. 0 means `txid` IS the CreateContract. */ + depth: number; + /** Reason `tokenId` is null, when it is. */ + reason?: string; +} + +/** + * Walk back input[0] until parent output is non-STAS. Returns the current tx's + * txid as the CreateContract / tokenId. Caps at `maxDepth` (default 30). + */ +export async function findCreateContractTxid( + args: FindCreateContractArgs +): Promise { + const maxDepth = args.maxDepth ?? DEFAULT_MAX_DEPTH; + let currentTxid = args.txid; + for (let i = 0; i < maxDepth; i++) { + const rawTx = await fetchRawTx(args.wallet, currentTxid); + if (!rawTx) { + return { tokenId: null, depth: i, reason: `no rawTx for ${currentTxid}` }; + } + let tx: Transaction; + try { + tx = Transaction.fromBinary(rawTx); + } catch (err) { + return { + tokenId: null, + depth: i, + reason: `tx parse for ${currentTxid}: ${err instanceof Error ? err.message : String(err)}`, + }; + } + if (tx.inputs.length === 0) { + return { tokenId: null, depth: i, reason: `${currentTxid} has no inputs (coinbase?)` }; + } + const input0 = tx.inputs[0]; + const parentTxid = (input0 as any).sourceTXID ?? (input0 as any).sourceTxId ?? null; + if (!parentTxid) { + return { tokenId: null, depth: i, reason: `${currentTxid} input[0] missing sourceTXID` }; + } + const parentRaw = await fetchRawTx(args.wallet, parentTxid); + if (!parentRaw) { + // Can't see the parent — current tx is likely the CreateContract since + // walletable ancestry stops. Best-effort: treat current as the tokenId. + return { + tokenId: currentTxid, + depth: i, + reason: `parent ${parentTxid} unreachable; treating ${currentTxid} as CreateContract`, + }; + } + let parentTx: Transaction; + try { + parentTx = Transaction.fromBinary(parentRaw); + } catch { + return { tokenId: currentTxid, depth: i }; + } + const parentVout = (input0 as any).sourceOutputIndex ?? (input0 as any).vout ?? 0; + const parentOutput = parentTx.outputs[parentVout]; + if (!parentOutput) { + return { tokenId: currentTxid, depth: i }; + } + const parentScriptHex = parentOutput.lockingScript.toHex(); + if (isStasScript(parentScriptHex)) { + // Parent is also STAS — walk back. + currentTxid = parentTxid; + continue; + } + // Parent is non-STAS (BSV funding). `currentTxid` IS the CreateContract. + return { tokenId: currentTxid, depth: i }; + } + return { tokenId: null, depth: maxDepth, reason: 'maxDepth exceeded' }; +} diff --git a/src/lib/services/stas/index.ts b/src/lib/services/stas/index.ts new file mode 100644 index 0000000..f57c5e9 --- /dev/null +++ b/src/lib/services/stas/index.ts @@ -0,0 +1,17 @@ +/** + * STAS BRC-42 ownership services. + * + * - constants BRC-42 derivation scheme + * - dstasParser DSTAS locking-script parsing (the only SDK import site) + * - StasKeyDeriver derive STAS receive keys, manage the receive counter + * - StasOwnershipService recognise wallet-owned DSTAS outputs + */ + +export * from './constants'; +export * from './dstasParser'; +export * from './StasKeyDeriver'; +export * from './StasOwnershipService'; +export * from './StasRegistration'; +export * from './StasDiscoveryService'; +export * from './StasTransferService'; +export * from './stasIpc'; diff --git a/src/lib/services/stas/parseClassicStasMetadata.ts b/src/lib/services/stas/parseClassicStasMetadata.ts new file mode 100644 index 0000000000000000000000000000000000000000..eec921086c4fef93382a6871758ccd0ca667755f GIT binary patch literal 4028 zcmd5<+j1I55Y00`k@kyOBv>xS1WQON+lfmmS7b^;l?Rn747;FGYx-rK9e9%L++{C&ctjDt(XHmoVRH#lF7AMlwZIsH%gNhINJMZOr*n`&9%ssj z$$|q<=W)tmCc-tu5=6#+Uh*c)mI@S3e;WUI@!jO=;+%|W7&)KEA_ZpV6^j$X0Su&K zvxI|Ou#DqgT!168^^>eic%O5o_kI9y``{_}nWULUXfqu`Eq;;EOC}G?ie>`m^@hyie z=TW>OMBen90ejQ!!>HG3(IJrCE{}B0u-Z`rbi}%T#OJ( zNnR6jb`J}_^5IJIXqiAHatLEKPlZ%*Abs)!@nsiWE%S7Y=8zf-?)v7iwyD+dEDFn* z@>9Z8qk2bSF~Dh$&Jg{D!lO}v+X8!gi4{UXK`_h@2duMwW^Cz!Ts0WV)#dv0Jvhd1~|rLmW1d1tR2#K$nEGRF(evayc`ZLs*&`DcWr`p*v_88+2SO&)K@*&oKpyNL zLC>ruXVC{2vvQD9>XLYSJVmx0x}ziLI2XbBpJ6h1^}2|1PO7?AYyuXWm z%Mah?`0)SbxDD8=F9xjd0_N^wK~DdR`vz{`aA%y&)Bjds!bxo%mu^5{-gvw|1O7L!RDosaib30~K6NKD34qa_S0)5HalgGZx%}62R{=h59W*4e|?1;*h9P z`Pz0K8=;in!vq!Nx7tGP)t4%24eL#KKx2v}D6$yU{qHKwL1Ajtgv|*@mI&T>B48_811QSDH?GfukULlT_Z6nvHoOpkyu*4 zSB2n?x_~D8R76ZNe2CMq6m{TrRs+@mmIe!v^U o`$WMZgy0WQdO~Uj5)=huzb$Z zNQhcxO?i)!K85LkO^y7*lnUaI<8YF!bzP90dOz^$bA$5PTuCQU&q7jlB@bliEDibUQ{>eL%t#NSs=8rR zN)=10D~ZntY2u0WajKj$#*LMNygKR*8tXcCfThB$-UC_uu zDhae33xSO+25c?xZT6&I<7tH+M-8lBgQnIt>7{Z*@k1jMjB2q?S4?{I@fAKPk=w2& z9K4>EAYMSSZ;mu$=MXg`#@7}=4$<}4W ztoDJ{pAZ~d#*5L0pL3m4Ui { + const api = + typeof window !== 'undefined' ? (window as any).electronAPI?.stas : undefined; + if (!api) return undefined; + const res = await api.query(identityKey, chain, method, args); + if (!res || !res.success) { + throw new Error(`stas:query ${method} failed: ${res && res.error}`); + } + return res.result; +} diff --git a/src/lib/services/tokens/BSV21ProtocolAdapter.ts b/src/lib/services/tokens/BSV21ProtocolAdapter.ts new file mode 100644 index 0000000..fd87f86 --- /dev/null +++ b/src/lib/services/tokens/BSV21ProtocolAdapter.ts @@ -0,0 +1,101 @@ +/** + * BSV21ProtocolAdapter — wraps the bsv21/* service modules into the + * cross-protocol `TokenProtocolAdapter` contract declared in Part A. + * + * Note: BSV-21 discovery is BESPOKE (BSV21DiscoveryService — 1Sat REST, + * different from STAS's per-address Bitails scan). The registry's + * `find(scriptHex)` path is still useful for type detection elsewhere + * (e.g. if a foreign output ends up in a token basket and we want to + * recognise it), but the main discovery loop calls + * `stas.bsv21Discovery.scan()` directly. + */ + +import { BSV21_BASKET } from '../../constants/baskets'; +import { parseBsv21LockingScript } from './bsv21/inscription'; +import type { BSV21TransferService } from './bsv21/BSV21TransferService'; +import type { + TokenProtocolAdapter, + ParsedTokenOutput, + TransferArgs, + TransferResult, +} from './TokenProtocolAdapter'; + +export class BSV21ProtocolAdapter implements TokenProtocolAdapter { + readonly id = 'bsv-21' as const; + readonly basketName = BSV21_BASKET; + readonly displayName = 'BSV-21'; + readonly transferSupported = true; + + /** + * `transferService` carries the wallet + indexer + deriver context the + * BSV-21 send flow needs. The cross-protocol `TransferArgs` shape we + * receive only covers the input outpoint + recipient + brc42KeyId — for + * BSV-21 we also need the token id, amount, and decimals to assemble + * the destination output. Those come from the input's basket TAGS, + * which the renderer (`AssetsPage`) reads at `listBasketOutputs` time + * and threads through via a richer args object than the cross-protocol + * interface exposes. + */ + constructor(private readonly transferService: BSV21TransferService) {} + + async parseOutput(scriptHex: string): Promise { + const parsed = parseBsv21LockingScript(scriptHex); + if (!parsed) return null; + return { + tokenId: parsed.id, + ownerFieldHash160: parsed.ownerHash160, + symbol: parsed.sym, + satoshisPerToken: 1, + }; + } + + /** + * Cross-protocol transfer entry point. AssetsPage passes BSV-21- + * specific extras (tokenId, amt, dec, sym, icon, sendAmount) through + * a richer args shape — see `Bsv21SendArgs` below; callers that go + * through this adapter method should cast their args accordingly. + */ + async transfer(args: TransferArgs): Promise { + const extra = args as TransferArgs & Bsv21SendExtras; + if (!extra.tokenId || !extra.amount || !extra.sourceAmt) { + return { + ok: false, + reason: 'BSV-21 transfer requires tokenId, amount, and sourceAmt — caller must thread these through', + }; + } + return this.transferService.transfer({ + source: { + txid: args.source.txid, + vout: args.source.vout, + scriptHex: args.source.scriptHex, + satoshis: args.source.satoshis, + brc42KeyId: args.source.brc42KeyId, + tokenId: extra.tokenId, + amt: extra.sourceAmt, + dec: extra.dec, + sym: extra.sym, + icon: extra.icon, + }, + amount: extra.amount, + recipientAddress: args.recipientAddress, + }); + } +} + +/** + * Extra fields callers attach to `TransferArgs` when sending BSV-21. + * The cross-protocol interface stays minimal; BSV-21 carries token- + * specific context separately. Exporting this type so AssetsPage's + * send dialog can shape the args correctly at call time. + */ +export interface Bsv21SendExtras { + /** Token id of the source UTXO (`txid_vout`). */ + tokenId: string; + /** Raw token amount the source UTXO holds (stringified bigint). */ + sourceAmt: string; + /** Raw token amount to send (stringified bigint). */ + amount: string; + dec?: number; + sym?: string; + icon?: string; +} diff --git a/src/lib/services/tokens/DstasProtocolAdapter.ts b/src/lib/services/tokens/DstasProtocolAdapter.ts new file mode 100644 index 0000000..5525983 --- /dev/null +++ b/src/lib/services/tokens/DstasProtocolAdapter.ts @@ -0,0 +1,47 @@ +/** + * DstasProtocolAdapter — STAS v3 / "DSTAS", parsed via dxs-bsv-token-sdk. + * + * Discovery + registration land via StasDiscoveryService's registry + * dispatch. Transfer goes through DstasTransferService (F3): the SDK's + * `buildDstasLockingScript` gives us the new output, wallet-toolbox + * handles funding + broadcast via createAction/signAction, and the + * DSTAS unlocking script is hand-assembled to match the template's + * expected witness format (mirror of the SDK's InputBuilder.sign). + */ + +import { DSTAS_BASKET } from '../../constants/baskets'; +import { parseDstasLockingScript } from '../stas/dstasParser'; +import type { + TokenProtocolAdapter, + ParsedTokenOutput, + TransferArgs, + TransferResult, +} from './TokenProtocolAdapter'; +import type { DstasTransferService } from './dstas/DstasTransferService'; + +export class DstasProtocolAdapter implements TokenProtocolAdapter { + readonly id = 'dstas' as const; + readonly basketName = DSTAS_BASKET; + readonly displayName = 'DSTAS'; + readonly transferSupported = true; + + constructor(private readonly transferService: DstasTransferService) {} + + async parseOutput(scriptHex: string): Promise { + const parsed = parseDstasLockingScript(scriptHex); + if (!parsed) return null; + return { + tokenId: parsed.tokenId, + ownerFieldHash160: parsed.ownerFieldHash160, + flagsHex: parsed.flagsHex, + satoshisPerToken: 1, + freezeEnabled: parsed.freezeEnabled, + confiscationEnabled: parsed.confiscationEnabled, + serviceFields: parsed.serviceFields, + }; + } + + async transfer(args: TransferArgs): Promise { + return this.transferService.transfer(args); + } +} diff --git a/src/lib/services/tokens/StasProtocolAdapter.ts b/src/lib/services/tokens/StasProtocolAdapter.ts new file mode 100644 index 0000000..6547f6a --- /dev/null +++ b/src/lib/services/tokens/StasProtocolAdapter.ts @@ -0,0 +1,66 @@ +/** + * StasProtocolAdapter — classic STAS, the original on-chain token engine. + * + * Recognises locking scripts by the canonical P2PKH+OP_VERIFY prefix + * (`76a914 88ac69 …`), extracts symbol/flags from the OP_RETURN + * tail via parseClassicStasMetadata, and walks back through tx inputs + * to the CreateContract txid (canonical tokenId) via findCreateContractTxid. + * + * Transfer delegates to the existing StasTransferService, which carries + * the BRC-42-unlock + stas-js engine logic. + */ + +import { STAS_BASKET } from '../../constants/baskets'; +import { parseClassicStasMetadata } from '../stas/parseClassicStasMetadata'; +import { findCreateContractTxid } from '../stas/findCreateContractTxid'; +import { StasTransferService } from '../stas/StasTransferService'; +import type { + TokenProtocolAdapter, + ParseContext, + ParsedTokenOutput, + TransferArgs, + TransferResult, +} from './TokenProtocolAdapter'; + +export class StasProtocolAdapter implements TokenProtocolAdapter { + readonly id = 'stas' as const; + readonly basketName = STAS_BASKET; + readonly displayName = 'STAS'; + readonly transferSupported = true; + + constructor(private readonly transferService: StasTransferService) {} + + async parseOutput(scriptHex: string, ctx?: ParseContext): Promise { + const meta = parseClassicStasMetadata(scriptHex); + if (!meta) return null; + + // Best-effort: derive canonical tokenId by walking back to the + // CreateContract tx. Caller may not have supplied a wallet (parse-only + // contexts), in which case we leave tokenId empty — registration will + // backfill it later. + let tokenId = ''; + if (ctx?.wallet && ctx?.txid) { + try { + const cc = await findCreateContractTxid({ wallet: ctx.wallet, txid: ctx.txid }); + if (cc.tokenId) tokenId = cc.tokenId; + } catch { + // Leave tokenId empty; non-fatal. + } + } + + return { + tokenId, + ownerFieldHash160: meta.ownerFieldHash160, + symbol: meta.symbol ?? undefined, + flagsHex: meta.flagsHex ?? undefined, + satoshisPerToken: 1, + freezeEnabled: false, + confiscationEnabled: false, + serviceFields: [], + }; + } + + async transfer(args: TransferArgs): Promise { + return this.transferService.transfer(args); + } +} diff --git a/src/lib/services/tokens/TokenProtocolAdapter.ts b/src/lib/services/tokens/TokenProtocolAdapter.ts new file mode 100644 index 0000000..82da0cc --- /dev/null +++ b/src/lib/services/tokens/TokenProtocolAdapter.ts @@ -0,0 +1,115 @@ +/** + * TokenProtocolAdapter — single seam between protocol-specific logic + * (STAS, DSTAS, BSV-21) and the shared pipeline (DB, IPC, UI). + * + * Every protocol the wallet recognises is represented by exactly one + * adapter instance. The adapter answers: + * - "is this locking script one of mine?" (parseOutput) + * - "which basket do my UTXOs go in?" (basketName) + * - "can I build a transfer right now?" (transferSupported) + * - "build me a transfer" (transfer, when supported) + * + * Adapters are held in a TokenProtocolRegistry and looked up by id. + */ + +export type TokenProtocolId = 'stas' | 'dstas' | 'bsv-21'; + +/** + * Output-level data every protocol must produce when it recognises one of + * its scripts. A superset of the existing `ParsedDstas` so DSTAS can keep + * its current behavior without losing fields. Protocols may omit anything + * not applicable to them. + */ +export interface ParsedTokenOutput { + /** Canonical token identifier — what the UI groups by. */ + tokenId: string; + /** 20-byte owner field (PKH), hex — what ownership recognition matches on. */ + ownerFieldHash160: string; + /** Display ticker, when known at parse time. */ + symbol?: string; + /** Protocol-specific flags region, hex. */ + flagsHex?: string; + /** Bytes-per-token. STAS=1; BSV-21 uses `decimals` instead. */ + satoshisPerToken?: number; + /** STAS/DSTAS engine feature flags. */ + freezeEnabled?: boolean; + confiscationEnabled?: boolean; + /** Raw protocol service fields, hex (DSTAS). */ + serviceFields?: string[]; +} + +/** + * Optional context passed to `parseOutput` for protocols that need more + * than the locking script to identify a token (e.g. classic STAS walks + * back through tx inputs to find its CreateContract txid). + */ +export interface ParseContext { + /** Outpoint the script lives at — supplied when known. */ + txid?: string; + vout?: number; + /** Wallet interface for SDK calls that need on-chain reads. */ + wallet?: any; +} + +export interface TransferArgs { + source: { + txid: string; + vout: number; + scriptHex: string; + satoshis: number; + brc42KeyId: string; + }; + recipientAddress: string; + /** + * Token amount to send (satoshi-denominated for STAS/DSTAS). Omit to send the + * whole UTXO. When less than `source.satoshis` the transfer SPLITS: the + * recipient gets `amount` and the remainder returns to the sender as + * token-change at `senderChangeHash160`. BSV-21 carries its amount via + * `Bsv21SendExtras` instead (raw bigint string), so it ignores this field. + */ + amount?: number; + /** Owner pkh (hex) for the sender's token-change output on a partial send. */ + senderChangeHash160?: string; + /** BRC-42 keyId of the sender's change receive key (for createAction tracking). */ + senderChangeKeyId?: string; + /** Canonical tokenId for the change output's metadata. */ + tokenId?: string; +} + +export interface TransferResult { + ok: boolean; + txid?: string; + reason?: string; +} + +/** + * One protocol's plug-in. Implementations live alongside this file. + * + * The adapter is intentionally narrow: ownership/discovery and transfer. + * Receive-address generation, key derivation, and indexer choice stay on + * the shared services for now — they will be lifted into the adapter when + * BSV-21 lands and needs different keys + a different indexer. + */ +export interface TokenProtocolAdapter { + readonly id: TokenProtocolId; + /** Output basket this protocol's UTXOs are stored in. */ + readonly basketName: string; + /** Human-readable label for the UI badge ("STAS", "DSTAS", "BSV-21"). */ + readonly displayName: string; + /** Whether `transfer(...)` is implemented yet on this adapter. */ + readonly transferSupported: boolean; + + /** + * Try to recognise a locking script as one of this protocol's outputs. + * Returns `null` if the script doesn't belong to this protocol — never + * throws. Async because some protocols (classic STAS) need to walk back + * through inputs to find the canonical tokenId. + */ + parseOutput(scriptHex: string, ctx?: ParseContext): Promise; + + /** + * Build + broadcast a transfer. Only present when `transferSupported` + * is true — callers must check before invoking. + */ + transfer?(args: TransferArgs): Promise; +} diff --git a/src/lib/services/tokens/TokenProtocolRegistry.ts b/src/lib/services/tokens/TokenProtocolRegistry.ts new file mode 100644 index 0000000..8cdd463 --- /dev/null +++ b/src/lib/services/tokens/TokenProtocolRegistry.ts @@ -0,0 +1,61 @@ +/** + * TokenProtocolRegistry — holds every TokenProtocolAdapter the wallet + * knows about. The renderer accesses it through `stas.tokens` on the + * WalletService bundle. + * + * Lookup order matters for `find(scriptHex)`: the registry asks each + * adapter to try parsing the script in registration order and returns + * the first that succeeds. STAS adapters are registered before DSTAS + * to preserve the existing precedence — classic STAS's prefix sniff is + * cheap and unambiguous, so checking it first short-circuits the more + * expensive DSTAS reader. + */ + +import type { + TokenProtocolAdapter, + TokenProtocolId, + ParseContext, + ParsedTokenOutput, +} from './TokenProtocolAdapter'; + +export interface AdapterMatch { + adapter: TokenProtocolAdapter; + parsed: ParsedTokenOutput; +} + +export class TokenProtocolRegistry { + private readonly adapters: TokenProtocolAdapter[] = []; + + register(adapter: TokenProtocolAdapter): void { + if (this.adapters.some((a) => a.id === adapter.id)) { + throw new Error(`TokenProtocolRegistry: adapter "${adapter.id}" already registered`); + } + this.adapters.push(adapter); + } + + all(): readonly TokenProtocolAdapter[] { + return this.adapters; + } + + getById(id: TokenProtocolId): TokenProtocolAdapter | undefined { + return this.adapters.find((a) => a.id === id); + } + + /** + * Walk every registered adapter and return the first whose + * `parseOutput` recognises the script. Returns `null` if no adapter + * claims it (foreign script — not one of our tokens). + */ + async find(scriptHex: string, ctx?: ParseContext): Promise { + for (const adapter of this.adapters) { + try { + const parsed = await adapter.parseOutput(scriptHex, ctx); + if (parsed) return { adapter, parsed }; + } catch { + // Adapters must not throw on non-matching scripts; if one does, + // treat it as "did not match" and move on. + } + } + return null; + } +} diff --git a/src/lib/services/tokens/TokenVerificationService.ts b/src/lib/services/tokens/TokenVerificationService.ts new file mode 100644 index 0000000..e2d0bb2 --- /dev/null +++ b/src/lib/services/tokens/TokenVerificationService.ts @@ -0,0 +1,146 @@ +/** + * TokenVerificationService — Back-to-Genesis provenance for held tokens. + * + * Wraps BackToGenesisClient with the two things the UI needs on top of the raw + * endpoint: + * + * 1. A per-outpoint session cache. An outpoint's provenance is immutable + * (barring a reorg), so we verify each `(std, txid, vout)` at most once per + * session. Durable persistence across sessions lives in the wallet DB + * (`token_verifications`, migration 0004), seeded by the caller — this + * in-memory map is only the same-session accelerator on top of it. + * + * 2. A per-token aggregate. A token card groups several UTXOs; its badge is the + * worst verdict among them — one counterfeit output taints the card, and an + * `undetermined` (unknown) never masquerades as verified. + * + * Why the wallet needs this at all: for classic STAS `assetKey.tokenId` is the + * issuer PKH, shared by every token that issuer minted, and B2G omits `symbol`. + * So `authentic` alone cannot tell EXSTAS1 from EXSTAS2 — the resolved `genesis` + * outpoint is the only stable identity. Callers should group/trust on genesis, + * which this service surfaces per outpoint. + * + * Fail-safe throughout: a transport failure is `undetermined`, never a throw and + * never a false counterfeit. + */ + +import { + BackToGenesisClient, + formatGenesisRef, + type B2GVerifyResult, + type TokenStd, +} from './woc/BackToGenesisClient'; +import type { TokenProtocolId } from './TokenProtocolAdapter'; + +/** UI-facing rollup of a token card's provenance. */ +export type VerificationBadge = 'verified' | 'counterfeit' | 'unknown'; + +export interface OutpointVerification { + outpoint: string; // `${txid}_${vout}` + result: B2GVerifyResult['result']; + reason?: string; + /** `${txid}_${vout}` of the resolved genesis — the stable token identity. */ + genesis?: string; + genesisDepth?: number; +} + +/** The minimum an item must expose to be verifiable. */ +export interface VerifiableOutput { + txid: string; + vout: number; + protocol: TokenProtocolId; +} + +const PROTOCOL_TO_STD: Record = { + stas: 'stas', + dstas: 'dstas', + 'bsv-21': 'bsv21', +}; + +/** Roll a set of per-outpoint verdicts into one card badge (worst wins). */ +export function aggregateBadge(verdicts: OutpointVerification[]): VerificationBadge { + if (verdicts.length === 0) return 'unknown'; + if (verdicts.some((v) => v.result === 'not-authentic')) return 'counterfeit'; + if (verdicts.every((v) => v.result === 'authentic')) return 'verified'; + return 'unknown'; // at least one undetermined, none counterfeit +} + +export class TokenVerificationService { + private readonly client: BackToGenesisClient; + private readonly chain: 'main' | 'test'; + /** Same-session cache. Durable persistence is the wallet DB (see class doc). */ + private readonly cache = new Map(); + + constructor(opts: { chain?: 'main' | 'test'; client?: BackToGenesisClient } = {}) { + this.chain = opts.chain ?? 'main'; + this.client = opts.client ?? new BackToGenesisClient({ chain: this.chain }); + } + + private key(std: TokenStd, txid: string, vout: number): string { + return `${std}:${txid}_${vout}`; + } + + /** + * Seed the session cache from durable storage (the wallet DB). Lets a card's + * badge render from a prior session's verdict before any network call. Only + * settled verdicts should be seeded — an `undetermined` must be re-verified. + */ + seed(entries: Array<{ output: VerifiableOutput; verdict: OutpointVerification }>): void { + for (const { output, verdict } of entries) { + if (verdict.result === 'undetermined') continue; + const std = PROTOCOL_TO_STD[output.protocol]; + this.cache.set(this.key(std, output.txid, output.vout), verdict); + } + } + + /** Cached verdict for one outpoint, or undefined if never verified. */ + peek(output: VerifiableOutput): OutpointVerification | undefined { + const std = PROTOCOL_TO_STD[output.protocol]; + return this.cache.get(this.key(std, output.txid, output.vout)); + } + + /** + * Verify one outpoint, using the cache unless `force`. A settled verdict + * (authentic / not-authentic) is never re-fetched; an `undetermined` one is + * retried, since it means "couldn't decide yet", not "decided: unknown". + */ + async verifyOutput( + output: VerifiableOutput, + opts: { expectedGenesis?: string; force?: boolean } = {} + ): Promise { + const std = PROTOCOL_TO_STD[output.protocol]; + const k = this.key(std, output.txid, output.vout); + const cached = this.cache.get(k); + if (!opts.force && cached && cached.result !== 'undetermined') return cached; + + const res = await this.client.verify(std, output.txid, output.vout, { + expectedGenesis: opts.expectedGenesis, + }); + const verdict: OutpointVerification = { + outpoint: `${output.txid}_${output.vout}`, + result: res.result, + reason: res.reason, + genesis: res.genesis ? formatGenesisRef(res.genesis) : undefined, + genesisDepth: res.genesisDepth, + }; + this.cache.set(k, verdict); + return verdict; + } + + /** + * Verify many outpoints. Returns a map keyed by `${txid}_${vout}`. Requests + * go through the shared WOC rate limiter, so passing the whole wallet at once + * is safe — they queue rather than burst. Cached outpoints resolve instantly. + */ + async verifyOutputs( + outputs: VerifiableOutput[], + opts: { force?: boolean } = {} + ): Promise> { + const results = await Promise.all( + outputs.map((o) => this.verifyOutput(o, { force: opts.force })) + ); + const map = new Map(); + results.forEach((v) => map.set(v.outpoint, v)); + return map; + } +} diff --git a/src/lib/services/tokens/bsv21/BSV21DiscoveryService.ts b/src/lib/services/tokens/bsv21/BSV21DiscoveryService.ts new file mode 100644 index 0000000..7f456be --- /dev/null +++ b/src/lib/services/tokens/bsv21/BSV21DiscoveryService.ts @@ -0,0 +1,540 @@ +/** + * BSV21DiscoveryService — find BSV-21 UTXOs the wallet owns at any of its + * derived BSV-21 receive addresses, then register them via + * BSV21Registration. + * + * Discovery shape mirrors StasDiscoveryService: + * enumerate derived owner addresses + * → query the 1Sat indexer per-address for any unspent BSV-21 outputs + * → parse the on-chain script locally (defence-in-depth) and confirm + * it agrees with the indexer's claim + * → register via BSV21Registration (BEEF + internalizeAction + tag set) + * → return a structured ScanResult + * + * One scan per call; no background timer. The Refresh button in + * AssetsPage triggers scan(), same pattern as STAS. + */ + +import { Transaction } from '@bsv/sdk'; +import { Address, fromHex } from 'dxs-bsv-token-sdk/bsv'; +import type { BSV21KeyDeriver } from './BSV21KeyDeriver'; +import type { IndexedOutput } from './OneSatIndexerClient'; +import type { BSV21Registration } from './BSV21Registration'; +import { BSV21_GAP_LIMIT } from './constants'; +import { BSV21_BASKET } from '../../../constants/baskets'; +import { parseBsv21LockingScript } from './inscription'; + +export interface Bsv21ScanResult { + scannedAddresses: number; + /** Total UTXOs the indexer returned across scanned addresses. */ + candidates: number; + /** Candidates whose locking script parses as BSV-21. */ + bsv21: number; + /** BSV-21 UTXOs that mapped to a derived key (always true if the address binding works). */ + ownedAndBsv21: number; + registered: number; + skippedAlreadyKnown: number; + errors: Array<{ outpoint?: string; message: string }>; + registeredOutpoints: Array<{ txid: string; vout: number; tokenId: string }>; + /** Outputs whose spendable flag we flipped from false → true post-register. */ + spendableFlipped?: number; +} + +/** + * Per-address BSV-21 indexer the discovery loop pulls from. Both the legacy + * `OneSatIndexerClient` (1Sat overlay SSE) and the new `WocTokenIndexerClient` + * (WOC per-address unspent) satisfy this — the scan consumes `IndexedOutput` + * rows the same way regardless of source. + */ +export interface Bsv21DiscoveryIndexer { + getOwnedTxos(address: string): Promise; +} + +export interface BSV21DiscoveryDeps { + deriver: BSV21KeyDeriver; + indexer: Bsv21DiscoveryIndexer; + registration: BSV21Registration; + /** Wallet exposing `getServices()` (wallet-toolbox Wallet). */ + wallet: any; + gapLimit?: number; +} + +export interface Bsv21RegisterByTxidResult { + txid: string; + registered: number; + outputs: Array<{ + vout: number; + matched: boolean; + /** When matched=true: the recv-N keyIndex that owns the output. */ + keyIndex?: number; + /** When matched=true and register failed: reason string. */ + reason?: string; + /** Was the wallet successful in registering it? */ + ok?: boolean; + }>; + /** Error before per-output processing started (e.g. tx not found). */ + error?: string; +} + +function hash160ToAddress(hash160Hex: string): string { + return new (Address as any)(fromHex(hash160Hex)).Value as string; +} + +export class BSV21DiscoveryService { + constructor(private readonly deps: BSV21DiscoveryDeps) {} + + /** + * Expose the BSV-21 BRC-42 key deriver. Used by `/bsv-21/receive-address` + * so external apps can request a BSV-21-namespace receive address without + * needing a second wiring path. The deriver lives behind the service for + * dependency-injection cleanliness; this getter is the one well-defined + * outward escape hatch. + */ + getDeriver(): BSV21KeyDeriver { + return this.deps.deriver; + } + + /** + * DEMO-ONLY fast-path: register a BSV-21 UTXO directly by txid. + * + * The PRIMARY discovery mechanism is `scan()` — query the 1Sat overlay's + * per-address SSE stream and register every matching output. That covers + * organic receive (anyone sends to one of our derived addresses) as long + * as the sender's broadcast went through any `/1sat/tx`-capable endpoint + * (the faucet now does this per-mint). + * + * This method exists so a colocated mint flow (dex-shell after a faucet + * mint) can skip the indexer round-trip and get immediate UI feedback — + * the wallet fetches the tx directly via `getServices().getRawTx`, parses + * outputs, matches owner hash160 against derived keys, and internalizes. + * Mirrors `StasDiscoveryService.registerByTxid`. + */ + async registerByTxid(txid: string): Promise { + const out: Bsv21RegisterByTxidResult = { txid, registered: 0, outputs: [] }; + + const services: any = (this.deps.wallet as any).getServices?.(); + if (!services) { + out.error = 'wallet.getServices() unavailable'; + return out; + } + + let rawTxRes: any; + try { + rawTxRes = await services.getRawTx(txid); + } catch (err) { + out.error = `getRawTx failed: ${err instanceof Error ? err.message : String(err)}`; + return out; + } + if (!rawTxRes?.rawTx) { + out.error = rawTxRes?.error?.message ?? 'getRawTx returned no rawTx'; + return out; + } + + let tx: any; + try { + tx = Transaction.fromBinary(rawTxRes.rawTx as number[]); + } catch (err) { + out.error = `tx parse failed: ${err instanceof Error ? err.message : String(err)}`; + return out; + } + + // Enumerate owner hashes the wallet has derived under the BSV-21 + // protocolID. Bootstrap mode (hwm=0) uses a small starter window — + // BSV-21 receives can't predate receive-context generation today. + const hwm = await this.deps.deriver.getHighWaterMark(); + const gap = this.deps.gapLimit ?? BSV21_GAP_LIMIT; + const ownerMap = await this.deps.deriver.enumerateOwnerFields( + hwm > 0 ? hwm + gap : Math.min(gap, 5) + ); + + for (let vout = 0; vout < tx.outputs.length; vout++) { + const txout = tx.outputs[vout]; + const scriptHex: string = txout.lockingScript.toHex(); + const parsed = parseBsv21LockingScript(scriptHex); + if (!parsed) { + out.outputs.push({ vout, matched: false }); + continue; + } + const keyIndex = ownerMap.get(parsed.ownerHash160); + if (keyIndex === undefined) { + out.outputs.push({ vout, matched: false }); + continue; + } + + // Deploy+mint payloads carry no `id` in the JSON — the outpoint + // IS the canonical token id. Transfer payloads carry their own id. + const tokenId = parsed.id || `${txid}_${vout}`; + const reg = await this.deps.registration.register({ + txid, + vout, + tokenId, + amt: parsed.amt, + dec: parsed.dec, + sym: parsed.sym, + icon: parsed.icon, + brc42KeyId: `recv ${keyIndex}`, + ownerAddress: new (Address as any)(fromHex(parsed.ownerHash160)).Value as string, + }); + const ok = !!reg.registered; + if (ok) out.registered++; + out.outputs.push({ + vout, + matched: true, + keyIndex, + ok, + reason: reg.reason, + }); + } + return out; + } + + /** + * Recover a pre-fix orphaned BSV-21 output by outpoint. + * + * Pre-PR-32 BSV-21 sends produced change outputs that landed in the + * `outputs` table without a basket assignment (the wallet did not + * declare basket+customInstructions+tags on the change output). Those + * UTXOs are unspendable because AssetsPage queries by basket and + * the registration path's idempotency check skips them. + * + * This recovery flow: + * 1. Fetch the parent tx via getRawTx + * 2. Parse the specific output's locking script + * 3. Match ownerHash160 against derived BRC-42 keys (proves ownership) + * 4. Call the SQL recovery method to retroactively assign basket, + * customInstructions, tags, and spendable=true + * + * Idempotent — already-recovered outputs return ok=true with + * `alreadyHadBasket: true`. + * + * Returns a structured result so the UI can render success/failure + * without surfacing exceptions. + */ + async recoverByOutpoint(args: { + txid: string; + vout: number; + identityKey: string; + chain: 'main' | 'test'; + }): Promise<{ + ok: boolean; + outputId?: number; + keyIndex?: number; + tokenId?: string; + alreadyHadBasket?: boolean; + reason?: string; + }> { + const services: any = (this.deps.wallet as any).getServices?.(); + if (!services) { + return { ok: false, reason: 'wallet.getServices() unavailable' }; + } + + let rawTxRes: any; + try { + rawTxRes = await services.getRawTx(args.txid); + } catch (err) { + return { ok: false, reason: `getRawTx failed: ${err instanceof Error ? err.message : String(err)}` }; + } + if (!rawTxRes?.rawTx) { + return { ok: false, reason: rawTxRes?.error?.message ?? 'getRawTx returned no rawTx' }; + } + + let tx: any; + try { + tx = Transaction.fromBinary(rawTxRes.rawTx as number[]); + } catch (err) { + return { ok: false, reason: `tx parse failed: ${err instanceof Error ? err.message : String(err)}` }; + } + if (args.vout < 0 || args.vout >= tx.outputs.length) { + return { ok: false, reason: `vout ${args.vout} out of range (tx has ${tx.outputs.length} outputs)` }; + } + + const scriptHex: string = tx.outputs[args.vout].lockingScript.toHex(); + const parsed = parseBsv21LockingScript(scriptHex); + if (!parsed) { + return { ok: false, reason: 'output does not parse as BSV-21' }; + } + + // Walk derived keys — same shape registerByTxid uses. Gap-limit + // applies; if the output was sent to a key past the current high + // water mark we don't find it. + const hwm = await this.deps.deriver.getHighWaterMark(); + const gap = this.deps.gapLimit ?? BSV21_GAP_LIMIT; + const ownerMap = await this.deps.deriver.enumerateOwnerFields( + hwm > 0 ? hwm + gap : Math.min(gap, 5) + ); + const keyIndex = ownerMap.get(parsed.ownerHash160); + if (keyIndex === undefined) { + return { + ok: false, + reason: `owner hash160 ${parsed.ownerHash160} does not match any derived BRC-42 key within gap ${gap}`, + }; + } + + // Deploy+mint payloads carry no `id` — outpoint underscore form + // IS the tokenId. Transfer payloads (the change-output case) + // carry the original tokenId. + const tokenId = parsed.id || `${args.txid}_${args.vout}`; + + // Mirror BSV21Registration.register's customInstructions + tags + // exactly, so a recovered output looks identical to a freshly- + // registered one (same UI surface, same spend-time unlock recipe). + const ownerAddress = hash160ToAddress(parsed.ownerHash160); + const customInstructions = JSON.stringify({ + kind: 'bsv-21', + protocolID: ['2', 'bsv-21'], + keyID: `recv ${keyIndex}`, + counterparty: 'self', + tokenId, + ownerAddress, + }); + + const tags: string[] = ['bsv21', `id:${tokenId}`, `amt:${parsed.amt}`]; + if (parsed.dec !== undefined) tags.push(`dec:${parsed.dec}`); + if (parsed.sym) tags.push(`sym:${parsed.sym}`); + if (parsed.icon) tags.push(`icon:${parsed.icon}`); + + // Dispatch via the stas-query IPC channel to the SQL recovery method. + // We don't go through internalizeAction because the output is already + // in the `outputs` table — re-internalizing would either fail or + // create a duplicate row. + const api = typeof window !== 'undefined' ? (window as any).electronAPI?.stas : undefined; + if (!api) { + return { ok: false, reason: 'STAS query channel unavailable' }; + } + const res = await api.query(args.identityKey, args.chain, 'recoverOrphanOutput', [ + { + txid: args.txid, + vout: args.vout, + customInstructions, + tags, + basketName: 'bsv-21-tokens', + }, + ]); + if (!res || !res.success) { + return { ok: false, reason: `recoverOrphanOutput query failed: ${res?.error ?? 'unknown'}` }; + } + const sqlRes = res.result as { + ok: boolean; + outputId?: number; + alreadyHadBasket?: boolean; + reason?: string; + }; + + return { + ok: sqlRes.ok, + outputId: sqlRes.outputId, + alreadyHadBasket: sqlRes.alreadyHadBasket, + keyIndex, + tokenId, + reason: sqlRes.reason, + }; + } + + async scan(opts: { onProgress?: (p: { phase: 'bsv21' | 'register'; done: number; total: number }) => void } = {}): Promise { + const result: Bsv21ScanResult = { + scannedAddresses: 0, + candidates: 0, + bsv21: 0, + ownedAndBsv21: 0, + registered: 0, + skippedAlreadyKnown: 0, + errors: [], + registeredOutpoints: [], + }; + + const gap = this.deps.gapLimit ?? BSV21_GAP_LIMIT; + + // 1. Enumerate derived owner hashes (hash160 → keyIndex). BRC-42 + // derivation is deterministic, so the cache is only ever extended. + const hwm = await this.deps.deriver.getHighWaterMark(); + const bootstrap = 5; + const upTo = hwm > 0 ? hwm + gap : Math.min(bootstrap, gap); + const ownerMap = await this.deps.deriver.enumerateOwnerFields(upTo); + + // 2. hash160 → base58 P2PKH address (the indexer talks in addresses). + const addressToHash = new Map(); + for (const hash160Hex of ownerMap.keys()) { + try { + const addr = hash160ToAddress(hash160Hex); + addressToHash.set(addr, hash160Hex); + } catch { + /* skip undecodable */ + } + } + result.scannedAddresses = addressToHash.size; + if (addressToHash.size === 0) return result; + + // 3. Query the indexer per address. The owner-txos endpoint returns + // every UTXO the overlay knows about for that address regardless + // of token — we filter to BSV-21 entries below. + const candidates: Array<{ address: string; out: IndexedOutput }> = []; + const addressList = [...addressToHash.keys()]; + for (const [i, address] of addressList.entries()) { + opts.onProgress?.({ phase: 'bsv21', done: i, total: addressList.length }); + try { + const txos = await this.deps.indexer.getOwnedTxos(address); + for (const o of txos) { + // The live overlay tags BSV-21 outputs with the event + // `"type:application/bsv-20"` (the inscription content-type) + // alongside `"insc"`. Older / alternative indexer revisions + // emit `"bsv21"` directly or carry a top-level `id`. Accept + // all three so a server-side rename doesn't break discovery. + const evs = o.events ?? []; + const isBsv21 = + evs.includes('bsv21') || + evs.includes('type:application/bsv-20') || + !!o.id; + if (isBsv21) candidates.push({ address, out: o }); + } + } catch (err) { + result.errors.push({ + message: `indexer getOwnedTxos(${address}) failed: ${err instanceof Error ? err.message : String(err)}`, + }); + } + } + result.candidates = candidates.length; + if (candidates.length === 0) return result; + + // 4. For each candidate, fetch the tx, parse the output's script + // locally, and register. + const services = (this.deps.wallet as any).getServices?.(); + if (!services) { + result.errors.push({ message: 'wallet.getServices() unavailable' }); + return result; + } + const txCache = new Map(); + + // Build the set of BSV-21 outpoints the wallet already holds. We skip these + // BEFORE the getRawTx + parse + register round-trip: they're registered, so + // re-processing them is wasted work — and, because getRawTx re-hits an + // external provider for every candidate, it was both spamming the console + // with provider errors and adding rate-limit pressure on every rescan. + const known = new Set(); + try { + const held: any = await (this.deps.wallet as any).listOutputs({ + basket: BSV21_BASKET, + limit: 10000, + }); + for (const o of held?.outputs ?? []) { + const op: string = o.outpoint ?? ''; + const sep = Math.max(op.lastIndexOf('.'), op.lastIndexOf('_')); + if (sep > 0) known.add(`${op.slice(0, sep)}_${op.slice(sep + 1)}`); + } + } catch { + /* basket may not exist yet — treat everything as new */ + } + + for (const { address, out } of candidates) { + // The 1sat overlay uses `txid.vout` (period) on the SSE `event: txo` + // payload, but the same indexer's REST shapes use `txid_vout` + // (underscore). Accept both — splitting on the last separator that + // matches either character is safer than committing to one. + const outpointU = out.outpoint; + const sepIdx = Math.max(outpointU.lastIndexOf('.'), outpointU.lastIndexOf('_')); + const txid = sepIdx > 0 ? outpointU.slice(0, sepIdx) : ''; + const voutStr = sepIdx > 0 ? outpointU.slice(sepIdx + 1) : ''; + const vout = Number(voutStr); + if (!txid || Number.isNaN(vout)) { + result.errors.push({ outpoint: outpointU, message: 'malformed outpoint from indexer' }); + continue; + } + + // Already held → nothing to do. Skip before any network fetch. + if (known.has(`${txid}_${vout}`)) { + result.skippedAlreadyKnown++; + continue; + } + + try { + // Fetch tx once per txid. + let tx = txCache.get(txid); + if (!tx) { + const rawTxRes = await services.getRawTx(txid); + if (!rawTxRes?.rawTx) { + result.errors.push({ + outpoint: `${txid}.${vout}`, + message: rawTxRes?.error?.message ?? 'getRawTx returned no rawTx', + }); + continue; + } + tx = Transaction.fromBinary(rawTxRes.rawTx as number[]); + txCache.set(txid, tx); + } + + const txout = tx.outputs[vout]; + if (!txout) { + result.errors.push({ outpoint: `${txid}.${vout}`, message: 'output index out of range' }); + continue; + } + const scriptHex = txout.lockingScript.toHex(); + + // Defence-in-depth: confirm the locking script really is BSV-21 + // and that the trailing P2PKH matches the indexer's address. + const parsed = parseBsv21LockingScript(scriptHex); + if (!parsed) { + // Indexer claimed BSV-21 but we don't recognise the script. + // Don't register; surface as an error so the user can investigate. + result.errors.push({ outpoint: `${txid}.${vout}`, message: 'parser rejected BSV-21 claim' }); + continue; + } + result.bsv21++; + + const expectedHash160 = addressToHash.get(address); + if (!expectedHash160 || parsed.ownerHash160 !== expectedHash160) { + result.errors.push({ + outpoint: `${txid}.${vout}`, + message: `owner hash160 mismatch (script ${parsed.ownerHash160}, address-derived ${expectedHash160 ?? 'unknown'})`, + }); + continue; + } + result.ownedAndBsv21++; + + const keyIndex = ownerMap.get(parsed.ownerHash160); + if (keyIndex === undefined) continue; + + // Prefer the parsed payload (defence) but fall back to indexer-supplied + // fields when the parsed payload is missing them (e.g. dec on transfer + // payloads; the spec only requires dec on deploy+mint). + // + // For deploy+mint outputs the canonical tokenId is `_` + // (UNDERSCORE) per BSV-21 spec. The overlay surfaces outpoints in + // dot form (`txid.vout`), so we cannot use `outpointU` (dot) as a + // fallback — that produced spec-violating transfers with + // `"id":"."` which the topic-manager rejects. + const tokenId = parsed.id || out.id || `${txid}_${voutStr}`; + const amt = parsed.amt; + const dec = parsed.dec ?? out.dec; + const sym = parsed.sym ?? out.sym; + const icon = parsed.icon ?? out.icon; + + const reg = await this.deps.registration.register({ + txid, + vout, + tokenId, + amt, + dec, + sym, + icon, + brc42KeyId: `recv ${keyIndex}`, + ownerAddress: address, + }); + + if (reg.registered) { + result.registered++; + result.registeredOutpoints.push({ txid, vout, tokenId }); + } else if (reg.reason === 'already registered') { + result.skippedAlreadyKnown++; + } else if (reg.reason) { + result.errors.push({ outpoint: `${txid}.${vout}`, message: reg.reason }); + } + } catch (err) { + result.errors.push({ + outpoint: `${txid}.${vout}`, + message: err instanceof Error ? err.message : String(err), + }); + } + } + + return result; + } +} diff --git a/src/lib/services/tokens/bsv21/BSV21KeyDeriver.ts b/src/lib/services/tokens/bsv21/BSV21KeyDeriver.ts new file mode 100644 index 0000000..ea7e870 --- /dev/null +++ b/src/lib/services/tokens/bsv21/BSV21KeyDeriver.ts @@ -0,0 +1,98 @@ +/** + * BSV21KeyDeriver — BRC-42 derivation of BSV-21 receive keys. + * + * Symmetric with `StasKeyDeriver` but keyed under the `bsv-21 token + * ownership` protocolID, persisted into the `bsv21_receive_contexts` + * table. Keeping the namespaces separate so a wallet's STAS receive + * range never collides with its BSV-21 range. + */ + +import type { WalletInterface } from '@bsv/sdk'; +import { hash160, toHex, fromHex } from 'dxs-bsv-token-sdk/bsv'; +import { BSV21_PROTOCOL_ID, BSV21_COUNTERPARTY, bsv21KeyId } from './constants'; + +export interface DerivedBsv21ReceiveKey { + index: number; + keyId: string; + /** Compressed public key, hex. */ + publicKey: string; + /** hash160(publicKey), hex — the P2PKH owner hash. */ + ownerFieldHash160: string; +} + +export interface Bsv21ReceiveContextRow { + profileIdentityKey: string; + keyIndex: number; + keyId: string; + ownerFieldHash160: string; + derivedPublicKey: string; + createdAt: string; +} + +export class BSV21KeyDeriver { + private readonly _ownerFields = new Map(); + private _enumeratedUpTo = 0; + + constructor( + private readonly wallet: WalletInterface, + private readonly _identityKey: string, + private readonly _chain: 'main' | 'test' + ) {} + + get identityKey(): string { return this._identityKey; } + get chain(): 'main' | 'test' { return this._chain; } + + async deriveReceiveKey(index: number): Promise { + const keyId = bsv21KeyId(index); + const { publicKey } = await this.wallet.getPublicKey({ + protocolID: BSV21_PROTOCOL_ID, + keyID: keyId, + counterparty: BSV21_COUNTERPARTY, + }); + const ownerFieldHash160 = toHex(hash160(fromHex(publicKey))); + return { index, keyId, publicKey, ownerFieldHash160 }; + } + + async enumerateOwnerFields(upTo: number): Promise> { + for (let i = this._enumeratedUpTo + 1; i <= upTo; i++) { + const k = await this.deriveReceiveKey(i); + this._ownerFields.set(k.ownerFieldHash160, i); + } + if (upTo > this._enumeratedUpTo) this._enumeratedUpTo = upTo; + return this._ownerFields; + } + + async getHighWaterMark(): Promise { + const res = await this.query('getBsv21ReceiveHighWaterMark', [this._identityKey]); + return res === undefined ? 0 : (res as number); + } + + async createNextReceiveContext(): Promise { + if (typeof window === 'undefined' || !(window as any).electronAPI?.stas) { + throw new Error('BSV-21 query channel unavailable — cannot persist receive context'); + } + const next = (await this.getHighWaterMark()) + 1; + const k = await this.deriveReceiveKey(next); + const row: Bsv21ReceiveContextRow = { + profileIdentityKey: this._identityKey, + keyIndex: next, + keyId: k.keyId, + ownerFieldHash160: k.ownerFieldHash160, + derivedPublicKey: k.publicKey, + createdAt: new Date().toISOString(), + }; + await this.query('insertBsv21ReceiveContext', [row]); + return row; + } + + private async query(method: string, args: any[]): Promise { + const api = + typeof window !== 'undefined' ? (window as any).electronAPI?.stas : undefined; + if (!api) return undefined; + const res = await api.query(this._identityKey, this.chain, method, args); + if (!res || !res.success) { + throw new Error(`stas:query ${method} failed: ${res && res.error}`); + } + return res.result; + } +} diff --git a/src/lib/services/tokens/bsv21/BSV21Registration.ts b/src/lib/services/tokens/bsv21/BSV21Registration.ts new file mode 100644 index 0000000..fa4facd --- /dev/null +++ b/src/lib/services/tokens/bsv21/BSV21Registration.ts @@ -0,0 +1,170 @@ +/** + * BSV21Registration — internalize a discovered BSV-21 UTXO into the + * `bsv-21-tokens` basket via `wallet.internalizeAction`. + * + * BSV-21 keeps every token-level metadata field on the wallet-toolbox + * basket TAGS (per 1sat-wallet-toolbox convention), so there's no + * satellite-table linkage step like STAS does. The only durable artefacts + * are: + * - wallet-toolbox's `outputs` row (created by internalizeAction) + * - the basket tags carrying `id`, `amt`, `dec`, `sym`, `icon` + * - `customInstructions` JSON that lets `wallet.signAction` recover the + * BRC-42 derivation context at spend time (BSV-21 inputs are P2PKH; + * the protocolID + keyID + counterparty are the unlock recipe) + * + * `outputs.spendable` is flipped to true after internalize — the wallet- + * toolbox conservatively marks non-stock-template outputs `false`, but + * our adapter knows how to unlock them and the flag would otherwise + * block `createAction` from referencing the UTXO as input. + */ + +import type { WalletInterface } from '@bsv/sdk'; +import { BSV21_BASKET } from '../../../constants/baskets'; +import { BSV21_PROTOCOL_ID, BSV21_COUNTERPARTY } from './constants'; +import { buildChainedAtomicBeef } from '../../stas/buildChainedAtomicBeef'; +import { verifyAndPersistOnReceive } from '../verifyOnReceive'; + +const ORIGINATOR = 'admin.bsv21-discovery'; + +export interface RegisterBsv21Args { + txid: string; + vout: number; + /** Token id — `_` of the deploy+mint. */ + tokenId: string; + /** Raw amount (stringified bigint). */ + amt: string; + /** Decimals (optional — usually only on deploy+mint payloads). */ + dec?: number; + /** Symbol / ticker. */ + sym?: string; + /** Icon outpoint / URL. */ + icon?: string; + /** BRC-42 keyID of the receive key that owns this UTXO (e.g. `"recv 7"`). */ + brc42KeyId: string; + /** Owner address (base58). Stored in customInstructions for diagnostics. */ + ownerAddress: string; +} + +export interface RegisterBsv21Result { + registered: boolean; + txid: string; + vout: number; + outputId?: number; + reason?: string; +} + +export class BSV21Registration { + constructor( + private readonly wallet: WalletInterface, + private readonly identityKey: string, + private readonly chain: 'main' | 'test' + ) {} + + async register(args: RegisterBsv21Args): Promise { + const { txid, vout, tokenId, amt, dec, sym, icon, brc42KeyId, ownerAddress } = args; + + // 1. Idempotency — if wallet-toolbox already knows the outpoint, skip. + // BSV-21 has no satellite table; `outputs.outputId` lookup is the + // canonical "have I seen this UTXO?" probe. + try { + const existingId = await this.stasQuery('findOutputIdByOutpoint', [txid, vout]); + if (existingId) { + return { registered: false, txid, vout, outputId: existingId, reason: 'already registered' }; + } + } catch { + /* best-effort — proceed and let internalize handle duplicates */ + } + + // 2. Chained AtomicBEEF — walks back the input ancestry until every + // leaf has a proof. Works equally well for confirmed and mempool + // BSV-21 outputs. + let atomicBeef: number[]; + try { + const built = await buildChainedAtomicBeef({ wallet: this.wallet, txid }); + atomicBeef = built.atomicBeef; + } catch (err) { + return { + registered: false, + txid, + vout, + reason: `chained BEEF assembly failed: ${err instanceof Error ? err.message : String(err)}`, + }; + } + + // 3. customInstructions carries the BRC-42 derivation recipe for + // spend-time unlocking. The transfer service reads this back via + // listOutputs / output.customInstructions and feeds it to + // wallet.createSignature with the same protocolID + keyID + counterparty. + const customInstructions = JSON.stringify({ + kind: 'bsv-21', + protocolID: BSV21_PROTOCOL_ID, + keyID: brc42KeyId, + counterparty: BSV21_COUNTERPARTY, + tokenId, + ownerAddress, + }); + + const tags: string[] = ['bsv21', `id:${tokenId}`, `amt:${amt}`]; + if (dec !== undefined) tags.push(`dec:${dec}`); + if (sym) tags.push(`sym:${sym}`); + if (icon) tags.push(`icon:${icon}`); + + try { + await this.wallet.internalizeAction( + { + tx: atomicBeef, + outputs: [ + { + outputIndex: vout, + protocol: 'basket insertion', + insertionRemittance: { + basket: BSV21_BASKET, + customInstructions, + tags, + }, + }, + ], + description: 'bsv-21 discovery', + seekPermission: false, + } as any, + ORIGINATOR + ); + } catch (err) { + return { + registered: false, + txid, + vout, + reason: `internalizeAction failed: ${err instanceof Error ? err.message : String(err)}`, + }; + } + + // 4. Look up the freshly-inserted output and flip spendable=true so + // createAction will let us reference it as an input later. + // Mirror of the STAS post-register step. + let outputId: number | undefined; + try { + outputId = await this.stasQuery('findOutputIdByOutpoint', [txid, vout]); + if (outputId) { + await this.stasQuery('setOutputSpendable', [outputId, true]); + } + } catch (err) { + console.warn(`[BSV21Registration] post-internalize step failed for ${txid}:${vout}`, err); + } + + // Verify provenance on receive (the BSV-21 discovery path). Fire-and-forget. + verifyAndPersistOnReceive(this.identityKey, this.chain, { txid, vout, protocol: 'bsv-21' }); + + return { registered: true, txid, vout, outputId }; + } + + private async stasQuery(method: string, args: any[]): Promise { + const api = + typeof window !== 'undefined' ? (window as any).electronAPI?.stas : undefined; + if (!api) throw new Error('STAS query channel unavailable'); + const res = await api.query(this.identityKey, this.chain, method, args); + if (!res || !res.success) { + throw new Error(`stas:query ${method} failed: ${res && res.error}`); + } + return res.result; + } +} diff --git a/src/lib/services/tokens/bsv21/BSV21TransferService.ts b/src/lib/services/tokens/bsv21/BSV21TransferService.ts new file mode 100644 index 0000000..c3daf9c --- /dev/null +++ b/src/lib/services/tokens/bsv21/BSV21TransferService.ts @@ -0,0 +1,479 @@ +/** + * BSV21TransferService — build, sign, and broadcast a BSV-21 transfer. + * + * Unlike STAS, BSV-21 is just an ord-inscription envelope wrapping a + * standard P2PKH owner script — no engine, no custom sighash rules, + * no payment segments. The transfer is: + * + * in : [ source BSV-21 UTXO (1 sat) ] ← signed by BRC-42 owner key + * + wallet-funded BSV inputs ← signed natively by wallet + * out: [ recipient BSV-21 output (1 sat) ] + * [ optional token-change output (1 sat) ] + * [ wallet BSV change ] ← added by createAction + * + * Signing for the BSV-21 input uses standard P2PKH sighash (ALL|FORKID) + * over the full source locking script. The unlocking script is the + * canonical ` ` pair — the ord envelope is dead code + * (OP_FALSE OP_IF … OP_ENDIF) and never executes. + * + * Optional pre-flight origin verification can be enabled (default on) + * — calls `OneSatIndexerClient.validateOutputs` and refuses to send if + * the source outpoint isn't part of the token's overlay-validated DAG. + */ + +import type { WalletInterface } from '@bsv/sdk'; +import { Beef } from '@bsv/sdk'; +import { Address, fromHex } from 'dxs-bsv-token-sdk/bsv'; +import { BSV21_PROTOCOL_ID, BSV21_COUNTERPARTY } from './constants'; +import { BSV21_BASKET } from '../../../constants/baskets'; +import { buildBsv21Transfer } from './inscription'; +import { buildChainedAtomicBeef } from '../../stas/buildChainedAtomicBeef'; +import { OneSatIndexerClient } from './OneSatIndexerClient'; +import type { BSV21KeyDeriver } from './BSV21KeyDeriver'; +import { tokenLog } from '../tokenLog'; + +const ORIGINATOR = 'admin.bsv21-transfer'; + +/** stas-js exports the SIGHASH ALL|FORKID byte we want for P2PKH sigs. */ +const SIGHASH_ALL_FORKID = 0x41; // SIGHASH_ALL (0x01) | SIGHASH_FORKID (0x40) + +export interface BSV21TransferArgs { + source: { + txid: string; + vout: number; + scriptHex: string; + satoshis: number; + brc42KeyId: string; + /** Token id this UTXO carries — `_` of the deploy+mint. */ + tokenId: string; + /** Raw token amount the input holds. */ + amt: string; + /** Decimals + symbol propagate to change tags for UI continuity. */ + dec?: number; + sym?: string; + icon?: string; + /** + * Optional owner-key derivation override for signing the BSV-21 input. + * Defaults to the self-owned scheme (BSV21_PROTOCOL_ID, keyID + * `brc42KeyId`, counterparty 'self'). A token received over a peer + * channel (BRC-29) is owned under a derivation keyed to the SENDER, so + * re-spending it requires `keyID = " "` and + * `counterparty = senderIdentityKey`. Backward compatible. + */ + owner?: { + protocolID?: [number, string]; + keyID: string; + counterparty: string; + /** True for a BRC-29-received token: derive the recipient's OWN key. */ + forSelf?: boolean; + }; + }; + /** Amount of tokens (raw integer units) to send. */ + amount: string; + recipientAddress: string; +} + +export interface BSV21TransferResult { + ok: boolean; + txid?: string; + reason?: string; + /** Signed AtomicBEEF of the transfer (from signAction) — for peer delivery. */ + beef?: number[]; +} + +export interface BSV21TransferDeps { + wallet: WalletInterface; + identityKey: string; + chain: 'main' | 'test'; + /** Deriver used for token-change addresses. */ + deriver: BSV21KeyDeriver; + /** Indexer for optional pre-send origin validation. */ + indexer: OneSatIndexerClient; + /** Toggle the overlay check off when the indexer is known unavailable. */ + originVerify?: boolean; +} + +/** Dynamic bsv-js import — same pattern StasTransferService uses. */ +async function loadBsvJs(): Promise<{ bsv: any }> { + const bsvMod: any = await import('bsv'); + return { bsv: bsvMod.default ?? bsvMod }; +} + +function toHex(bytes: number[] | Uint8Array): string { + const arr = Array.isArray(bytes) ? bytes : Array.from(bytes); + return arr.map((b) => b.toString(16).padStart(2, '0')).join(''); +} + +function errMsg(err: unknown): string { + return err instanceof Error ? err.message : String(err); +} + +export class BSV21TransferService { + constructor(private readonly deps: BSV21TransferDeps) {} + + async transfer(args: BSV21TransferArgs): Promise { + const { source, amount, recipientAddress } = args; + const { wallet, deriver, indexer } = this.deps; + const originVerify = this.deps.originVerify ?? true; + + // 1. Validate amounts up front. BSV-21 amounts are bigint strings. + let sendAmt: bigint; + let inAmt: bigint; + try { + sendAmt = BigInt(amount); + inAmt = BigInt(source.amt); + if (sendAmt <= 0n) throw new Error('amount must be > 0'); + if (sendAmt > inAmt) throw new Error(`amount ${sendAmt} exceeds input ${inAmt}`); + } catch (err) { + return { ok: false, reason: `amount validation: ${errMsg(err)}` }; + } + const changeAmt = inAmt - sendAmt; + + // 2. Optional origin verification — fail closed where we can, + // short-circuit where we can't. + // + // Three branches: + // a) Source IS the deploy+mint output itself (first transfer from + // the root). It's canonical by construction — no validation + // needed. Token id encodes the deploy outpoint as `_`. + // b) Overlay returns `null` for the validate-outputs call. This + // happens when the per-token topic-manager (`tm_{tokenId}`) + // isn't active (1sat-stack fee-gate). We can't verify, but + // can't fail closed either — log a warning and proceed. + // c) Overlay returns an array. Standard path — outpoint must be + // in the validated set or we refuse. + const sourceOutpointUnderscored = OneSatIndexerClient.dotToUnderscore( + `${source.txid}.${source.vout}` + ); + const isDeployRoot = sourceOutpointUnderscored === source.tokenId; + if (originVerify && !isDeployRoot) { + let valid: Set | null; + try { + valid = await indexer.validateOutputs(source.tokenId, [ + sourceOutpointUnderscored, + ]); + } catch (err) { + return { ok: false, reason: `origin overlay unreachable: ${errMsg(err)}` }; + } + if (valid === null) { + // Per-token validation unavailable. Most common cause: token's + // per-token worker isn't active yet (overlay returns 200 + null + // body). Log and proceed — the recipient's wallet still trusts + // the inscription bytes for ownership; the worst case is they + // can't see a token-scoped balance until activation. + tokenLog.warn( + `[bsv-21 transfer] origin validate unavailable for ${source.tokenId} — proceeding without ancestry check` + ); + } else if (!valid.has(sourceOutpointUnderscored)) { + // Fail-open (not fail-closed): the overlay returned a validated set + // that omits our outpoint. This is common for self-broadcast transfers + // and tokens whose per-token worker lagged or rejected the submit — it + // does NOT mean the token is counterfeit. Blocking here would refuse a + // legitimate send of a UTXO we hold. Two facts make the overlay's set + // non-authoritative now: + // • discovery migrated to WOC, whose BSV-21 indexer runs its OWN + // origin validation on the receive side (the real gate), and + // • the broadcast goes through wallet-toolbox/ARC, not the overlay. + // So warn and proceed; the recipient's indexer decides admissibility. + tokenLog.warn( + `[bsv-21 transfer] origin outpoint ${sourceOutpointUnderscored} not in overlay validated set for ${source.tokenId} — proceeding (WOC indexer is the receive-side gate)` + ); + } + } + + // 3. Resolve recipient + (optional) change hash160s. Addresses come in + // base58 — bsv-js's Address gives us the hash buffer. + let bsv: any; + try { + ({ bsv } = await loadBsvJs()); + } catch (err) { + return { ok: false, reason: `load bsv-js: ${errMsg(err)}` }; + } + let recipientHash160Hex: string; + try { + recipientHash160Hex = bsv.Address.fromString(recipientAddress).hashBuffer.toString('hex'); + } catch (err) { + return { ok: false, reason: `invalid recipient: ${errMsg(err)}` }; + } + + let changeHash160Hex: string | undefined; + let changeKeyId: string | undefined; + if (changeAmt > 0n) { + try { + const ctx = await deriver.createNextReceiveContext(); + changeHash160Hex = ctx.ownerFieldHash160; + changeKeyId = ctx.keyId; + } catch (err) { + return { ok: false, reason: `derive change key: ${errMsg(err)}` }; + } + } + + // 4. Build the two BSV-21 outputs. Both are 1 sat. + // + // Normalize tokenId to underscore form per BSV-21 spec. Historical + // registration paths in this wallet sometimes wrote the dot form (the + // overlay surfaces outpoints as `txid.vout`); the inscription's `id` + // field MUST be `txid_vout` or the topic-manager rejects the transfer. + // Normalising at the boundary makes the on-chain bytes correct + // regardless of how the source was stored. + const canonicalTokenId = source.tokenId.replace('.', '_'); + const destScriptHex = buildBsv21Transfer({ + payload: { + id: canonicalTokenId, + amt: sendAmt.toString(), + dec: source.dec, + sym: source.sym, + icon: source.icon, + }, + ownerHash160: recipientHash160Hex, + }); + let changeScriptHex: string | undefined; + if (changeAmt > 0n && changeHash160Hex) { + changeScriptHex = buildBsv21Transfer({ + payload: { + id: canonicalTokenId, + amt: changeAmt.toString(), + dec: source.dec, + sym: source.sym, + icon: source.icon, + }, + ownerHash160: changeHash160Hex, + }); + } + + // 5. Build the inputBEEF that lets internalize/createAction verify the + // spent output. Same chained walkback STAS uses. + let inputBEEF: number[]; + try { + const built = await buildChainedAtomicBeef({ wallet, txid: source.txid }); + inputBEEF = built.beef; + } catch (err) { + return { ok: false, reason: `inputBEEF: ${errMsg(err)}` }; + } + + // 6. createAction. The wallet auto-funds BSV and adds standard change. + // + // The recipient output stays external — wallet-toolbox should NOT add + // it to any basket. The token-change output, by contrast, goes back to + // a wallet-derived BSV-21 address (see step 3 — `changeHash160Hex` + // comes from `deriver.createNextReceiveContext()`), so we declare its + // `basket` + `customInstructions` + `tags` here. Without these, + // createAction creates the on-chain output but leaves + // `outputs.basketId = NULL` in the SQL row, which means the user + // permanently loses sight of their change tokens — the AssetsPage + // basket query never returns them. + // + // The shape mirrors `BSV21Registration.register()`'s internalize call + // so listOutputs(bsv-21-tokens) returns identical row metadata for + // organic-discovery and self-change paths. + const outputs: any[] = [ + { + lockingScript: destScriptHex, + satoshis: 1, + outputDescription: 'BSV-21 to recipient', + }, + ]; + if (changeScriptHex && changeHash160Hex && changeKeyId) { + // Owner address for the customInstructions. + let changeOwnerAddress: string; + try { + changeOwnerAddress = new (Address as any)(fromHex(changeHash160Hex)).Value as string; + } catch { + changeOwnerAddress = ''; + } + const changeCustomInstructions = JSON.stringify({ + kind: 'bsv-21', + protocolID: BSV21_PROTOCOL_ID, + keyID: changeKeyId, + counterparty: BSV21_COUNTERPARTY, + tokenId: canonicalTokenId, + ownerAddress: changeOwnerAddress, + }); + const changeTags: string[] = ['bsv21', `id:${canonicalTokenId}`, `amt:${changeAmt.toString()}`]; + if (source.dec !== undefined) changeTags.push(`dec:${source.dec}`); + if (source.sym) changeTags.push(`sym:${source.sym}`); + if (source.icon) changeTags.push(`icon:${source.icon}`); + + outputs.push({ + lockingScript: changeScriptHex, + satoshis: 1, + outputDescription: 'BSV-21 token change', + basket: BSV21_BASKET, + customInstructions: changeCustomInstructions, + tags: changeTags, + }); + } + + let createRes: any; + try { + createRes = await wallet.createAction( + { + labels: ['peertoken'], + inputBEEF, + inputs: [ + { + outpoint: `${source.txid}.${source.vout}`, + unlockingScriptLength: 108, // standard P2PKH unlock: ~73 sig + 33 pubkey + push opcodes + inputDescription: 'BSV-21 token input', + }, + ], + outputs, + description: 'BSV-21 transfer', + options: { randomizeOutputs: false }, + } as any, + ORIGINATOR + ); + } catch (err) { + return { ok: false, reason: `createAction: ${errMsg(err)}` }; + } + + const signable = createRes?.signableTransaction; + if (!signable || !signable.tx) { + return { ok: false, reason: 'createAction did not return signableTransaction' }; + } + + // 7. Pull the atomic tx out of the signable BEEF and rebuild a bsv-js + // Transaction so we can compute the sighash. Same trick as STAS. + let tx: any; + try { + const beef = Beef.fromBinary(signable.tx); + const atomicTxid = (beef as any).atomicTxid as string | undefined; + if (!atomicTxid) return { ok: false, reason: 'signable BEEF has no atomic txid' }; + const btx = beef.findTxid(atomicTxid); + if (!btx?.tx) return { ok: false, reason: `signable BEEF missing atomic tx ${atomicTxid}` }; + const rawTxBytes = btx.tx.toBinary(); + tx = new bsv.Transaction(Buffer.from(rawTxBytes).toString('hex')); + tx.inputs[0].output = new bsv.Transaction.Output({ + script: bsv.Script.fromHex(source.scriptHex), + satoshis: source.satoshis, + }); + } catch (err) { + return { ok: false, reason: `parse signable tx: ${errMsg(err)}` }; + } + + // 8. Compute the P2PKH sighash for input 0 over the full source script. + // The ord envelope at the head is dead code on eval but participates + // in the sighash subject (BSV sighash hashes whole locking script). + let sigHex: string; + let ownerPubKeyHex: string; + // Effective owner-key derivation. Defaults to the self-owned scheme; a + // BRC-29 peer-received token overrides keyID + counterparty so it stays + // spendable. + const ownerDerivation = { + protocolID: (source.owner?.protocolID ?? BSV21_PROTOCOL_ID) as any, + keyID: source.owner?.keyID ?? source.brc42KeyId, + counterparty: (source.owner?.counterparty ?? BSV21_COUNTERPARTY) as any, + forSelf: source.owner?.forSelf === true, + }; + try { + const sourceLocking = bsv.Script.fromHex(source.scriptHex); + const satsBN = new bsv.crypto.BN(source.satoshis); + const preimage = bsv.Transaction.sighash.sighashPreimage( + tx, SIGHASH_ALL_FORKID, 0, sourceLocking, satsBN + ); + const digestBuf = bsv.crypto.Hash.sha256sha256(preimage); + const digestBytes = Array.from(digestBuf as Buffer) as number[]; + + const sigRes = await wallet.createSignature( + { + protocolID: ownerDerivation.protocolID, + keyID: ownerDerivation.keyID, + counterparty: ownerDerivation.counterparty, + hashToDirectlySign: digestBytes, + } as any, + ORIGINATOR + ); + sigHex = toHex(sigRes.signature) + SIGHASH_ALL_FORKID.toString(16).padStart(2, '0'); + + // Derive the matching pubkey for the unlocking script. + const { publicKey } = await wallet.getPublicKey( + { + protocolID: ownerDerivation.protocolID, + keyID: ownerDerivation.keyID, + counterparty: ownerDerivation.counterparty, + forSelf: ownerDerivation.forSelf, + } as any, + ORIGINATOR + ); + ownerPubKeyHex = publicKey; + } catch (err) { + return { ok: false, reason: `sighash/sign: ${errMsg(err)}` }; + } + + // 9. Standard P2PKH unlocking script: . + let unlockingScriptHex: string; + try { + const asm = `${sigHex} ${ownerPubKeyHex}`; + unlockingScriptHex = bsv.Script.fromASM(asm).toHex(); + } catch (err) { + return { ok: false, reason: `unlocking script assembly: ${errMsg(err)}` }; + } + + // 10. signAction — the wallet queues + monitor worker handles broadcast. + let signResp: any; + try { + signResp = await wallet.signAction( + { + reference: signable.reference, + spends: { 0: { unlockingScript: unlockingScriptHex } }, + } as any, + ORIGINATOR + ); + } catch (err) { + return { ok: false, reason: `signAction: ${errMsg(err)}` }; + } + + const sendResults: any[] = Array.isArray(signResp?.sendWithResults) + ? signResp.sendWithResults + : []; + const failed = sendResults.find((r) => r?.status === 'failed'); + if (failed) { + return { + ok: false, + reason: `broadcast failed: ${JSON.stringify(failed)} (txid was ${signResp?.txid})`, + }; + } + + // 11. Indexer-coupling step: submit the AtomicBEEF to the overlay's + // `/1sat/bsv21/overlay/submit` endpoint with the per-token topic + // (`tm_`) so the BSV-21 topic-manager admits the transfer + // and surfaces it via `/1sat/owner/.../txos`. This is what + // yours-wallet's @1sat/client OverlayClient.submitBsv21 does and + // what makes organic-receive work for the recipient side. + // + // We pass `signResp.tx` (the signed AtomicBEEF) — not raw bytes, + // not refetched-via-getRawTx. The AtomicBEEF includes parent + // funding transactions with their merkle proofs, which is what + // the topic-manager needs to validate the chain. + // + // Best-effort: a failure here doesn't fail the transfer. The tx + // is already broadcast through wallet-toolbox's primary path; the + // overlay submit only adds the indexer entry. If it fails today, + // the tx becomes discoverable when JungleBus auto-pickup catches + // up (also requires canonical inscription format — see inscription.ts). + try { + const signedBeef: number[] | undefined = signResp?.tx; + if (signedBeef && signedBeef.length > 0) { + const submit = await this.deps.indexer.submitTransaction(signedBeef, { + tokenId: source.tokenId, + }); + if (submit.ok) { + tokenLog.debug(`[bsv-21 transfer] overlay submit ✓ ${submit.body.slice(0, 200)}`); + } else { + tokenLog.warn(`[bsv-21 transfer] overlay submit ${submit.status}: ${submit.body.slice(0, 200)}`); + } + } else { + tokenLog.warn('[bsv-21 transfer] overlay submit skipped — signResp.tx empty (returnTXIDOnly?)'); + } + } catch (err) { + tokenLog.warn(`[bsv-21 transfer] overlay submit threw: ${err instanceof Error ? err.message : String(err)}`); + } + + return { ok: true, txid: signResp?.txid, beef: signResp?.tx }; + } +} + +// Suppress an unused-import warning — `fromHex` and `Address` may be useful +// in the future for richer address-handling and we want to keep the import +// surface aligned with the rest of the BSV-21 module. +void fromHex; void Address; diff --git a/src/lib/services/tokens/bsv21/OneSatIndexerClient.ts b/src/lib/services/tokens/bsv21/OneSatIndexerClient.ts new file mode 100644 index 0000000..ed48969 --- /dev/null +++ b/src/lib/services/tokens/bsv21/OneSatIndexerClient.ts @@ -0,0 +1,254 @@ +/** + * OneSatIndexerClient — REST client for the 1Sat overlay API. + * + * Discovers BSV-21 UTXOs at wallet-owned addresses, fetches token + * metadata, and optionally validates that outpoints trace back to the + * canonical deploy (origin-verification before send). + * + * Endpoint patterns mirror @1sat/wallet-toolbox's `Bsv21Client` / + * `OwnerClient` / `OverlayClient` so future protocol changes show up on + * a single, shared surface — adjust paths here when the upstream toolkit + * moves. + * + * Base: https://api.1sat.app + * Token detail: GET /1sat/bsv21/{tokenId} + * Unspent (1 address): GET /1sat/bsv21/{tokenId}/{lockType}/{address}/unspent + * Unspent (multi-address): POST /1sat/bsv21/{tokenId}/{lockType}/unspent + * body: ["addr1", "addr2", …] + * Validate outpoints: POST /1sat/bsv21/{tokenId}/outputs?unspent=true + * body: ["txid_vout", …] + * Owner txos (any token): GET /1sat/owner/{address}/txos?unspent=true + * Overlay submit (BSV-21): POST /1sat/bsv21/overlay/submit + * header: X-Topics: tm_bsv21 | tm_ + * body: BEEF bytes + * + * Outpoint shape is `txid_vout` (underscore), matching the 1Sat overlay. + * Callers that use `txid.vout` (the rest of this wallet) must convert. + */ + +import { + ONESAT_API_DEFAULT_MAIN, + ONESAT_API_DEFAULT_TEST, + ONESAT_LOCK_TYPE_P2PKH, +} from './constants'; + +export interface IndexedOutput { + /** `txid_vout` (underscore). */ + outpoint: string; + /** Token id (deploy outpoint, also `txid_vout`). */ + id?: string; + /** Token amount, stringified bigint. */ + amt?: string; + /** Decimals (only on deploy+mint payloads). */ + dec?: number; + sym?: string; + icon?: string; + /** Address that owns the output. */ + owner?: string; + /** Output value in satoshis (BSV-21 transfers are always 1 sat). */ + satoshis?: number; + /** Confirmation block height — 0 / undefined means mempool. */ + height?: number; + /** Event / tag list assigned by the indexer (e.g. ["bsv21"]). */ + events?: string[]; +} + +export interface TokenDetailResponse { + /** Token id — `txid_vout`. */ + id?: string; + tick?: string; + sym?: string; + dec?: number; + icon?: string; + supply?: string; + max?: string; + lim?: string; + fundAddress?: string; + /** Many other indexer-internal fields exist; pass-through tolerated. */ + [key: string]: unknown; +} + +export interface OneSatIndexerOptions { + /** Base URL override — defaults to api.1sat.app per chain. */ + baseUrl?: string; + /** 'main' or 'test'. Default 'main'. */ + chain?: 'main' | 'test'; + /** Lock-type path segment. Default 'p2pkh'. */ + lockType?: string; +} + +/** + * Result of a `/1sat/bsv21/overlay/submit` call. Wraps the raw response so + * callers can log on failure but proceed — the wallet has already + * broadcast through ARC; the overlay submit is the indexer-coupling step. + */ +export interface OverlaySubmitResult { + ok: boolean; + status: number; + /** Server-returned body, truncated by the caller as needed. */ + body: string; + /** Parsed STEAK response on 200, when present. */ + steak?: unknown; +} + +export class OneSatIndexerClient { + private readonly baseUrl: string; + private readonly lockType: string; + + constructor(opts: OneSatIndexerOptions = {}) { + const chain = opts.chain ?? 'main'; + this.baseUrl = + opts.baseUrl ?? (chain === 'main' ? ONESAT_API_DEFAULT_MAIN : ONESAT_API_DEFAULT_TEST); + this.lockType = opts.lockType ?? ONESAT_LOCK_TYPE_P2PKH; + } + + /** GET /1sat/bsv21/{tokenId} — token metadata (symbol, decimals, icon). */ + async getTokenDetails(tokenId: string): Promise { + const r = await fetch(`${this.baseUrl}/1sat/bsv21/${encodeURIComponent(tokenId)}`); + if (!r.ok) return null; + return (await r.json()) as TokenDetailResponse; + } + + /** + * GET /1sat/bsv21/{id}/{lockType}/{address}/unspent — unspent BSV-21 + * outputs at a single address for the given token. + */ + async getUnspentAtAddress(tokenId: string, address: string): Promise { + const url = `${this.baseUrl}/1sat/bsv21/${encodeURIComponent(tokenId)}/${this.lockType}/${encodeURIComponent(address)}/unspent`; + const r = await fetch(url); + if (!r.ok) return []; + return (await r.json()) as IndexedOutput[]; + } + + /** + * POST /1sat/bsv21/{id}/{lockType}/unspent — unspent BSV-21 outputs + * across many addresses (the bulk shape used by sendBsv21). + */ + async getUnspentForAddresses(tokenId: string, addresses: string[]): Promise { + if (addresses.length === 0) return []; + const url = `${this.baseUrl}/1sat/bsv21/${encodeURIComponent(tokenId)}/${this.lockType}/unspent`; + const r = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(addresses), + }); + if (!r.ok) return []; + return (await r.json()) as IndexedOutput[]; + } + + + /** + * POST /1sat/bsv21/{id}/outputs?unspent=true — origin-validate a batch + * of outpoints. Returns the subset the overlay considers a valid part + * of the token's ancestry DAG. + * + * Tri-state return: + * - `Set` (possibly empty): overlay responded with an array; + * each element is a known-valid outpoint + * - `null`: overlay returned a `null` body (status 200 with `null` JSON, + * which happens for tokens whose per-token topic-manager isn't + * active — the 1sat-stack fee-gate keeps `tm_{tokenId}` workers off + * until the issuer funds the fee_address). Caller should treat this + * as "validation unavailable", not "validation failed". + * + * The fetch is wrapped in try/catch so callers don't have to — network + * errors also surface as `null`. + */ + async validateOutputs(tokenId: string, outpoints: string[]): Promise | null> { + if (outpoints.length === 0) return new Set(); + const url = `${this.baseUrl}/1sat/bsv21/${encodeURIComponent(tokenId)}/outputs?unspent=true`; + let r: Response; + try { + r = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(outpoints), + }); + } catch { + return null; // network error → "unavailable" + } + if (!r.ok) return null; + let validated: IndexedOutput[] | null; + try { + validated = (await r.json()) as IndexedOutput[] | null; + } catch { + return null; + } + if (validated === null || validated === undefined) return null; + if (!Array.isArray(validated)) return null; + return new Set(validated.map((v) => v.outpoint)); + } + + /** Convert our wallet's `txid.vout` outpoints into the indexer's `txid_vout` form. */ + static dotToUnderscore(outpoint: string): string { + return outpoint.replace('.', '_'); + } + /** And the reverse. */ + static underscoreToDot(outpoint: string): string { + return outpoint.replace('_', '.'); + } + + /** + * POST /1sat/bsv21/overlay/submit — feed a BSV-21 transaction into the + * overlay's topic-manager. + * + * This is the load-bearing step for organic-receive on the recipient + * side. The overlay's BSV-21 topic-manager (mounted on the public + * `api.1sat.app` at `/1sat/bsv21/overlay/submit`) accepts BEEF-encoded + * transactions plus an `X-Topics` header listing the topics to consider + * admission to. Once admitted, the new outputs surface in: + * - `GET /1sat/bsv21/{tokenId}` (token detail) + * - `GET /1sat/owner/{addr}/txos` (per-owner sync, what our + * discovery scan consumes) + * - `GET /1sat/bsv21/{tokenId}/p2pkh/{addr}/unspent` + * + * Topics: + * - `tm_bsv21` — discovery topic. Use for deploy+mint / deploy+auth + * so the topic-manager registers the token AND triggers per-token + * worker creation downstream. Pass `{ tokenId: undefined }`. + * - `tm_` — per-token topic. Use for transfers; admission + * validates the token's ancestry DAG. Pass `{ tokenId }`. + * + * Body: BEEF bytes (not raw tx). The BEEF must include parent funding + * transactions with their merkle proofs so the topic-manager can verify + * the chain. wallet-toolbox's `signAction` returns an AtomicBEEF with + * proven parents — pass `signResp.tx` directly. + * + * Empirical baseline (2026-05-28): + * - raw tx bytes → 500 (overlay can't parse without BEEF framing) + * - BEEF without merkle proofs in parents → 500 + * - BEEF with parent merkle proofs → 200 STEAK + * + * Best-effort by convention — callers should NOT fail their flow on a + * non-OK response. The tx is already on-chain via the primary broadcast; + * this only adds the indexer entry. If overlay submit fails today, the + * tx becomes discoverable when JungleBus's auto-pickup catches it (which + * also requires the inscription to be in canonical form — see the note in + * `inscription.ts` about `OP_1` for the content-type tag). + */ + async submitTransaction( + beef: number[] | Uint8Array, + opts: { tokenId?: string } = {}, + ): Promise { + const bytes = beef instanceof Uint8Array ? beef : new Uint8Array(beef); + // tm_bsv21 admits any deploy. tm_{tokenId} validates transfers against + // the deploy's ancestry. The SDK pattern in @1sat/client@0.0.38 is to + // use whichever matches the operation; we let the caller decide via + // opts.tokenId — undefined → discovery, defined → per-token. + const topic = opts.tokenId ? `tm_${opts.tokenId}` : 'tm_bsv21'; + const r = await fetch(`${this.baseUrl}/1sat/bsv21/overlay/submit`, { + method: 'POST', + headers: { + 'Content-Type': 'application/octet-stream', + 'X-Topics': topic, + }, + body: bytes, + }); + const body = await r.text(); + let steak: unknown; + if (r.ok) { + try { steak = JSON.parse(body); } catch { /* leave undefined */ } + } + return { ok: r.ok, status: r.status, body, steak }; + } +} diff --git a/src/lib/services/tokens/bsv21/constants.ts b/src/lib/services/tokens/bsv21/constants.ts new file mode 100644 index 0000000..38ae3cb --- /dev/null +++ b/src/lib/services/tokens/bsv21/constants.ts @@ -0,0 +1,44 @@ +/** + * BSV-21 protocol constants — BRC-42 derivation namespace, 1Sat REST + * defaults, and the on-chain inscription envelope markers. + */ + +/** + * BRC-42 protocol for BSV-21 owner-key derivation. Distinct from STAS. + * + * Wallet-toolbox enforces `/^[a-zA-Z0-9 ]+$/` on protocol-name strings — + * a hyphen is rejected at `getPublicKey` time with *"protocol names can + * only contain letters, numbers and spaces"*. So `bsv21` (no hyphen) + * rather than the canonical `bsv-21`. + */ +export const BSV21_PROTOCOL_ID = [2, 'bsv21 token ownership'] as [2, string]; + +/** BSV-21 owner keys are self-owned. */ +export const BSV21_COUNTERPARTY = 'self'; + +/** keyID for the Nth receive key — monotonic counter, 1-based. */ +export const bsv21KeyId = (index: number): string => `recv ${index}`; + +/** + * Default gap limit for ownership scans beyond the high-water mark. + * + * BIP-44's standard gap of 20 — matches STAS_GAP_LIMIT. With WOC discovery each + * gap address is a rate-limited `/token/bsv21/{addr}/unspent` call, so the old + * value of 100 meant `hwm + 100` requests per scan, which tripped WOC's 429 + * throttle (and a 429'd address degrades to "empty", risking missed tokens). + * Received tokens land at issued addresses (≤ hwm); 20 beyond hwm is ample. + */ +export const BSV21_GAP_LIMIT = 20; + +/** ord-inscription content type for BSV-20 / BSV-21 JSON payloads. */ +export const BSV20_CONTENT_TYPE = 'application/bsv-20'; + +/** 1Sat REST default base URL (mainnet). Configurable per client instance. */ +export const ONESAT_API_DEFAULT_MAIN = 'https://api.1sat.app'; +export const ONESAT_API_DEFAULT_TEST = 'https://testnet.api.1sat.app'; + +/** + * The 1Sat indexer paths use `lockType` as a path segment. P2PKH outputs + * — the wallet-recognisable shape — use `'p2pkh'`. + */ +export const ONESAT_LOCK_TYPE_P2PKH = 'p2pkh'; diff --git a/src/lib/services/tokens/bsv21/index.ts b/src/lib/services/tokens/bsv21/index.ts new file mode 100644 index 0000000..5516479 --- /dev/null +++ b/src/lib/services/tokens/bsv21/index.ts @@ -0,0 +1,13 @@ +/** + * BSV-21 service barrel. Pure helpers, key derivation, indexer client, + * registration, transfer, and discovery — composed by + * `BSV21ProtocolAdapter`. + */ + +export * from './constants'; +export * from './inscription'; +export * from './BSV21KeyDeriver'; +export * from './OneSatIndexerClient'; +export * from './BSV21Registration'; +export * from './BSV21TransferService'; +export * from './BSV21DiscoveryService'; diff --git a/src/lib/services/tokens/bsv21/inscription.ts b/src/lib/services/tokens/bsv21/inscription.ts new file mode 100644 index 0000000..d3b759b --- /dev/null +++ b/src/lib/services/tokens/bsv21/inscription.ts @@ -0,0 +1,324 @@ +/** + * BSV-21 ord-inscription envelope: build + parse. + * + * On-chain output layout (hex bytes shown): + * + * 00 63 OP_FALSE OP_IF + * 03 6f 72 64 push "ord" (3-byte length-prefixed) + * 51 OP_1 — content-type tag (canonical, minimal-push) + * 12 push content-type bytes (18 = "application/bsv-20") + * 00 OP_0 (separator before content payload) + * push the JSON payload (variable-length) + * 68 OP_ENDIF + * 76 a9 14 <20-byte pkh> 88 ac + * P2PKH owner lock + * + * JSON payload shape (transfer): {"p":"bsv-20","op":"transfer","id":"","amt":""} + * Field order is fixed by our builder so the produced bytes are reproducible, + * but the parser accepts any order — the wire format is JSON, not byte-significant. + * + * Why OP_1 (0x51) for the content-type tag: the canonical Ordinals envelope + * uses minimal-push encoding (OP_1 for single-byte value 0x01). Earlier + * versions of this builder emitted the non-minimal `01 01` push, which the + * 1sat-stack `go-templates/bsv21` decoder rejects as non-canonical — meaning + * neither JungleBus auto-pickup nor direct `/1sat/bsv21/overlay/submit` + * would index our outputs. Verified empirically 2026-05-28 against + * `$NINJAPUNKGIRLS` and other indexed tokens; they all use OP_1. + * + * No dependency on @bopen-io/templates; this module talks bytes directly. + */ + +import { BSV20_CONTENT_TYPE } from './constants'; + +const ORD_TAG_HEX = '6f7264'; // "ord" +const OP_FALSE_HEX = '00'; +const OP_IF_HEX = '63'; +const OP_1_HEX = '51'; // OP_1 — canonical minimal-push of value 0x01 +const OP_ENDIF_HEX = '68'; +const OP_DUP_HEX = '76'; +const OP_HASH160_HEX = 'a9'; +const OP_EQUALVERIFY_HEX = '88'; +const OP_CHECKSIG_HEX = 'ac'; +const PKH_PUSH_LEN_HEX = '14'; // 20-byte hash160 push + +export interface Bsv21TransferPayload { + /** Token id — `_` of the deploy+mint output. */ + id: string; + /** Token amount, stringified bigint (raw integer units). */ + amt: string; + /** Decimals — only present on deploy+mint per spec, but we tolerate it. */ + dec?: number; + /** Optional symbol / ticker. */ + sym?: string; + /** Optional icon outpoint / URL. */ + icon?: string; +} + +export interface Bsv21BuildArgs { + payload: Bsv21TransferPayload; + /** P2PKH owner — hash160 hex (40 chars). */ + ownerHash160: string; +} + +export interface ParsedBsv21Output extends Bsv21TransferPayload { + /** 20-byte owner field (PKH), hex — the trailing P2PKH owner. */ + ownerHash160: string; +} + +/** Convert a UTF-8 string to lowercase hex. */ +function utf8ToHex(s: string): string { + const bytes = new TextEncoder().encode(s); + let h = ''; + for (const b of bytes) h += b.toString(16).padStart(2, '0'); + return h; +} + +/** Encode a Bitcoin pushdata for `bytes` (hex), returning the opcode+length+data hex. */ +function encodePushHex(bytesHex: string): string { + const len = bytesHex.length / 2; + if (len === 0) return '00'; // OP_0 + if (len <= 0x4b) { + return len.toString(16).padStart(2, '0') + bytesHex; + } + if (len <= 0xff) { + return '4c' + len.toString(16).padStart(2, '0') + bytesHex; + } + if (len <= 0xffff) { + const lo = len & 0xff; + const hi = (len >> 8) & 0xff; + return '4d' + lo.toString(16).padStart(2, '0') + hi.toString(16).padStart(2, '0') + bytesHex; + } + // 4-byte length (OP_PUSHDATA4) — BSV-20 payloads should never reach this size. + const b0 = len & 0xff; + const b1 = (len >> 8) & 0xff; + const b2 = (len >> 16) & 0xff; + const b3 = (len >> 24) & 0xff; + return ( + '4e' + + b0.toString(16).padStart(2, '0') + + b1.toString(16).padStart(2, '0') + + b2.toString(16).padStart(2, '0') + + b3.toString(16).padStart(2, '0') + + bytesHex + ); +} + +/** + * Build a BSV-21 transfer locking-script (hex). The payload's `op` is + * forced to `"transfer"` and `id`/`amt` are required. `dec`, `sym`, `icon` + * are optional and included only if defined. + */ +export function buildBsv21Transfer(args: Bsv21BuildArgs): string { + const { payload, ownerHash160 } = args; + if (!/^[0-9a-fA-F]{40}$/.test(ownerHash160)) { + throw new Error(`buildBsv21Transfer: ownerHash160 must be 40 hex chars (got ${ownerHash160.length})`); + } + + // Construct the BSV-20 JSON. Field order is fixed for reproducible bytes. + // EVERY value must serialize as a JSON string — 1sat-stack's + // `go-templates/bsv21` Decode unmarshals into `map[string]string`, so a + // numeric `dec` (e.g. `"dec": 10`) breaks `json.Unmarshal` and the + // topic-manager rejects the output with no error surfacing to us. + // `amt` is already a stringified bigint per spec; `dec` arrives as a + // JS number from the basket tag, so we coerce here. + const obj: Record = { + p: 'bsv-20', + op: 'transfer', + id: payload.id, + amt: payload.amt, + }; + if (payload.dec !== undefined) obj.dec = String(payload.dec); + if (payload.sym !== undefined) obj.sym = payload.sym; + if (payload.icon !== undefined) obj.icon = payload.icon; + const jsonHex = utf8ToHex(JSON.stringify(obj)); + + // ord envelope. + const ordTagPush = encodePushHex(ORD_TAG_HEX); // 03 6f 72 64 + // Content-type field tag: OP_1 (0x51), the canonical minimal-push of value 1. + // Was previously the non-minimal 01 01 form, which 1sat-stack's go-templates + // bsv21 decoder rejects as non-canonical. + const fieldIdContentType = OP_1_HEX; + const ctPush = encodePushHex(utf8ToHex(BSV20_CONTENT_TYPE)); + const separator = '00'; // OP_0 + const contentPush = encodePushHex(jsonHex); + + const envelope = + OP_FALSE_HEX + + OP_IF_HEX + + ordTagPush + + fieldIdContentType + + ctPush + + separator + + contentPush + + OP_ENDIF_HEX; + + const p2pkh = + OP_DUP_HEX + + OP_HASH160_HEX + + PKH_PUSH_LEN_HEX + + ownerHash160.toLowerCase() + + OP_EQUALVERIFY_HEX + + OP_CHECKSIG_HEX; + + return envelope + p2pkh; +} + +/** + * Reader over a hex-encoded script. Tracks a byte offset (in hex pairs) + * and exposes a tiny pushdata reader used by the parser. + */ +class HexReader { + pos = 0; + constructor(public readonly hex: string) {} + remaining(): number { return (this.hex.length - this.pos) / 2; } + readByteHex(): string | null { + if (this.pos + 2 > this.hex.length) return null; + const b = this.hex.substring(this.pos, this.pos + 2); + this.pos += 2; + return b; + } + readBytesHex(n: number): string | null { + if (this.pos + n * 2 > this.hex.length) return null; + const out = this.hex.substring(this.pos, this.pos + n * 2); + this.pos += n * 2; + return out; + } + /** Read the next pushdata's payload bytes (hex), advancing past the opcode + length. */ + readPushHex(): string | null { + const op = this.readByteHex(); + if (op === null) return null; + const code = parseInt(op, 16); + if (code === 0) return ''; // OP_0 + if (code >= 0x01 && code <= 0x4b) { + return this.readBytesHex(code); + } + if (code === 0x4c) { + const lenHex = this.readByteHex(); + if (lenHex === null) return null; + return this.readBytesHex(parseInt(lenHex, 16)); + } + if (code === 0x4d) { + const b1 = this.readByteHex(); const b2 = this.readByteHex(); + if (b1 === null || b2 === null) return null; + const len = parseInt(b2 + b1, 16); // LE + return this.readBytesHex(len); + } + if (code === 0x4e) { + const b1 = this.readByteHex(); const b2 = this.readByteHex(); + const b3 = this.readByteHex(); const b4 = this.readByteHex(); + if (!b1 || !b2 || !b3 || !b4) return null; + const len = parseInt(b4 + b3 + b2 + b1, 16); + return this.readBytesHex(len); + } + return null; // non-push opcode + } +} + +function hexToUtf8(hex: string): string { + const bytes: number[] = []; + for (let i = 0; i < hex.length; i += 2) bytes.push(parseInt(hex.substring(i, i + 2), 16)); + try { + return new TextDecoder('utf-8', { fatal: false }).decode(new Uint8Array(bytes)); + } catch { + return ''; + } +} + +/** + * Parse a locking script as a BSV-21 transfer (or deploy+mint) output. + * Returns null for non-BSV-21 scripts — never throws. + * + * Recognises both `OP_1 (0x51)` and `push-of-0x01` for the ord field-id + * marker, since toolboxes in the wild emit both shapes — including our own + * older outputs before the canonical-form fix. + */ +export function parseBsv21LockingScript(scriptHex: string): ParsedBsv21Output | null { + if (typeof scriptHex !== 'string' || scriptHex.length < 60) return null; + const lower = scriptHex.toLowerCase(); + // Must start with OP_FALSE OP_IF. + if (!lower.startsWith(OP_FALSE_HEX + OP_IF_HEX)) return null; + + const r = new HexReader(lower); + r.pos = 4; // past OP_FALSE OP_IF + + // First push: "ord". + const tag = r.readPushHex(); + if (tag !== ORD_TAG_HEX) return null; + + // Field id: 0x01 (content-type marker) — accept OP_1 (0x51) or push-of-1-byte-0x01. + const peek = lower.substring(r.pos, r.pos + 2); + if (peek === '51') { + r.pos += 2; + } else { + const fieldIdBytes = r.readPushHex(); + if (fieldIdBytes !== '01') return null; + } + + // Content-type push. + const ctHex = r.readPushHex(); + if (ctHex === null) return null; + const ct = hexToUtf8(ctHex); + if (ct !== BSV20_CONTENT_TYPE) return null; + + // OP_0 separator. + const sep = r.readByteHex(); + if (sep !== '00') return null; + + // Content payload — the BSV-20 JSON. + const contentHex = r.readPushHex(); + if (contentHex === null) return null; + const jsonText = hexToUtf8(contentHex); + let payload: any; + try { + payload = JSON.parse(jsonText); + } catch { + return null; + } + if (!payload || payload.p !== 'bsv-20') return null; + + // OP_ENDIF. + const endIf = r.readByteHex(); + if (endIf !== OP_ENDIF_HEX) return null; + + // Trailing P2PKH lock. + const dup = r.readByteHex(); + const hash160Op = r.readByteHex(); + const pushLen = r.readByteHex(); + if (dup !== OP_DUP_HEX || hash160Op !== OP_HASH160_HEX || pushLen !== PKH_PUSH_LEN_HEX) { + return null; + } + const ownerHash160 = r.readBytesHex(20); + if (!ownerHash160) return null; + const equalVerify = r.readByteHex(); + const checkSig = r.readByteHex(); + if (equalVerify !== OP_EQUALVERIFY_HEX || checkSig !== OP_CHECKSIG_HEX) return null; + + // Map JSON payload into our parsed shape. `op` may be 'transfer' or + // 'deploy+mint'; transfers have an `id`, mints don't (the deploy outpoint + // IS the id). Surface both — the caller picks what it needs. + const isMint = payload.op === 'deploy+mint'; + const id: string | undefined = isMint ? undefined : payload.id; + const amt: string | undefined = payload.amt; + if (!amt) return null; + + // `dec` is a string per spec ("0".."18") but we also accept a JS number + // for legacy outputs written before the canonical-form fix. + let dec: number | undefined; + if (typeof payload.dec === 'number' && Number.isFinite(payload.dec)) { + dec = payload.dec; + } else if (typeof payload.dec === 'string' && /^\d+$/.test(payload.dec)) { + const n = parseInt(payload.dec, 10); + if (Number.isFinite(n) && n >= 0 && n <= 18) dec = n; + } + + return { + // Mints don't have id in the payload; the caller resolves it from the + // outpoint at registration time. + id: id ?? '', + amt, + dec, + sym: typeof payload.sym === 'string' ? payload.sym : undefined, + icon: typeof payload.icon === 'string' ? payload.icon : undefined, + ownerHash160, + }; +} diff --git a/src/lib/services/tokens/dstas/DstasTransferService.ts b/src/lib/services/tokens/dstas/DstasTransferService.ts new file mode 100644 index 0000000..e5f2c73 --- /dev/null +++ b/src/lib/services/tokens/dstas/DstasTransferService.ts @@ -0,0 +1,635 @@ +/** + * DstasTransferService — DSTAS transfer via createAction + signAction. + * + * Same architectural shape as StasTransferService: wallet-toolbox owns + * the tx assembly + funding via createAction; the DSTAS input is signed + * externally via wallet.createSignature (BRC-42) and the unlocking script + * is hand-assembled to match the SDK's expected DSTAS witness format + * (mirror of dxs-bsv-token-sdk's input-builder.ts:91-178 — see + * buildDstasUnlockingScript.ts for the spec). + * + * Output layout (per DSTAS_SCRIPT_INVARIANTS.md §1 — Transfer): + * vout 0 = new DSTAS to recipient (spending-type=1, 1-to-1) + * vout 1 = BSV change back to funder + * + * Funding fragmentation suppressed the same way StasTransferService does + * (lower default basket's numberOfDesiredUTXOs to 0 around the call, + * restore on every exit path). + * + * Signing: + * - DSTAS input (our outpoint): externally via wallet.createSignature + * with the BRC-42 derivation that owns the DSTAS — same protocolID + * as classic STAS, since the receive namespace is shared. + * - BSV input (wallet-owned): the wallet signs it internally during + * signAction. + */ + +import type { WalletInterface } from '@bsv/sdk' +import { Beef } from '@bsv/sdk' +import { fromHex, toHex } from 'dxs-bsv-token-sdk/bsv' +// Leaf-module imports for SDK builders. We use namespace-import on each +// because Rollup's CJS plugin can't see names forwarded through +// __exportStar in the `/bsv` aggregator (same reason dstasParser.ts +// does this for LockingScriptReader). Each path is whitelisted in +// vendor/dxs-bsv-token-sdk/package.json's `exports` field. +import * as DstasLockingBuilderModule from 'dxs-bsv-token-sdk/script/build/dstas-locking-builder' +const { buildDstasLockingScript } = DstasLockingBuilderModule +import { STAS_PROTOCOL_ID, STAS_COUNTERPARTY } from '../../stas/constants' +import { DSTAS_BASKET } from '../../../constants/baskets' +import { parseDstasLockingScript } from '../../stas/dstasParser' +import { stasQuery } from '../../stas/stasIpc' +import { buildChainedAtomicBeef } from '../../stas/buildChainedAtomicBeef' +import { StasRegistration } from '../../stas/StasRegistration' +import { buildDstasUnlockingScript, DSTAS_SIGHASH_TYPE } from './buildDstasUnlockingScript' +import { tokenLog } from '../tokenLog' + +/** + * Dynamic bsv-js import — same pattern StasTransferService uses. + * `createRequire('module')` doesn't work in the Vite browser bundle; + * `await import('bsv')` does, and Vite pre-bundles bsv via optimizeDeps. + */ +async function loadBsvJs(): Promise { + const mod: any = await import('bsv') + return mod.default ?? mod +} + +const ORIGINATOR = 'admin.dstas-transfer' +const SIGHASH = DSTAS_SIGHASH_TYPE // 0x41 — ALL | FORKID + +export interface DstasTransferArgs { + source: { + txid: string + vout: number + scriptHex: string + satoshis: number + brc42KeyId: string + /** + * Optional owner-key derivation override for signing the DSTAS input. + * Defaults to the self-owned scheme (STAS_PROTOCOL_ID, keyID + * `brc42KeyId`, counterparty 'self'). A token received over a peer + * channel (BRC-29) is owned under a derivation keyed to the SENDER, so + * re-spending it requires `keyID = " "` and + * `counterparty = senderIdentityKey`. Backward compatible. + */ + owner?: { + protocolID?: [number, string] + keyID: string + counterparty: string + /** True for a BRC-29-received token: derive the recipient's OWN key. */ + forSelf?: boolean + } + } + recipientAddress: string + /** + * Token amount (satoshis) to send. Defaults to the full `source.satoshis`. + * When less, the service SPLITS: recipient DSTAS output of `amount` + a + * sender token-change DSTAS output of the remainder (to `senderChangeHash160`). + */ + amount?: number + /** Owner pkh (hex) for the sender's token-change DSTAS output (partial sends). */ + senderChangeHash160?: string + /** BRC-42 keyId of the sender's change receive key (for createAction tracking). */ + senderChangeKeyId?: string + /** Token id for the change output's customInstructions. */ + tokenId?: string +} + +export interface DstasTransferResult { + ok: boolean + txid?: string + reason?: string + /** Signed AtomicBEEF of the transfer (from signAction) — for peer delivery. */ + beef?: number[] +} + +export class DstasTransferService { + constructor( + private readonly wallet: WalletInterface, + private readonly identityKey: string, + private readonly chain: 'main' | 'test' + ) {} + + async transfer(args: DstasTransferArgs): Promise { + const { source, recipientAddress } = args + + let bsvJs: any + try { + bsvJs = await loadBsvJs() + } catch (err) { + return { ok: false, reason: `load bsv-js failed: ${errMsg(err)}` } + } + + // 1. Parse + validate the source. parseDstasLockingScript returns + // null for non-DSTAS scripts, surfaces frozen state via the + // action-data marker. We reject frozen UTXOs here (per + // DSTAS_SCRIPT_INVARIANTS.md — frozen STAS can't be spent under + // spendingType=1; freeze flow is its own surface). + const parsed = parseDstasLockingScript(source.scriptHex) + if (!parsed) { + return { + ok: false, + reason: `source.scriptHex doesn't parse as DSTAS — prefix "${source.scriptHex.slice(0, 24)}…"`, + } + } + if (parsed.frozen) { + return { + ok: false, + reason: 'source DSTAS UTXO is frozen — cannot transfer under spendingType=1', + } + } + + // 2. Owner pubkey via BRC-42 derivation. DSTAS shares STAS's + // receive namespace (see StasKeyDeriver) so the protocolID is + // the same. + // Effective owner-key derivation. Defaults to the self-owned scheme; a + // BRC-29 peer-received token overrides keyID + counterparty so it stays + // spendable. + const ownerDerivation = { + protocolID: (source.owner?.protocolID ?? STAS_PROTOCOL_ID) as any, + keyID: source.owner?.keyID ?? source.brc42KeyId, + counterparty: (source.owner?.counterparty ?? STAS_COUNTERPARTY) as any, + forSelf: source.owner?.forSelf === true, + } + + let ownerPubKeyHex: string + try { + const { publicKey } = await this.wallet.getPublicKey( + { + protocolID: ownerDerivation.protocolID, + keyID: ownerDerivation.keyID, + counterparty: ownerDerivation.counterparty, + forSelf: ownerDerivation.forSelf, + } as any, + ORIGINATOR + ) + ownerPubKeyHex = publicKey + } catch (err) { + return { ok: false, reason: `getPublicKey: ${errMsg(err)}` } + } + + // 3. Recipient hash160 (bsv-js parses base58check + extracts). + let recipientPkhHex: string + try { + const addr = bsvJs.Address.fromString(recipientAddress, 'livenet') + recipientPkhHex = addr.hashBuffer.toString('hex') + } catch (err) { + return { ok: false, reason: `invalid recipient: ${errMsg(err)}` } + } + + // 4. Build the new DSTAS output locking script via the SDK's pure + // builder. ownerPkh = recipient's hash160. Everything else + // propagates from the source (redemptionPkh, flags, + // serviceFields, optionalData byte-exact per §7 invariant). + // Fresh transfer → actionData: null, frozen: false. + // Resolve send amount vs. token change (SPLIT). Full-value keeps the + // single-output path; partial adds a sender token-change DSTAS output. + const sendAmt = args.amount ?? source.satoshis + const changeAmt = source.satoshis - sendAmt + if (!Number.isInteger(sendAmt) || sendAmt < 1 || changeAmt < 0) { + return { ok: false, reason: `invalid amount ${sendAmt} (must be 1..${source.satoshis})` } + } + if (changeAmt > 0 && !args.senderChangeHash160) { + return { ok: false, reason: 'partial DSTAS transfer requires senderChangeHash160' } + } + + let newDstasScriptHex: string + let changeDstasScriptHex: string | null = null + try { + const flagsBytes = fromHex(parsed.flagsHex || '00') + const serviceFields = parsed.serviceFields.map((s) => fromHex(s)) + const optionalData = parsed.optionalData.map((s) => fromHex(s)) + const buildFor = (ownerPkhHex: string) => toHex(buildDstasLockingScript({ + ownerPkh: fromHex(ownerPkhHex), + redemptionPkh: fromHex(parsed.tokenId), + flags: flagsBytes, + serviceFields, + optionalData, + actionData: null, + frozen: false, + })) + newDstasScriptHex = buildFor(recipientPkhHex) + if (changeAmt > 0 && args.senderChangeHash160) { + changeDstasScriptHex = buildFor(args.senderChangeHash160) + } + } catch (err) { + return { ok: false, reason: `build new DSTAS locking script: ${errMsg(err)}` } + } + + // 5. Build inputBEEF (chained-atomic so mempool ancestors are OK). + let inputBEEF: number[] + try { + const built = await buildChainedAtomicBeef({ wallet: this.wallet, txid: source.txid }) + inputBEEF = built.beef + } catch (err) { + return { ok: false, reason: `inputBEEF assembly: ${errMsg(err)}` } + } + + // 6. Mark the source spendable on wallet-toolbox's side — DSTAS + // outputs are flagged non-spendable by default (the toolbox + // doesn't recognise the custom template). + try { + const outputId: number | null = await stasQuery( + this.identityKey, + this.chain, + 'findOutputIdByOutpoint', + [source.txid, source.vout] + ) + if (outputId) { + await stasQuery(this.identityKey, this.chain, 'setOutputSpendable', [outputId, true]) + } + } catch { + /* best effort */ + } + + // 7. Suppress change fragmentation around the call — same as STAS + // transfer needs because the DSTAS template expects the funding + // branch to be a single P2PKH change output. + let previousBasketTarget: number | null = null + try { + const res: any = await stasQuery( + this.identityKey, + this.chain, + 'setDefaultBasketUTXOTarget', + [0] + ) + previousBasketTarget = res?.previous ?? null + } catch (err) { + tokenLog.warn( + '[dstas-transfer] setDefaultBasketUTXOTarget failed — fragmentation may break the template. ' + + 'Likely cause: stale dist-electron build. Fully restart `npm run dev`. Error:', + err + ) + } + const restoreBasket = async () => { + if (previousBasketTarget != null) { + try { + await stasQuery( + this.identityKey, + this.chain, + 'setDefaultBasketUTXOTarget', + [previousBasketTarget] + ) + } catch { /* best effort */ } + } + } + + try { + // 8. createAction. Wallet auto-funds + adds the BSV change output. + // Conservation: source.satoshis tokens → new DSTAS output gets + // the same satoshis (DSTAS transfer is 1-to-1 per §1). + let createRes: any + try { + createRes = await this.wallet.createAction( + { + labels: ['peertoken'], + inputBEEF, + inputs: [ + { + outpoint: `${source.txid}.${source.vout}`, + // DSTAS unlocking script is comparable in size to classic STAS + // (~3 KB worst-case) — we'll let bsv-js compute the actual size + // post-build; the estimate guides createAction's fee math. + unlockingScriptLength: 4500, + inputDescription: 'DSTAS being transferred', + }, + ], + outputs: [ + { + lockingScript: newDstasScriptHex, + satoshis: sendAmt, + outputDescription: 'DSTAS to recipient', + }, + ...(changeDstasScriptHex != null + ? [{ + lockingScript: changeDstasScriptHex, + satoshis: changeAmt, + outputDescription: 'DSTAS token change', + // Declare the basket so the wallet tracks this self-owned + // change output natively (mirrors STAS/BSV-21 change). + basket: DSTAS_BASKET, + customInstructions: JSON.stringify({ + brc42KeyId: args.senderChangeKeyId, + tokenId: args.tokenId, + }), + tags: ['dstas'], + }] + : []), + ], + description: 'DSTAS transfer', + options: { randomizeOutputs: false }, + } as any, + ORIGINATOR + ) + } catch (err) { + return { ok: false, reason: `createAction: ${errMsg(err)}` } + } + + const signable = createRes?.signableTransaction + if (!signable || !signable.tx) { + return { ok: false, reason: 'createAction did not return signableTransaction' } + } + + // 9. Parse signable.tx (AtomicBEEF) → atomic tx → bsv-js Transaction + // so we can compute sighash + walk outputs for the unlock builder. + let tx: any + try { + const beef = Beef.fromBinary(signable.tx) + const atomicTxid = (beef as any).atomicTxid as string | undefined + if (!atomicTxid) return { ok: false, reason: 'signable BEEF has no atomic txid' } + const btx = beef.findTxid(atomicTxid) + if (!btx?.tx) return { ok: false, reason: `signable BEEF missing atomic tx ${atomicTxid}` } + const rawTxBytes = btx.tx.toBinary() + tx = new bsvJs.Transaction(Buffer.from(rawTxBytes).toString('hex')) + // Attach the source's prev-output for sighash computation. + tx.inputs[0].output = new bsvJs.Transaction.Output({ + script: bsvJs.Script.fromHex(source.scriptHex), + satoshis: source.satoshis, + }) + } catch (err) { + return { ok: false, reason: `parse signable tx: ${errMsg(err)}` } + } + + // 10. Resolve the funding input. The DSTAS template encodes EXACTLY + // ONE funding outpoint (vout + txid) into the unlock witness; + // the template verifies this matches the tx's prevout hash. + // wallet-toolbox normally pulls a single funding input, but + // if the default basket only has fragments smaller than the + // fee, it combines multiple — which the template can't accept. + // Same constraint applies to the SDK's `BuildDstasTransferTx` + // (see `input-builder.ts:resolveFundingInput`). + // + // Fail clean here so the user gets an actionable message + // instead of a cryptic "OP_EQUALVERIFY required equal" deep + // in the script evaluator. + const nonDstasInputs: number[] = [] + for (let i = 0; i < tx.inputs.length; i++) { + if (i === 0) continue // input 0 is our DSTAS source + nonDstasInputs.push(i) + } + if (nonDstasInputs.length === 0) { + return { ok: false, reason: 'no funding input found in the assembled tx' } + } + if (nonDstasInputs.length > 1) { + return { + ok: false, + reason: + `DSTAS template requires exactly one funding input, but wallet-toolbox ` + + `picked ${nonDstasInputs.length} from the default basket — likely ` + + `because no single change UTXO is large enough to cover the tx fee. ` + + `Workaround: consolidate the default basket by sending a small BSV ` + + `self-payment to yourself first, then retry the DSTAS send. ` + + `(Same architectural constraint applies to the SDK's BuildDstasTransferTx.)`, + } + } + const fundingInputIdx = nonDstasInputs[0] + + // Same constraint on outputs: the DSTAS template walks outputs and + // expects exactly the recipient DSTAS output + at most 1 P2PKH + // change output (+ optional null-data). Multiple P2PKH outputs from + // fragmentation would break the template's per-output handling. + let p2pkhOutputCount = 0 + for (const out of tx.outputs) { + const sh = out.script.toHex() + if (sh.startsWith('76a914') && sh.endsWith('88ac') && sh.length === 50) { + p2pkhOutputCount++ + } + } + if (p2pkhOutputCount > 1) { + return { + ok: false, + reason: + `DSTAS template requires at most one P2PKH change output, but the ` + + `assembled tx has ${p2pkhOutputCount}. Same root cause as the ` + + `multi-funding-input case — consolidate the default basket first.`, + } + } + + tokenLog.debug( + `[dstas-transfer] tx shape: ${tx.inputs.length} inputs (DSTAS at 0, funding at ${fundingInputIdx}), ${tx.outputs.length} outputs` + ) + + // 11. Sighash + signature for input 0. + let sigDer: Uint8Array + let preimage: Uint8Array + try { + const sourceLocking = bsvJs.Script.fromHex(source.scriptHex) + const satsBN = new bsvJs.crypto.BN(source.satoshis) + const preimageBuf: Buffer = bsvJs.Transaction.sighash.sighashPreimage( + tx, SIGHASH, 0, sourceLocking, satsBN + ) + preimage = new Uint8Array(preimageBuf) + const digestBuf = bsvJs.crypto.Hash.sha256sha256(preimageBuf) + const digestBytes = Array.from(digestBuf as Buffer) as number[] + + const sigRes = await this.wallet.createSignature( + { + protocolID: ownerDerivation.protocolID, + keyID: ownerDerivation.keyID, + counterparty: ownerDerivation.counterparty, + hashToDirectlySign: digestBytes, + } as any, + ORIGINATOR + ) + sigDer = new Uint8Array(sigRes.signature) + } catch (err) { + return { ok: false, reason: `sighash/sign: ${errMsg(err)}` } + } + + // 12. Assemble DSTAS unlocking script via our helper (mirror of + // SDK's input-builder.ts:91-178). + let unlockingScriptHex: string + try { + unlockingScriptHex = buildDstasUnlockingScript({ + unsignedTx: tx, + inputIdx: 0, + fundingInputIdx, + preimage, + signatureDer: sigDer, + publicKey: new Uint8Array(Buffer.from(ownerPubKeyHex, 'hex')), + spendingType: 1, + }) + } catch (err) { + return { ok: false, reason: `assemble DSTAS unlocking script: ${errMsg(err)}` } + } + + // 13. Best-effort pre-broadcast script-level diagnostic. + // + // The SDK's AGENTS.md mandates `evaluateTransactionHex` for + // "every flow-producing change" — but that's a normative rule + // for SDK developers writing fully-signed test fixtures, not + // a wallet running mid-flow validation. At THIS point in our + // flow the funding input (input 1) is still unsigned — the + // wallet only signs it inside the upcoming `signAction` call. + // So a full-tx evaluation will fail on input 1 regardless of + // whether our DSTAS input 0 is byte-perfect. + // + // We run the evaluator anyway as a diagnostic and log its + // result, but we DO NOT gate the broadcast on it — chain + // validation is the real backstop and StasTransferService + // follows the same trust-the-wallet-and-the-chain model. + // + // If the evaluator surfaces a structured per-input result we + // can later harden this into "input 0 must pass" — left as a + // TODO until we see what the evaluator actually returns. + try { + const evalResult = await evaluateDstasInputZero({ + tx, + sourceScriptHex: source.scriptHex, + sourceSatoshis: source.satoshis, + unlockingScriptHex, + }) + if (evalResult.success) { + tokenLog.debug('[dstas-transfer] script-evaluator pre-broadcast: success') + } else { + // Expected when the funding input isn't signed yet — log full + // diagnostic so a real failure mode (e.g. byte-mismatch on + // input 0's unlock) can be diagnosed from the dev tools. + tokenLog.warn( + '[dstas-transfer] script-evaluator pre-broadcast: NON-SUCCESS (expected — funding input still unsigned at this point). ' + + `Diagnostic: ${evalResult.reason ?? 'no detail'}` + ) + if (evalResult.fullResult) { + tokenLog.warn('[dstas-transfer] full evaluator result:', evalResult.fullResult) + } + } + } catch (err) { + tokenLog.warn(`[dstas-transfer] script-evaluator threw: ${errMsg(err)}`) + } + + // 14. signAction. wallet-toolbox signs the funding input and + // queues the broadcast; monitor worker handles relay. + let signResp: any + try { + signResp = await this.wallet.signAction( + { + reference: signable.reference, + spends: { 0: { unlockingScript: unlockingScriptHex } }, + } as any, + ORIGINATOR + ) + } catch (err) { + return { ok: false, reason: `signAction: ${errMsg(err)}` } + } + + const sendResults: any[] = Array.isArray(signResp?.sendWithResults) + ? signResp.sendWithResults + : [] + const failed = sendResults.find((r) => r?.status === 'failed') + if (failed) { + return { + ok: false, + reason: `broadcast failed: ${JSON.stringify(failed)} (txid was ${signResp?.txid})`, + } + } + + const wocBase = this.chain === 'main' ? 'https://whatsonchain.com/tx/' : 'https://test.whatsonchain.com/tx/' + tokenLog.info(`[dstas-transfer] BROADCAST ✓ txid: ${signResp?.txid} ${wocBase}${signResp?.txid}`) + + // 16. Link the sender's token-change output (vout 1) into the satellite + // tables. The Assets view reads DSTAS holdings from `listStasOutputs`, + // not from the basket, so without this the remainder of a partial send + // is invisible until a discovery scan re-finds it on-chain. We built + // the output, so there is nothing to discover. `skipInternalize`: + // createAction already declared its basket. Idempotent — the peer + // settlement adapter's own registration then reports 'already + // registered'. + if (changeDstasScriptHex != null && args.senderChangeHash160 && signResp?.txid) { + try { + const parsedChange = parseDstasLockingScript(source.scriptHex) + const r = await new StasRegistration(this.wallet, this.identityKey, this.chain).register({ + txid: signResp.txid, + vout: 1, + tokenSatoshis: changeAmt, + ownerFieldHash160: args.senderChangeHash160, + brc42KeyId: args.senderChangeKeyId ?? source.brc42KeyId, + parsed: { + ...(parsedChange ?? {}), + ownerFieldHash160: args.senderChangeHash160, + tokenId: args.tokenId ?? '', + } as any, + protocol: { id: 'dstas', basketName: DSTAS_BASKET }, + skipInternalize: true, + }) + if (!r.registered && r.reason !== 'already registered') { + tokenLog.warn(`[dstas-transfer] token-change NOT registered: ${r.reason} (scan will recover)`) + } + } catch (err) { + tokenLog.warn(`[dstas-transfer] token-change registration threw: ${errMsg(err)} (scan will recover)`) + } + } + + return { ok: true, txid: signResp?.txid, beef: signResp?.tx } + } finally { + await restoreBasket() + } + } +} + +/** + * Apply the unlocking script to tx.inputs[0] and run the SDK's + * evaluator. Returns `{ success, reason? }`. The evaluator wants the + * source's prev-output supplied via a resolver callback so it can look + * up the locking script and satoshis during script execution. + * + * Imported via the leaf-module path (whitelisted in the SDK's exports) + * to bypass Rollup's __exportStar blindness — same pattern dstasParser + * uses for LockingScriptReader. + */ +async function evaluateDstasInputZero(args: { + tx: any + sourceScriptHex: string + sourceSatoshis: number + unlockingScriptHex: string +}): Promise<{ success: boolean; reason?: string; fullResult?: any }> { + let evaluateTransactionHex: any + try { + const evalMod: any = await import( + 'dxs-bsv-token-sdk/script/eval/script-evaluator' + ) + evaluateTransactionHex = evalMod.evaluateTransactionHex + } catch { + /* fall through to no-op */ + } + if (typeof evaluateTransactionHex !== 'function') { + return { success: true, reason: 'evaluator unavailable in this environment' } + } + try { + args.tx.inputs[0].setScript(args.unlockingScriptHex) + const txHex: string = args.tx.toString() + const result = evaluateTransactionHex(txHex, (txid: string, vout: number) => { + const sourcePrevTxIdHex: string = + typeof args.tx.inputs[0].prevTxId === 'string' + ? args.tx.inputs[0].prevTxId + : Buffer.from(args.tx.inputs[0].prevTxId).toString('hex') + if (txid === sourcePrevTxIdHex && vout === args.tx.inputs[0].outputIndex) { + return { + LockingScript: new Uint8Array(Buffer.from(args.sourceScriptHex, 'hex')), + Satoshis: args.sourceSatoshis, + } + } + // Funding input's prev-output: we don't have it cached here, so the + // evaluator may report a resolver miss. That's expected — we want + // input 0's result, not the full-tx pass. + return null + }) + // Surface a structured summary plus the full result for the caller + // to log. The SDK's `evaluateTransactionHex` historically returns + // `{ success, results: InputResult[], failureReason? }`; field names + // vary across versions so we keep `fullResult` opaque for diagnostics. + const reason = result?.failureReason + ?? result?.results?.find?.((r: any) => r && r.success === false)?.reason + ?? (result?.success ? undefined : 'evaluator returned non-success (see fullResult)') + return { + success: !!result?.success, + reason, + fullResult: result, + } + } catch (err) { + return { success: false, reason: errMsg(err) } + } +} + +function errMsg(err: unknown): string { + return err instanceof Error ? err.message : String(err) +} + diff --git a/src/lib/services/tokens/dstas/buildDstasUnlockingScript.ts b/src/lib/services/tokens/dstas/buildDstasUnlockingScript.ts new file mode 100644 index 0000000..c9abec7 --- /dev/null +++ b/src/lib/services/tokens/dstas/buildDstasUnlockingScript.ts @@ -0,0 +1,306 @@ +/** + * Build the DSTAS unlocking script for a regular spend (spendingType=1). + * + * This is the load-bearing piece of F3 — it mirrors + * `dxs-bsv-token-sdk/src/transaction/build/input-builder.ts:91-178` byte + * for byte. The SDK builds the script inside `InputBuilder.sign()`; the + * helper isn't exported, so we reproduce it here. Any drift between our + * code and the SDK template would manifest as `evaluateTransactionHex` + * rejection in tests — which is exactly why the SDK's `AGENTS.md` + * mandates script-level evaluation as the validation backstop. + * + * Script content (in order): + * + * for each output: + * if null-data: + * push + * else: + * push (ScriptNum-encoded) + * push + * if DSTAS output: + * push ← bytes or sentinel opcode + * if no P2PKH change output: + * push OP_0 OP_0 + * if no null-data output: + * push OP_0 + * push (ScriptNum) + * push (32 bytes) + * push OP_0 (not-merge marker) + * push + * push (DSTAS only — 1 byte for spendingType=1) + * push + * push (33-byte compressed) + * + * The DSTAS-output owner field comes from `LockingScriptReader.Dstas.Owner` + * (token 0). The P2PKH-change owner field is the hash160 push inside the + * canonical `76 a9 14 88 ac` shape. + */ + +import { fromHex, toHex, ScriptType } from 'dxs-bsv-token-sdk/bsv' +// Same namespace-import escape hatch we use in dstasParser.ts — see the +// long comment there. The leaf-module path is whitelisted in the SDK's +// `exports` field. +import * as LockingScriptReaderModule from 'dxs-bsv-token-sdk/script/read/locking-script-reader' +const { LockingScriptReader } = LockingScriptReaderModule +// We never instantiate bsv-js here — the unlock builder reads +// duck-typed `unsignedTx.outputs[i]` / `unsignedTx.inputs[i]` shapes +// from whatever bsv-js Transaction the caller hands us. + +/** SIGHASH_ALL | SIGHASH_FORKID — the SDK's `DefaultSighashType`. */ +export const DSTAS_SIGHASH_TYPE = 0x41 + +export interface DstasUnlockSpec { + /** Unsigned tx (bsv-js Transaction). */ + unsignedTx: any + /** Index of the DSTAS input in `unsignedTx.inputs`. */ + inputIdx: number + /** Index of the BSV funding input — must be exactly one. */ + fundingInputIdx: number + /** Sighash preimage bytes (already computed via bsv-js). */ + preimage: Uint8Array + /** ECDSA signature bytes (DER-encoded), without the trailing sighash byte. */ + signatureDer: Uint8Array + /** Compressed public key bytes (33 bytes). */ + publicKey: Uint8Array + /** Spending type for DSTAS template — 1 = regular transfer. */ + spendingType: number +} + +// ──────────────── byte-encoding primitives ──────────────── + +/** Concatenate Uint8Arrays. */ +function concatBytes(parts: Uint8Array[]): Uint8Array { + const total = parts.reduce((n, p) => n + p.length, 0) + const out = new Uint8Array(total) + let off = 0 + for (const p of parts) { + out.set(p, off) + off += p.length + } + return out +} + +/** + * Bitcoin pushdata wrapper. Emits opcode + (length byte | length bytes) + + * payload. For length 0 emits OP_0 alone. + */ +function pushBytes(payload: Uint8Array): Uint8Array { + const len = payload.length + if (len === 0) return new Uint8Array([0x00]) // OP_0 + if (len <= 0x4b) { + return concatBytes([new Uint8Array([len]), payload]) + } + if (len <= 0xff) { + return concatBytes([new Uint8Array([0x4c, len]), payload]) + } + if (len <= 0xffff) { + return concatBytes([ + new Uint8Array([0x4d, len & 0xff, (len >> 8) & 0xff]), + payload, + ]) + } + // OP_PUSHDATA4 — never reached for DSTAS witness sizes. + return concatBytes([ + new Uint8Array([0x4e, len & 0xff, (len >> 8) & 0xff, (len >> 16) & 0xff, (len >> 24) & 0xff]), + payload, + ]) +} + +/** + * Bitcoin ScriptNum encoding for non-negative integers, matching the + * SDK's `ScriptBuilder.addNumber` exactly: + * + * 0 → OP_0 (single byte 0x00, empty stack push) + * 1..16 → OP_1..OP_16 (single bytes 0x51..0x60) + * 17+ → length-prefixed minimal LE magnitude bytes + * + * The 1..16 special case is REQUIRED by BSV post-Genesis: the script + * evaluator enforces minimal push encoding and rejects `01 NN` for + * NN ∈ {1..16} as "data not minimally encoded". The bug previously + * surfaced as a DSTAS unlock failure when fundingVout ∈ {1..16} or + * spendingType=1 was pushed via the data-push form. + * + * For values > 0x7f the high bit triggers a sign byte — we append + * `0x00` to keep the value positive (CScriptNum convention). + */ +function scriptNumPush(n: number | bigint): Uint8Array { + const value = typeof n === 'bigint' ? n : BigInt(n) + if (value === 0n) return new Uint8Array([0x00]) // OP_0 + if (value < 0n) throw new Error('scriptNumPush: negative numbers not supported here') + // OP_1 (0x51) through OP_16 (0x60). Mandatory for minimality. + if (value <= 16n) return new Uint8Array([0x50 + Number(value)]) + + // Minimal little-endian magnitude bytes. + let v = value + const bytes: number[] = [] + while (v > 0n) { + bytes.push(Number(v & 0xffn)) + v >>= 8n + } + // If high bit set on the last byte, push an extra 0x00 to keep it positive. + if (bytes[bytes.length - 1]! & 0x80) bytes.push(0x00) + return pushBytes(new Uint8Array(bytes)) +} + +/** Push a single sentinel opcode byte. */ +function pushOpcode(op: number): Uint8Array { + return new Uint8Array([op]) +} + +const OP_0 = 0x00 +const OP_RETURN = 0x6a + +// ──────────────── output classification (mirror of input-builder.ts) ──────────────── + +interface OutputInfo { + scriptType: 'p2pkh' | 'dstas' | 'nullData' | 'other' + ownerField?: Uint8Array + actionDataToken?: { data?: Uint8Array; opCode?: number } + /** For null-data: the payload bytes AFTER OP_RETURN's pushdata header. */ + nullDataPayload?: Uint8Array +} + +function classifyOutput(scriptBytes: Uint8Array): OutputInfo { + // null-data sniff: OP_RETURN at byte 0, OR OP_FALSE OP_RETURN at bytes 0/1 + if (scriptBytes.length >= 2 && scriptBytes[0] === OP_RETURN) { + return { + scriptType: 'nullData', + // Strip the OP_RETURN byte + its pushdata header. The SDK does + // `payload = nulldata.subarray(2)` which assumes single-byte + // pushdata length follows immediately after OP_RETURN; we replicate. + nullDataPayload: scriptBytes.slice(2), + } + } + if (scriptBytes.length >= 3 && scriptBytes[0] === 0x00 && scriptBytes[1] === OP_RETURN) { + return { scriptType: 'nullData', nullDataPayload: scriptBytes.slice(3) } + } + + // P2PKH: 76 a9 14 <20> 88 ac + if ( + scriptBytes.length === 25 && + scriptBytes[0] === 0x76 && scriptBytes[1] === 0xa9 && + scriptBytes[2] === 0x14 && scriptBytes[23] === 0x88 && + scriptBytes[24] === 0xac + ) { + return { + scriptType: 'p2pkh', + ownerField: scriptBytes.slice(3, 23), + } + } + + // Else try DSTAS via the SDK's reader. + try { + const reader: any = LockingScriptReader.read(scriptBytes) + if (reader && reader.ScriptType === ScriptType.dstas && reader.Dstas?.Owner) { + const d = reader.Dstas + return { + scriptType: 'dstas', + ownerField: d.Owner, + actionDataToken: d.ActionDataRaw + ? { data: d.ActionDataRaw } + : { opCode: d.ActionDataOpCode }, + } + } + } catch { + /* fall through */ + } + return { scriptType: 'other' } +} + +// ──────────────── main builder ──────────────── + +export function buildDstasUnlockingScript(spec: DstasUnlockSpec): string { + const { unsignedTx, fundingInputIdx, preimage, signatureDer, publicKey, spendingType } = spec + + // Re-encode the signature with the sighash type byte appended — same + // shape `InputBuilder.sign` produces (`derWithSigHashType`). + const sigWithType = new Uint8Array(signatureDer.length + 1) + sigWithType.set(signatureDer) + sigWithType[signatureDer.length] = DSTAS_SIGHASH_TYPE + + const chunks: Uint8Array[] = [] + let hasNote = false + let hasChangeOutput = false + + // ── per-output encoding ── + for (let i = 0; i < unsignedTx.outputs.length; i++) { + const out = unsignedTx.outputs[i] + const scriptBytes: Uint8Array = new Uint8Array(out.script.toBuffer()) + const info = classifyOutput(scriptBytes) + + if (info.scriptType === 'nullData') { + // Push the payload bytes after OP_RETURN's pushdata header. + chunks.push(pushBytes(info.nullDataPayload!)) + hasNote = true + continue + } + + if (!info.ownerField) { + throw new Error(`output ${i}: cannot recover owner field (script type ${info.scriptType})`) + } + + // Satoshis (ScriptNum-encoded) + ownerField (raw pushdata of the + // 20-byte hash160). + chunks.push(scriptNumPush(BigInt(out.satoshis))) + chunks.push(pushBytes(info.ownerField)) + + if (info.scriptType === 'dstas') { + const t = info.actionDataToken! + if (t.data) { + chunks.push(pushBytes(t.data)) + } else if (typeof t.opCode === 'number') { + chunks.push(pushOpcode(t.opCode)) + } else { + throw new Error(`output ${i}: DSTAS output missing action-data token`) + } + } + + if (info.scriptType === 'p2pkh') { + hasChangeOutput = true + } + } + + if (!hasChangeOutput) { + chunks.push(pushOpcode(OP_0)) + chunks.push(pushOpcode(OP_0)) + } + if (!hasNote) { + chunks.push(pushOpcode(OP_0)) + } + + // ── funding outpoint pointers ── + const fundingInput = unsignedTx.inputs[fundingInputIdx] + if (!fundingInput) throw new Error(`funding input idx ${fundingInputIdx} out of range`) + const fundingVout: number = fundingInput.outputIndex + // bsv-js stores prevTxId as a Buffer in BIG-endian byte order; the + // SDK pushes the LITTLE-endian (reversed) hash bytes here. Confirm by + // examining types: tx.inputs[i].prevTxId is Buffer; bsv-js exposes + // both endianness via toString('hex') (big) and the raw buffer. + const prevTxIdBuf: Buffer = + typeof fundingInput.prevTxId === 'string' + ? Buffer.from(fundingInput.prevTxId, 'hex') + : Buffer.from(fundingInput.prevTxId) + const reversedFundingTxId = new Uint8Array(prevTxIdBuf).reverse() + + chunks.push(scriptNumPush(BigInt(fundingVout))) + chunks.push(pushBytes(reversedFundingTxId)) + + // ── merge marker (not-merge for transfer) ── + chunks.push(pushOpcode(OP_0)) + + // ── sighash preimage ── + chunks.push(pushBytes(preimage)) + + // ── DSTAS spending-type byte ── + chunks.push(scriptNumPush(BigInt(spendingType))) + + // ── signature + pubkey ── + chunks.push(pushBytes(sigWithType)) + chunks.push(pushBytes(publicKey)) + + return toHex(concatBytes(chunks)) +} + +// Kept in the import surface for future use (e.g., constructing a +// sourceLockingScript from hex inputs in tests). +void fromHex diff --git a/src/lib/services/tokens/index.ts b/src/lib/services/tokens/index.ts new file mode 100644 index 0000000..22720a6 --- /dev/null +++ b/src/lib/services/tokens/index.ts @@ -0,0 +1,12 @@ +/** + * Token-protocol adapter layer — the single seam between protocol-specific + * logic (STAS, DSTAS, BSV-21) and the shared discovery / registration / UI + * pipeline. + */ + +export * from './TokenProtocolAdapter'; +export * from './TokenProtocolRegistry'; +export * from './StasProtocolAdapter'; +export * from './DstasProtocolAdapter'; +export * from './BSV21ProtocolAdapter'; +export * from './bsv21'; diff --git a/src/lib/services/tokens/peer/Bsv21TokenSettlementAdapter.ts b/src/lib/services/tokens/peer/Bsv21TokenSettlementAdapter.ts new file mode 100644 index 0000000..1b10c26 --- /dev/null +++ b/src/lib/services/tokens/peer/Bsv21TokenSettlementAdapter.ts @@ -0,0 +1,214 @@ +/** + * Bsv21TokenSettlementAdapter — concrete TokenSettlementAdapter for BSV-21. + * + * The BSV-21 analog of StasTokenSettlementAdapter. Because BSV-21 ownership is + * plain P2PKH (no engine), the peer flow is closer to PeerPay's BRC-29: + * - buildTokenSettlement derives the recipient's owner key BRC-29-style + * (counterparty = recipient) and reuses BSV21TransferService.transfer, + * which supports divisible/partial sends (recipient + token-change); + * - acceptTokenSettlement internalizes the recipient output into the BSV-21 + * basket, recording the BRC-29 derivation so the token stays re-spendable. + * + * The TokenSettlementAdapter interface is mirrored locally (see + * ./tokenSettlementTypes) until @bsv/message-box-client publishes it. + */ +import type { WalletInterface } from '@bsv/sdk'; +import { Hash, Utils, createNonce, Beef } from '@bsv/sdk'; +import { BSV21TransferService, type BSV21TransferDeps } from '../bsv21/BSV21TransferService'; +import { buildChainedAtomicBeef } from '../../stas/buildChainedAtomicBeef'; +import { parseBsv21LockingScript } from '../bsv21/inscription'; +import { verifyAndPersistOnReceive } from '../verifyOnReceive'; +import { BSV21_PROTOCOL_ID } from '../bsv21/constants'; +import { BSV21_BASKET } from '../../../constants/baskets'; +import type { + TokenSettlementAdapter, TokenSourceRef, TokenSettlementArtifact, + TokenAdapterContext, TokenBuildResult, TokenAcceptResult, +} from './tokenSettlementTypes'; + +const ORIGINATOR = 'admin.bsv21-peer'; + +function errMsg(err: unknown): string { + return err instanceof Error ? err.message : String(err); +} + +export type Bsv21AdapterDeps = BSV21TransferDeps; + +export class Bsv21TokenSettlementAdapter implements TokenSettlementAdapter { + readonly protocol = 'bsv-21'; + private readonly wallet: WalletInterface; + private readonly chain: 'main' | 'test'; + + constructor(private readonly deps: Bsv21AdapterDeps) { + this.wallet = deps.wallet; + this.chain = deps.chain; + } + + /** BRC-29-style derivation so the recipient can reconstruct the owner key. */ + private async deriveRecipientAddress( + recipient: string, + derivationPrefix: string, + derivationSuffix: string + ): Promise { + const { publicKey } = await this.wallet.getPublicKey( + { + protocolID: BSV21_PROTOCOL_ID as any, + keyID: `${derivationPrefix} ${derivationSuffix}`, + counterparty: recipient as any, + }, + ORIGINATOR + ); + const pkh = Hash.hash160(Utils.toArray(publicKey, 'hex')); + const versionByte = this.chain === 'main' ? 0x00 : 0x6f; + return Utils.toBase58Check(pkh, [versionByte]); + } + + async buildTokenSettlement( + args: { recipient: string; source: TokenSourceRef; amount: string }, + ctx: TokenAdapterContext + ): Promise { + const { recipient, source, amount } = args; + try { + const derivationPrefix = await createNonce(this.wallet, 'self', ctx.originator); + const derivationSuffix = await createNonce(this.wallet, 'self', ctx.originator); + const recipientAddress = await this.deriveRecipientAddress(recipient, derivationPrefix, derivationSuffix); + + // Dry run: prove derivation + validation only — never touch the chain. + if (ctx.dryRun) { + ctx.logger?.log(`[bsv-21 dry-run] would transfer ${amount} to ${recipientAddress}`); + return { + action: 'settle', + artifact: { + customInstructions: { derivationPrefix, derivationSuffix }, + transaction: [], + protocol: 'bsv-21', + assetId: source.assetId, + amount, + outputIndex: 0, + }, + }; + } + + const transfer = new BSV21TransferService(this.deps); + const res = await transfer.transfer({ + source: { + txid: source.txid, + vout: source.outputIndex, + scriptHex: source.lockingScriptHex, + satoshis: source.satoshis, + brc42KeyId: source.brc42KeyId ?? 'recv 0', + tokenId: source.assetId, + amt: String(source.amt ?? amount), + dec: source.dec as number | undefined, + sym: source.sym as string | undefined, + icon: source.icon as string | undefined, + owner: source.owner, + }, + amount, + recipientAddress, + }); + if (!res.ok || res.txid == null) { + return { action: 'terminate', termination: { code: 'bsv21.transfer_failed', message: res.reason ?? 'transfer failed' } }; + } + + const transaction = (res.beef && res.beef.length > 0) + ? res.beef + : (await buildChainedAtomicBeef({ wallet: this.wallet, txid: res.txid })).atomicBeef; + + return { + action: 'settle', + artifact: { + customInstructions: { derivationPrefix, derivationSuffix }, + transaction, + protocol: 'bsv-21', + assetId: source.assetId, + amount, + outputIndex: 0, // recipient BSV-21 output is built first + txid: res.txid, + }, + }; + } catch (err) { + return { action: 'terminate', termination: { code: 'bsv21.build_error', message: errMsg(err) } }; + } + } + + async acceptTokenSettlement( + args: { sender: string; settlement: TokenSettlementArtifact }, + _ctx: TokenAdapterContext + ): Promise { + const { sender, settlement } = args; + try { + // Parse the received inscription from the delivered BEEF so the holding + // displays with its amount/symbol (BSV-21 holdings are read from the + // basket tags, unlike STAS/DSTAS which use the satellite tables). + let amt = settlement.amount; + let dec: number | undefined; + let sym: string | undefined; + let icon: string | undefined; + try { + const beef = Beef.fromBinary(settlement.transaction); + const txid = (beef as any).atomicTxid as string | undefined + ?? (beef as any).txs?.[(beef as any).txs.length - 1]?.txid; + const btx = txid != null ? beef.findTxid(txid) : undefined; + const out = btx?.tx?.outputs[settlement.outputIndex]; + const parsed = out != null ? parseBsv21LockingScript(out.lockingScript.toHex()) : null; + if (parsed != null) { amt = parsed.amt; dec = parsed.dec; sym = parsed.sym; icon = parsed.icon; } + } catch { /* fall back to settlement.amount */ } + + // Store the BRC-29 owner derivation so the received token is re-spendable + // (the holdings loader decodes scheme:'brc29' into a source.owner override + // with counterparty = sender, forSelf:true). + const customInstructions = JSON.stringify({ + scheme: 'brc29', + kind: 'bsv-21', + tokenId: settlement.assetId, + derivationPrefix: settlement.customInstructions.derivationPrefix, + derivationSuffix: settlement.customInstructions.derivationSuffix, + senderIdentityKey: sender, + }); + + const tags = ['bsv21', 'peer', `id:${settlement.assetId}`, `amt:${amt}`]; + if (dec !== undefined) tags.push(`dec:${dec}`); + if (sym !== undefined) tags.push(`sym:${sym}`); + if (icon !== undefined) tags.push(`icon:${icon}`); + + const internalizeResult = await this.wallet.internalizeAction( + { + tx: settlement.transaction, + outputs: [ + { + outputIndex: settlement.outputIndex, + protocol: 'basket insertion', + insertionRemittance: { + basket: BSV21_BASKET, + customInstructions, + tags, + }, + }, + ], + description: 'BSV-21 peer receive', + seekPermission: false, + } as any, + ORIGINATOR + ); + + // Verify provenance on receive. This peer path internalizes directly + // (bypassing BSV21Registration), so it needs its own hook. Fire-and-forget. + try { + const beef = Beef.fromBinary(settlement.transaction); + const txid = (beef as any).atomicTxid as string | undefined + ?? (beef as any).txs?.[(beef as any).txs.length - 1]?.txid; + if (txid) { + verifyAndPersistOnReceive(this.deps.identityKey, this.chain, { + txid, + vout: settlement.outputIndex, + protocol: 'bsv-21', + }); + } + } catch { /* best-effort — the Assets load-time pass is the backstop */ } + + return { action: 'accept', receiptData: { internalizeResult } }; + } catch (err) { + return { action: 'terminate', termination: { code: 'bsv21.internalize_failed', message: errMsg(err) } }; + } + } +} diff --git a/src/lib/services/tokens/peer/DstasTokenSettlementAdapter.ts b/src/lib/services/tokens/peer/DstasTokenSettlementAdapter.ts new file mode 100644 index 0000000..741710c --- /dev/null +++ b/src/lib/services/tokens/peer/DstasTokenSettlementAdapter.ts @@ -0,0 +1,225 @@ +/** + * DstasTokenSettlementAdapter — concrete TokenSettlementAdapter for DSTAS. + * + * The DSTAS analog of StasTokenSettlementAdapter. DSTAS shares classic STAS's + * BRC-42 receive namespace (STAS_PROTOCOL_ID), so the BRC-29 owner derivation + * is identical; only the transfer builder (DstasTransferService, custom DSTAS + * witness) and the destination basket differ. + * + * - buildTokenSettlement derives the recipient's owner key BRC-29-style and + * reuses DstasTransferService.transfer (full-value 1-to-1, spending-type 1), + * then packages the signed tx as AtomicBEEF. + * - acceptTokenSettlement internalizes the recipient output into the DSTAS + * basket, recording the BRC-29 derivation so the token stays re-spendable. + * + * Interface mirrored locally (see ./tokenSettlementTypes) until + * @bsv/message-box-client publishes it. + */ +import type { WalletInterface } from '@bsv/sdk'; +import { Hash, Utils, createNonce, Beef } from '@bsv/sdk'; +import { DstasTransferService } from '../dstas/DstasTransferService'; +import { StasKeyDeriver } from '../../stas/StasKeyDeriver'; +import { buildChainedAtomicBeef } from '../../stas/buildChainedAtomicBeef'; +import { StasRegistration } from '../../stas/StasRegistration'; +import { parseDstasLockingScript } from '../../stas/dstasParser'; +import { encodeBrc29KeyId } from './brc29KeyId'; +import { STAS_PROTOCOL_ID } from '../../stas/constants'; +import { DSTAS_BASKET } from '../../../constants/baskets'; +import type { + TokenSettlementAdapter, TokenSourceRef, TokenSettlementArtifact, + TokenAdapterContext, TokenBuildResult, TokenAcceptResult, +} from './tokenSettlementTypes'; + +const ORIGINATOR = 'admin.dstas-peer'; + +function errMsg(err: unknown): string { + return err instanceof Error ? err.message : String(err); +} + +export class DstasTokenSettlementAdapter implements TokenSettlementAdapter { + readonly protocol = 'dstas'; + + constructor( + private readonly wallet: WalletInterface, + private readonly identityKey: string, + private readonly chain: 'main' | 'test' + ) {} + + /** BRC-29-style derivation (shared STAS namespace) so the recipient can reconstruct the key. */ + private async deriveRecipientAddress( + recipient: string, + derivationPrefix: string, + derivationSuffix: string + ): Promise { + const { publicKey } = await this.wallet.getPublicKey( + { + protocolID: STAS_PROTOCOL_ID as any, + keyID: `${derivationPrefix} ${derivationSuffix}`, + counterparty: recipient as any, + }, + ORIGINATOR + ); + const pkh = Hash.hash160(Utils.toArray(publicKey, 'hex')); + const versionByte = this.chain === 'main' ? 0x00 : 0x6f; + return Utils.toBase58Check(pkh, [versionByte]); + } + + async buildTokenSettlement( + args: { recipient: string; source: TokenSourceRef; amount: string }, + ctx: TokenAdapterContext + ): Promise { + const { recipient, source, amount } = args; + + // DSTAS is satoshi-denominated; a partial send SPLITS (recipient + sender + // token-change), like STAS. + const sendAmt = Number(amount); + if (!Number.isInteger(sendAmt) || sendAmt < 1 || sendAmt > source.satoshis) { + return { + action: 'terminate', + termination: { code: 'dstas.bad_amount', message: `amount must be an integer between 1 and ${source.satoshis} (got ${amount})` }, + }; + } + const isPartial = sendAmt < source.satoshis; + + try { + const derivationPrefix = await createNonce(this.wallet, 'self', ctx.originator); + const derivationSuffix = await createNonce(this.wallet, 'self', ctx.originator); + const recipientAddress = await this.deriveRecipientAddress(recipient, derivationPrefix, derivationSuffix); + + // Dry run: prove derivation + validation only — never touch the chain. + if (ctx.dryRun) { + ctx.logger?.log(`[dstas dry-run] would transfer ${amount}${isPartial ? ` (split, change ${source.satoshis - sendAmt})` : ''} to ${recipientAddress}`); + return { + action: 'settle', + artifact: { + customInstructions: { derivationPrefix, derivationSuffix }, + transaction: [], + protocol: 'dstas', + assetId: source.assetId, + amount, + outputIndex: 0, + }, + }; + } + + // Partial: derive a self-owned receive key (DSTAS shares the STAS + // namespace) for the token change. + let senderChange: { ownerFieldHash160: string; keyId: string } | undefined; + if (isPartial) { + const ctxRow = await new StasKeyDeriver(this.wallet, this.identityKey, this.chain).createNextReceiveContext(); + senderChange = { ownerFieldHash160: ctxRow.ownerFieldHash160, keyId: ctxRow.keyId }; + } + + const transfer = new DstasTransferService(this.wallet, this.identityKey, this.chain); + const res = await transfer.transfer({ + source: { + txid: source.txid, + vout: source.outputIndex, + scriptHex: source.lockingScriptHex, + satoshis: source.satoshis, + brc42KeyId: source.brc42KeyId ?? 'recv 0', + owner: source.owner, + }, + recipientAddress, + amount: sendAmt, + senderChangeHash160: senderChange?.ownerFieldHash160, + senderChangeKeyId: senderChange?.keyId, + tokenId: source.assetId, + }); + if (!res.ok || res.txid == null) { + return { action: 'terminate', termination: { code: 'dstas.transfer_failed', message: res.reason ?? 'transfer failed' } }; + } + + // Register the sender's token-change DSTAS output (vout 1) — basket was + // declared at createAction, so only link the satellite tables. + if (isPartial && senderChange) { + try { + const parsedChange = parseDstasLockingScript(source.lockingScriptHex); + const r = await new StasRegistration(this.wallet, this.identityKey, this.chain).register({ + txid: res.txid, + vout: 1, + tokenSatoshis: source.satoshis - sendAmt, + ownerFieldHash160: senderChange.ownerFieldHash160, + brc42KeyId: senderChange.keyId, + parsed: { ...(parsedChange ?? {}), ownerFieldHash160: senderChange.ownerFieldHash160, tokenId: source.assetId } as any, + protocol: { id: 'dstas', basketName: DSTAS_BASKET }, + skipInternalize: true, + }); + if (r.registered || r.reason === 'already registered') { + ctx.logger?.log?.(`[dstas] registered sender token-change (vout 1, ${source.satoshis - sendAmt})`); + } else { + ctx.logger?.warn?.(`[dstas] sender token-change NOT registered: ${r.reason}`); + } + } catch (e) { + ctx.logger?.warn?.(`[dstas] sender token-change registration failed (scan will recover): ${String(e)}`); + } + } + + const transaction = (res.beef && res.beef.length > 0) + ? res.beef + : (await buildChainedAtomicBeef({ wallet: this.wallet, txid: res.txid })).atomicBeef; + + return { + action: 'settle', + artifact: { + customInstructions: { derivationPrefix, derivationSuffix }, + transaction, + protocol: 'dstas', + assetId: source.assetId, + amount, + outputIndex: 0, // DSTAS transfer places the recipient output at vout 0 + txid: res.txid, + }, + }; + } catch (err) { + return { action: 'terminate', termination: { code: 'dstas.build_error', message: errMsg(err) } }; + } + } + + async acceptTokenSettlement( + args: { sender: string; settlement: TokenSettlementArtifact }, + _ctx: TokenAdapterContext + ): Promise { + const { sender, settlement } = args; + try { + // Recover the received output from the delivered AtomicBEEF and register + // it into the satellite tables (like discovery) so it shows in Assets; + // DSTAS holdings are read from the satellite tables, not the raw basket. + const beef = Beef.fromBinary(settlement.transaction); + const txid = (beef as any).atomicTxid as string | undefined + ?? (beef as any).txs?.[(beef as any).txs.length - 1]?.txid; + if (txid == null) throw new Error('delivered BEEF has no atomic txid'); + const btx = beef.findTxid(txid); + if (btx?.tx == null) throw new Error(`delivered BEEF missing tx ${txid}`); + const out = btx.tx.outputs[settlement.outputIndex]; + if (out == null) throw new Error(`tx ${txid} has no output ${settlement.outputIndex}`); + const parsed = parseDstasLockingScript(out.lockingScript.toHex()); + if (parsed == null) throw new Error('received output is not DSTAS'); + + const brc42KeyId = encodeBrc29KeyId({ + derivationPrefix: settlement.customInstructions.derivationPrefix, + derivationSuffix: settlement.customInstructions.derivationSuffix, + senderIdentityKey: sender, + }); + + const reg = new StasRegistration(this.wallet, this.identityKey, this.chain); + const result = await reg.register({ + txid, + vout: settlement.outputIndex, + tokenSatoshis: out.satoshis ?? Number(settlement.amount), + ownerFieldHash160: parsed.ownerFieldHash160, + brc42KeyId, + parsed: { ...parsed, tokenId: parsed.tokenId || settlement.assetId } as any, + protocol: { id: 'dstas', basketName: DSTAS_BASKET }, + atomicBeef: settlement.transaction, + }); + if (!result.registered && result.reason !== 'already registered') { + return { action: 'terminate', termination: { code: 'dstas.register_failed', message: result.reason ?? 'register failed' } }; + } + + return { action: 'accept', receiptData: { internalizeResult: result } }; + } catch (err) { + return { action: 'terminate', termination: { code: 'dstas.internalize_failed', message: errMsg(err) } }; + } + } +} diff --git a/src/lib/services/tokens/peer/StasTokenSettlementAdapter.ts b/src/lib/services/tokens/peer/StasTokenSettlementAdapter.ts new file mode 100644 index 0000000..7d798e6 --- /dev/null +++ b/src/lib/services/tokens/peer/StasTokenSettlementAdapter.ts @@ -0,0 +1,263 @@ +/** + * StasTokenSettlementAdapter — concrete TokenSettlementAdapter for classic STAS. + * + * Plugs into `PeerTokenClient` (from @bsv/message-box-client) to move classic + * STAS tokens peer-to-peer over MessageBox, the token analog of PeerPay's + * BRC-29 settlement. It composes the wallet's existing building blocks: + * - owner-field derivation (BRC-29 style, so the recipient can reconstruct + * the key) via wallet.getPublicKey; + * - StasTransferService.transfer to build + sign + broadcast the transfer; + * - buildChainedAtomicBeef to package the signed tx for the recipient; + * - wallet.internalizeAction (basket insertion) on accept, recording the + * BRC-29 derivation so the received token stays re-spendable. + * + * The TokenSettlementAdapter interface is mirrored locally until + * @bsv/message-box-client publishes it; the shape is structurally identical, so + * this class is assignable to the published interface after the version bump. + */ +import type { WalletInterface } from '@bsv/sdk'; +import { Hash, Utils, createNonce, Beef } from '@bsv/sdk'; +import { StasTransferService } from '../../stas/StasTransferService'; +import { StasKeyDeriver } from '../../stas/StasKeyDeriver'; +import { buildChainedAtomicBeef } from '../../stas/buildChainedAtomicBeef'; +import { StasRegistration } from '../../stas/StasRegistration'; +import { parseClassicStasMetadata } from '../../stas/parseClassicStasMetadata'; +import { encodeBrc29KeyId } from './brc29KeyId'; +import { STAS_PROTOCOL_ID } from '../../stas/constants'; +import { STAS_BASKET } from '../../../constants/baskets'; +import type { + TokenSettlementAdapter, TokenSourceRef, TokenSettlementArtifact, + TokenAdapterContext, TokenBuildResult, TokenAcceptResult, +} from './tokenSettlementTypes'; + +const ORIGINATOR = 'admin.stas-peer'; + +function errMsg(err: unknown): string { + return err instanceof Error ? err.message : String(err); +} + +export class StasTokenSettlementAdapter implements TokenSettlementAdapter { + readonly protocol = 'stas'; + + constructor( + private readonly wallet: WalletInterface, + private readonly identityKey: string, + private readonly chain: 'main' | 'test' + ) {} + + /** + * Derives the recipient's STAS owner key with a BRC-29-style shared + * derivation: the recipient can reconstruct the matching private key by + * deriving with `counterparty = senderIdentityKey` and the same keyID. + */ + private async deriveRecipientAddress( + recipient: string, + derivationPrefix: string, + derivationSuffix: string + ): Promise { + const { publicKey } = await this.wallet.getPublicKey( + { + protocolID: STAS_PROTOCOL_ID as any, + keyID: `${derivationPrefix} ${derivationSuffix}`, + counterparty: recipient as any, + }, + ORIGINATOR + ); + const pkh = Hash.hash160(Utils.toArray(publicKey, 'hex')); + const versionByte = this.chain === 'main' ? 0x00 : 0x6f; + return Utils.toBase58Check(pkh, [versionByte]); + } + + async buildTokenSettlement( + args: { recipient: string; source: TokenSourceRef; amount: string }, + ctx: TokenAdapterContext + ): Promise { + const { recipient, source, amount } = args; + + // Classic STAS is satoshi-denominated; the send amount must be a positive + // integer ≤ the UTXO value. A partial send SPLITS: recipient gets `amount`, + // the remainder returns to the sender as token change. + const sendAmt = Number(amount); + if (!Number.isInteger(sendAmt) || sendAmt < 1 || sendAmt > source.satoshis) { + return { + action: 'terminate', + termination: { code: 'stas.bad_amount', message: `amount must be an integer between 1 and ${source.satoshis} (got ${amount})` }, + }; + } + const isPartial = sendAmt < source.satoshis; + + try { + const derivationPrefix = await createNonce(this.wallet, 'self', ctx.originator); + const derivationSuffix = await createNonce(this.wallet, 'self', ctx.originator); + const recipientAddress = await this.deriveRecipientAddress(recipient, derivationPrefix, derivationSuffix); + + // Dry run: prove derivation + validation only — never touch the chain. + if (ctx.dryRun) { + ctx.logger?.log(`[stas dry-run] would transfer ${amount}${isPartial ? ` (split, change ${source.satoshis - sendAmt})` : ''} to ${recipientAddress}`); + return { + action: 'settle', + artifact: { + customInstructions: { derivationPrefix, derivationSuffix }, + transaction: [], + protocol: 'stas', + assetId: source.assetId, + amount, + outputIndex: 0, + }, + }; + } + + // For a partial send, derive a self-owned STAS receive key for the token + // change so the sender keeps (and can see/re-spend) the remainder. + let senderChange: { ownerFieldHash160: string; keyId: string } | undefined; + if (isPartial) { + const ctxRow = await new StasKeyDeriver(this.wallet, this.identityKey, this.chain).createNextReceiveContext(); + senderChange = { ownerFieldHash160: ctxRow.ownerFieldHash160, keyId: ctxRow.keyId }; + } + + const transfer = new StasTransferService(this.wallet, this.identityKey, this.chain); + const res = await transfer.transfer({ + source: { + txid: source.txid, + vout: source.outputIndex, + scriptHex: source.lockingScriptHex, + satoshis: source.satoshis, + brc42KeyId: source.brc42KeyId ?? 'recv 0', + owner: source.owner, + }, + recipientAddress, + amount: sendAmt, + senderChangeHash160: senderChange?.ownerFieldHash160, + senderChangeKeyId: senderChange?.keyId, + tokenId: source.assetId, + }); + if (!res.ok || res.txid == null) { + return { action: 'terminate', termination: { code: 'stas.transfer_failed', message: res.reason ?? 'transfer failed' } }; + } + + // Register the sender's token-change output (vout 1) into the satellite + // tables so the remaining balance shows immediately. Best-effort: the + // discovery scan would also find it. The change is self-owned, so it + // registers with the normal recv key (no BRC-29 override). + if (isPartial && senderChange) { + try { + const meta = parseClassicStasMetadata(source.lockingScriptHex); + await new StasRegistration(this.wallet, this.identityKey, this.chain).register({ + txid: res.txid, + vout: 1, + tokenSatoshis: source.satoshis - sendAmt, + ownerFieldHash160: senderChange.ownerFieldHash160, + brc42KeyId: senderChange.keyId, + parsed: { + tokenId: source.assetId, + ownerFieldHash160: senderChange.ownerFieldHash160, + symbol: meta?.symbol ?? undefined, + flagsHex: meta?.flagsHex ?? '', + serviceFields: [], optionalData: [], + freezeEnabled: false, confiscationEnabled: false, frozen: false, actionData: {}, + } as any, + protocol: { id: 'stas', basketName: STAS_BASKET }, + // The change output's basket was declared at createAction time, so + // its wallet output row already exists — only link the satellite + // tables (internalizing our own output again would conflict). + skipInternalize: true, + }).then((r) => { + if (r.registered || r.reason === 'already registered') { + ctx.logger?.log?.(`[stas] registered sender token-change (vout 1, ${source.satoshis - sendAmt})`); + } else { + ctx.logger?.warn?.(`[stas] sender token-change NOT registered: ${r.reason}`); + } + }); + } catch (e) { + ctx.logger?.warn?.(`[stas] sender token-change registration failed (scan will recover): ${String(e)}`); + } + } + + // Prefer the signed AtomicBEEF the wallet already returned (no re-fetch + // race); fall back to assembling a chained BEEF if it wasn't surfaced. + const transaction = (res.beef && res.beef.length > 0) + ? res.beef + : (await buildChainedAtomicBeef({ wallet: this.wallet, txid: res.txid })).atomicBeef; + + return { + action: 'settle', + artifact: { + customInstructions: { derivationPrefix, derivationSuffix }, + transaction, + protocol: 'stas', + assetId: source.assetId, + amount, + outputIndex: 0, // STAS engine places the recipient output at vout 0 + txid: res.txid, + }, + }; + } catch (err) { + return { action: 'terminate', termination: { code: 'stas.build_error', message: errMsg(err) } }; + } + } + + async acceptTokenSettlement( + args: { sender: string; settlement: TokenSettlementArtifact }, + _ctx: TokenAdapterContext + ): Promise { + const { sender, settlement } = args; + try { + // 1. Recover the received output (txid, vout, script) from the delivered + // AtomicBEEF so we can register it exactly like discovery does — which + // is what makes it show up in the Assets view (STAS holdings are read + // from the satellite tables, not the raw basket). + const beef = Beef.fromBinary(settlement.transaction); + const txid = (beef as any).atomicTxid as string | undefined + ?? (beef as any).txs?.[(beef as any).txs.length - 1]?.txid; + if (txid == null) throw new Error('delivered BEEF has no atomic txid'); + const btx = beef.findTxid(txid); + if (btx?.tx == null) throw new Error(`delivered BEEF missing tx ${txid}`); + const out = btx.tx.outputs[settlement.outputIndex]; + if (out == null) throw new Error(`tx ${txid} has no output ${settlement.outputIndex}`); + const scriptHex = out.lockingScript.toHex(); + const meta = parseClassicStasMetadata(scriptHex); + if (meta == null) throw new Error('received output is not classic STAS'); + + // 2. Pack the BRC-29 owner derivation into the brc42KeyId field so the + // received token is re-spendable (keyID " ", + // counterparty = sender). The holdings loader decodes this back. + const brc42KeyId = encodeBrc29KeyId({ + derivationPrefix: settlement.customInstructions.derivationPrefix, + derivationSuffix: settlement.customInstructions.derivationSuffix, + senderIdentityKey: sender, + }); + + // 3. Register via the same path discovery uses — internalize (with the + // delivered BEEF, no re-fetch) + satellite-table linkage + spendable. + const reg = new StasRegistration(this.wallet, this.identityKey, this.chain); + const result = await reg.register({ + txid, + vout: settlement.outputIndex, + tokenSatoshis: out.satoshis ?? Number(settlement.amount), + ownerFieldHash160: meta.ownerFieldHash160, + brc42KeyId, + parsed: { + tokenId: settlement.assetId, + ownerFieldHash160: meta.ownerFieldHash160, + symbol: meta.symbol ?? undefined, + flagsHex: meta.flagsHex ?? '', + serviceFields: [], + optionalData: [], + freezeEnabled: false, + confiscationEnabled: false, + frozen: false, + actionData: {}, + } as any, + protocol: { id: 'stas', basketName: STAS_BASKET }, + atomicBeef: settlement.transaction, + }); + if (!result.registered && result.reason !== 'already registered') { + return { action: 'terminate', termination: { code: 'stas.register_failed', message: result.reason ?? 'register failed' } }; + } + + return { action: 'accept', receiptData: { internalizeResult: result } }; + } catch (err) { + return { action: 'terminate', termination: { code: 'stas.internalize_failed', message: errMsg(err) } }; + } + } +} diff --git a/src/lib/services/tokens/peer/brc29KeyId.ts b/src/lib/services/tokens/peer/brc29KeyId.ts new file mode 100644 index 0000000..28f8cf7 --- /dev/null +++ b/src/lib/services/tokens/peer/brc29KeyId.ts @@ -0,0 +1,39 @@ +/** + * Encoding for a peer-received token's owner derivation, stored in the + * `brc42KeyId` satellite column. + * + * A normally-discovered STAS UTXO is owned by a self-derived receive key, so + * `brc42KeyId` is just `"recv N"` (signed with counterparty 'self'). A token + * received over MessageBox (BRC-29) is instead owned by a key derived with + * keyID = " " and counterparty = senderIdentityKey. We pack + * those three values into the same `brc42KeyId` string so the holdings loader + * can recover the owner derivation and the transfer service can re-spend it + * via its `owner` override. + * + * Format: `brc29|||` + * (prefix/suffix are base64 nonces, which never contain '|'). + */ +export interface Brc29Owner { + derivationPrefix: string; + derivationSuffix: string; + senderIdentityKey: string; +} + +const PREFIX = 'brc29|'; + +export function encodeBrc29KeyId(o: Brc29Owner): string { + return `${PREFIX}${o.derivationPrefix}|${o.derivationSuffix}|${o.senderIdentityKey}`; +} + +export function isBrc29KeyId(brc42KeyId: string | undefined | null): boolean { + return typeof brc42KeyId === 'string' && brc42KeyId.startsWith(PREFIX); +} + +export function decodeBrc29KeyId(brc42KeyId: string): Brc29Owner | null { + if (!isBrc29KeyId(brc42KeyId)) return null; + const parts = brc42KeyId.slice(PREFIX.length).split('|'); + if (parts.length !== 3) return null; + const [derivationPrefix, derivationSuffix, senderIdentityKey] = parts; + if (!derivationPrefix || !derivationSuffix || !senderIdentityKey) return null; + return { derivationPrefix, derivationSuffix, senderIdentityKey }; +} diff --git a/src/lib/services/tokens/peer/loadPeerHoldings.ts b/src/lib/services/tokens/peer/loadPeerHoldings.ts new file mode 100644 index 0000000..4861211 --- /dev/null +++ b/src/lib/services/tokens/peer/loadPeerHoldings.ts @@ -0,0 +1,142 @@ +/** + * loadPeerHoldings — resolve the wallet's spendable token holdings into + * `TokenSourceRef`s, shared by the in-wallet Peer Tokens page and the + * `/peerToken/holdings` + `/peerToken/send` HTTP routes. + * + * This is the single source of truth for turning on-chain UTXOs into the + * `source` object the adapters need (including the BRC-29 owner override that + * makes a peer-received token re-spendable). Keeping it React-free lets the + * renderer's HTTP bridge (onWalletReady) resolve a holding from just its + * outpoint — the web page never has to understand key derivation. + * + * - STAS / DSTAS: read from the satellite tables via the `listStasOutputs` + * IPC query; the BRC-29 derivation is decoded from the `brc42KeyId` field. + * - BSV-21: read from the BSV-21 basket via wallet.listOutputs; the BRC-29 + * derivation is decoded from customInstructions (scheme:'brc29'). + */ +import type { WalletInterface } from '@bsv/sdk'; +import { stasQuery } from '../../stas/stasIpc'; +import { BSV21_BASKET } from '../../../constants/baskets'; +import { parseBsv21LockingScript } from './../bsv21/inscription'; +import { decodeBrc29KeyId } from './brc29KeyId'; +import type { TokenSourceRef } from './tokenSettlementTypes'; + +export type ProtocolId = 'stas' | 'dstas' | 'bsv-21'; + +export interface PeerHolding { + /** Outpoint `txid.vout` — stable id used to re-resolve the source server-side. */ + key: string; + protocol: ProtocolId; + /** Human label, e.g. `STAS · 100 (received)`. */ + label: string; + /** Token units as a string (STAS/DSTAS = satoshis; BSV-21 = raw amt). */ + amount: string; + source: TokenSourceRef; +} + +function tagValue(tags: string[] | undefined, key: string): string | undefined { + const hit = (tags ?? []).find((t) => t.startsWith(`${key}:`)); + return hit ? hit.slice(key.length + 1) : undefined; +} + +export interface LoadPeerHoldingsArgs { + wallet: WalletInterface; + identityKey: string; + chain: 'main' | 'test'; + originator?: string; +} + +export async function loadPeerHoldings(args: LoadPeerHoldingsArgs): Promise { + const { wallet, identityKey, chain, originator } = args; + const next: PeerHolding[] = []; + + // STAS + DSTAS via the satellite-table IPC query. + try { + const rows: any[] = (await stasQuery(identityKey, chain, 'listStasOutputs', [])) ?? []; + for (const o of rows) { + if (o?.spendable === false) continue; + const protocol: ProtocolId = (o.protocol as ProtocolId) ?? 'stas'; + if (protocol !== 'stas' && protocol !== 'dstas') continue; + const sats = Number(o.outputSatoshis ?? o.tokenSatoshis ?? 0); + const scriptHex = o.lockingScript ?? null; + if (!scriptHex) continue; + // A peer-received token stores its BRC-29 owner derivation in the + // brc42KeyId field; decode it into an explicit owner override so the + // transfer service can re-spend it (counterparty = original sender). + const brc29 = decodeBrc29KeyId(o.brc42KeyId ?? ''); + next.push({ + key: `${o.txid}.${o.vout}`, + protocol, + label: `${o.symbol ?? protocol.toUpperCase()} · ${sats}${brc29 ? ' (received)' : ''}`, + amount: String(sats), + source: { + txid: o.txid, + outputIndex: Number(o.vout), + lockingScriptHex: scriptHex, + satoshis: sats, + protocol, + assetId: o.symbol ?? o.tokenId ?? protocol, + brc42KeyId: o.brc42KeyId ?? undefined, + owner: brc29 + ? { keyID: `${brc29.derivationPrefix} ${brc29.derivationSuffix}`, counterparty: brc29.senderIdentityKey, forSelf: true } + : undefined, + }, + }); + } + } catch (e) { + console.warn('[loadPeerHoldings] listStasOutputs failed', e); + } + + // BSV-21 via listOutputs on the basket. + try { + const res: any = await wallet.listOutputs({ + basket: BSV21_BASKET, + includeTags: true, + includeCustomInstructions: true, + include: 'locking scripts', + limit: 200, + }, originator); + for (const o of res?.outputs ?? []) { + const [txid, voutStr] = String(o.outpoint ?? '.').split('.'); + const scriptHex = o.lockingScript ?? null; + if (!scriptHex) continue; + const parsed = parseBsv21LockingScript(scriptHex); + const tokenId = tagValue(o.tags, 'id') ?? parsed?.id ?? ''; + const amt = tagValue(o.tags, 'amt') ?? parsed?.amt ?? '0'; + const sym = tagValue(o.tags, 'sym') ?? parsed?.sym; + let ci: any = {}; + try { ci = o.customInstructions ? JSON.parse(o.customInstructions) : {}; } catch { /* */ } + // A peer-received BSV-21 stores its BRC-29 owner derivation in + // customInstructions (scheme:'brc29'); decode it into an owner override + // (counterparty = sender, forSelf:true) so it's re-spendable. + const bsv21Brc29 = ci?.scheme === 'brc29' && ci.derivationPrefix && ci.senderIdentityKey + ? { keyID: `${ci.derivationPrefix} ${ci.derivationSuffix}`, counterparty: ci.senderIdentityKey as string, forSelf: true } + : undefined; + next.push({ + key: `${txid}.${voutStr}`, + protocol: 'bsv-21', + label: `${sym ?? 'BSV-21'} · ${amt}${bsv21Brc29 ? ' (received)' : ''}`, + amount: String(amt), + source: { + txid, + outputIndex: Number(voutStr), + lockingScriptHex: scriptHex, + satoshis: Number(o.satoshis ?? 1), + protocol: 'bsv-21', + assetId: tokenId, + brc42KeyId: ci.keyID ?? ci.brc42KeyId ?? undefined, + owner: bsv21Brc29, + tokenId, + amt, + dec: tagValue(o.tags, 'dec') ? Number(tagValue(o.tags, 'dec')) : parsed?.dec, + sym, + icon: tagValue(o.tags, 'icon') ?? parsed?.icon, + }, + }); + } + } catch (e) { + console.warn('[loadPeerHoldings] listOutputs(bsv-21) failed', e); + } + + return next; +} diff --git a/src/lib/services/tokens/peer/tokenSettlementTypes.ts b/src/lib/services/tokens/peer/tokenSettlementTypes.ts new file mode 100644 index 0000000..8c7e624 --- /dev/null +++ b/src/lib/services/tokens/peer/tokenSettlementTypes.ts @@ -0,0 +1,40 @@ +/** + * The TokenSettlementAdapter contract now ships in @bsv/message-box-client + * (>=2.1), so this file no longer mirrors it — it re-exports the published + * types and adds the one field bsv-desktop needs that upstream leaves to the + * adapter's discretion. + * + * Upstream's `TokenSourceRef` carries an index signature (`[key: string]: + * unknown`) for exactly this: standard-specific extras it passes through to the + * adapter without interpreting. We use it for `owner` — the BRC-29 derivation + * override under which a *received* token is held. Typing it here keeps the + * adapters type-safe instead of casting `unknown` at every read. + */ +import type { TokenSourceRef as UpstreamTokenSourceRef } from '@bsv/message-box-client'; + +export type { + TokenSettlementArtifact, + TokenAdapterContext, + TokenBuildResult, + TokenAcceptResult, + TokenSettlementAdapter, + Termination, +} from '@bsv/message-box-client'; + +/** + * Owner-key derivation for a token the wallet RECEIVED over a peer channel. + * Such a UTXO is locked to our key derived with `counterparty = the original + * sender` (BRC-29), not to our plain self-derived receive key — so re-spending + * it requires replaying that derivation with `forSelf: true`. + */ +export interface TokenOwnerOverride { + protocolID?: [number, string]; + keyID: string; + counterparty: string; + /** True for a BRC-29-received token: derive the recipient's OWN key. */ + forSelf?: boolean; +} + +export interface TokenSourceRef extends UpstreamTokenSourceRef { + owner?: TokenOwnerOverride; +} diff --git a/src/lib/services/tokens/tokenLog.ts b/src/lib/services/tokens/tokenLog.ts new file mode 100644 index 0000000..8f30b7f --- /dev/null +++ b/src/lib/services/tokens/tokenLog.ts @@ -0,0 +1,42 @@ +/** + * tokenLog — one switch for the token services' tracing output. + * + * The STAS/DSTAS/BSV-21 transfer paths were developed against a wall of + * console output: derived pubkeys, script invariants, per-input/per-output tx + * dumps, raw signAction results. That tracing is what makes an unlocking-script + * mismatch findable, so it should stay in the tree — but a tester watching a + * normal send should not have to tell it apart from an actual failure. + * + * So: `debug()` is off unless asked for; `info()` and `warn()` always speak. + * Only outcomes go through the latter two. + * + * Turn tracing on with either: + * localStorage.setItem('tokenDebug', '1') // then reload; per-machine, no rebuild + * VITE_TOKEN_DEBUG=1 // build-time + */ + +function tracingEnabled(): boolean { + try { + if (typeof localStorage !== 'undefined' && localStorage.getItem('tokenDebug') === '1') { + return true; + } + } catch { + /* localStorage unavailable (SSR / worker) — fall through to env */ + } + try { + return (import.meta as any)?.env?.VITE_TOKEN_DEBUG === '1'; + } catch { + return false; + } +} + +export const tokenLog = { + /** Development tracing. Silent unless tokenDebug is on. */ + debug: (...args: unknown[]): void => { + if (tracingEnabled()) console.log(...args); + }, + /** An outcome worth seeing on a normal run (e.g. a broadcast txid). */ + info: (...args: unknown[]): void => console.log(...args), + /** Something actually went wrong, or degraded. Always shown. */ + warn: (...args: unknown[]): void => console.warn(...args), +}; diff --git a/src/lib/services/tokens/verifyOnReceive.ts b/src/lib/services/tokens/verifyOnReceive.ts new file mode 100644 index 0000000..a1f2be8 --- /dev/null +++ b/src/lib/services/tokens/verifyOnReceive.ts @@ -0,0 +1,57 @@ +/** + * verifyAndPersistOnReceive — Back-to-Genesis verification at the moment a token + * is internalized, not on the next Assets load. + * + * The Assets page already verifies holdings when it renders, and persists the + * verdicts (migration 0004). But a token accepted over MessageBox — or picked up + * by a background discovery scan — is internalized whether or not Assets is open. + * Firing verification here, at the registration seam, means the DB already holds + * the Verified / Counterfeit verdict by the time the user looks, so the badge is + * instant and the load-time pass finds it in its DB seed and skips the network. + * + * Fire-and-forget by contract: this returns void immediately and never throws. + * It must not block or fail a receive — a WOC hiccup simply leaves the outpoint + * unverified until the load-time pass retries it. Only SETTLED verdicts are + * written; `undetermined` is left for a retry, never frozen. + */ + +import { BackToGenesisClient, formatGenesisRef, type TokenStd } from './woc/BackToGenesisClient'; +import { stasQuery } from '../stas/stasIpc'; +import type { TokenProtocolId } from './TokenProtocolAdapter'; + +const PROTOCOL_TO_STD: Record = { + stas: 'stas', + dstas: 'dstas', + 'bsv-21': 'bsv21', +}; + +export function verifyAndPersistOnReceive( + identityKey: string, + chain: 'main' | 'test', + outpoint: { txid: string; vout: number; protocol: TokenProtocolId }, + client: BackToGenesisClient = new BackToGenesisClient({ chain }) +): void { + void (async () => { + try { + const std = PROTOCOL_TO_STD[outpoint.protocol]; + const res = await client.verify(std, outpoint.txid, outpoint.vout); + // Leave `undetermined` for the load-time retry — persisting it would freeze + // a "couldn't decide yet" as if it were a decision. + if (res.result === 'undetermined') return; + await stasQuery(identityKey, chain, 'upsertTokenVerification', [ + { + txid: outpoint.txid, + vout: outpoint.vout, + protocol: outpoint.protocol, + result: res.result, + genesis: res.genesis ? formatGenesisRef(res.genesis) : null, + genesisDepth: res.genesisDepth ?? null, + reason: res.reason ?? null, + verifiedAt: new Date().toISOString(), + }, + ]); + } catch { + /* best-effort; the Assets load-time pass verifies + persists as a backstop */ + } + })(); +} diff --git a/src/lib/services/tokens/woc/BackToGenesisClient.ts b/src/lib/services/tokens/woc/BackToGenesisClient.ts new file mode 100644 index 0000000..a8f688c --- /dev/null +++ b/src/lib/services/tokens/woc/BackToGenesisClient.ts @@ -0,0 +1,172 @@ +/** + * BackToGenesisClient — WhatsOnChain token-provenance (Back-to-Genesis) reads. + * + * B2G answers one question about a token output: *does it provably descend from + * its genesis mint, with token conservation preserved at every hop back?* The + * endpoint walks raw transactions from bStore on demand — it does NOT use the + * token index, so it verifies tokens the index hasn't caught up on (confirmed + * against activation-pending BSV-21 that 404 on the UTXO endpoints). + * + * GET /token/{std}/tx/{txid}/out/{index}/verify[?expectedGenesis=_] + * GET /token/{std}/tx/{txid}/out/{index}/trace[?maxDepth=N] + * + * `result` is TRI-STATE and the distinction is load-bearing: + * - `authentic` — provably descends from a genesis, conservation held. + * - `not-authentic` — a provenance rule failed. This is the counterfeit + * verdict (verified adversarially: an output cloning a + * real token's tokenId+symbol but with no valid ancestor + * returns not-authentic / no-genesis). + * - `undetermined` — could NOT be decided (walk deeper than maxDepth, or a + * source tx was unavailable). Fail-SAFE: treat as + * "unknown", NEVER as counterfeit. A real token must never + * be shown fake because a fetch failed. + * + * IDENTITY CAVEAT (see project notes): for classic STAS `assetKey.tokenId` is + * the issuer PKH — every token an issuer ever minted shares it — and the + * response omits `symbol`. So `authentic` proves the token is real, NOT which + * token it is. The only stable identity is the resolved `genesis` outpoint; + * pin trust with `expectedGenesis` and check `matchesExpectedGenesis`. + * + * Every call is fail-soft: a 404 / 5xx / network error yields `undetermined` + * with a synthetic reason, never a throw. Verification degrading to "unknown" + * must never break a receive. + */ + +import { wocFetch } from '../../../utils/RateLimitedFetch'; + +const WOC_BASE = 'https://api.whatsonchain.com/v1/bsv'; + +/** Token standard discriminator, matching the endpoint path segment. */ +export type TokenStd = 'stas' | 'dstas' | 'bsv21'; + +export type B2GResultState = 'authentic' | 'not-authentic' | 'undetermined'; + +/** A `_` genesis reference, or a structured outpoint. */ +export interface B2GOutpoint { + txid: string; + index: number; +} + +export interface B2GVerifyResult { + outpoint: B2GOutpoint; + result: B2GResultState; + /** Present when not `authentic` — e.g. no-genesis, conservation-violation, + * genesis-malformed, not-a-token, source-unavailable, max-depth-exceeded. */ + reason?: string; + /** Standard-specific identity: `tokenId` (STAS/DSTAS) or `id` (BSV-21). */ + assetKey?: { tokenId?: string; id?: string }; + /** The resolved genesis outpoint — the ONLY stable token identity. */ + genesis?: B2GOutpoint; + /** Hops from the queried output back to genesis; 0 = the output IS genesis. */ + genesisDepth?: number; + /** Token amount at the queried output (string — preserves big integers). */ + amount?: string; + conservationOk?: boolean; + /** Only present when `expectedGenesis` was supplied. */ + matchesExpectedGenesis?: boolean; + /** Present on failure — the outpoint where the walk stopped. */ + failedAt?: B2GOutpoint; +} + +export interface B2GTraceHop { + txid: string; + index: number; + amount: string; + op: 'genesis' | 'transfer' | 'split' | 'merge'; + parentOutpoint?: string; +} + +export interface B2GTraceResult { + outpoint: B2GOutpoint; + result: B2GResultState; + reason?: string; + genesis?: B2GOutpoint; + genesisDepth?: number; + path?: B2GTraceHop[]; + maxDepth?: number; + truncated?: boolean; +} + +export interface BackToGenesisOptions { + chain?: 'main' | 'test'; + /** Base URL override (tests). Defaults to `${WOC_BASE}/${chain}`. */ + baseUrl?: string; +} + +/** Format a genesis outpoint as the `expectedGenesis` / `parentOutpoint` wire form. */ +export function formatGenesisRef(g: B2GOutpoint): string { + return `${g.txid}_${g.index}`; +} + +export class BackToGenesisClient { + private readonly base: string; + + constructor(opts: BackToGenesisOptions = {}) { + const chain = opts.chain ?? 'main'; + this.base = (opts.baseUrl ?? `${WOC_BASE}/${chain}`).replace(/\/$/, ''); + } + + /** + * Verify a token output's provenance. Never throws — a transport failure + * returns `undetermined` (fail-safe), so a caller can always branch on + * `result` without a try/catch. + * + * @param expectedGenesis optional `_` to assert the origin; adds + * `matchesExpectedGenesis` to the result. + */ + async verify( + std: TokenStd, + txid: string, + index: number, + opts: { expectedGenesis?: string } = {} + ): Promise { + const qs = opts.expectedGenesis + ? `?expectedGenesis=${encodeURIComponent(opts.expectedGenesis)}` + : ''; + const path = `/token/${std}/tx/${txid}/out/${index}/verify${qs}`; + const json = await this.getJson(path); + if (!json) { + return { + outpoint: { txid, index }, + result: 'undetermined', + reason: 'source-unavailable', + }; + } + return json; + } + + /** + * Trace the full provenance path back to genesis. Same fail-safe contract as + * verify(). `maxDepth` is clamped server-side to 100. + */ + async trace( + std: TokenStd, + txid: string, + index: number, + opts: { maxDepth?: number } = {} + ): Promise { + const qs = opts.maxDepth ? `?maxDepth=${opts.maxDepth}` : ''; + const path = `/token/${std}/tx/${txid}/out/${index}/trace${qs}`; + const json = await this.getJson(path); + if (!json) { + return { + outpoint: { txid, index }, + result: 'undetermined', + reason: 'source-unavailable', + }; + } + return json; + } + + private async getJson(path: string): Promise { + try { + const res = await wocFetch.fetch(`${this.base}${path}`, { + headers: { Accept: 'application/json' }, + }); + if (!res.ok) return null; // 400 (bad std/index) / 404 / 5xx → undetermined + return (await res.json()) as T; + } catch { + return null; + } + } +} diff --git a/src/lib/services/tokens/woc/WocTokenIndexerClient.ts b/src/lib/services/tokens/woc/WocTokenIndexerClient.ts new file mode 100644 index 0000000..02b7b9d --- /dev/null +++ b/src/lib/services/tokens/woc/WocTokenIndexerClient.ts @@ -0,0 +1,209 @@ +/** + * WocTokenIndexerClient — single WhatsOnChain-backed discovery source for all + * three token standards (STAS, DSTAS, BSV-21), replacing the previous + * per-standard indexers (Bitails, the local relay, the 1Sat overlay). + * + * One host, one chain-selected base URL, one shared `wocFetch` rate budget, + * one `?script=true` convention. Only the address format + path template + * differ per standard: + * + * STAS GET /address/{base58}/tokens/unspent (base58 address) + * DSTAS GET /address/{ownerHash160}/tokens/dstas/unspent (raw hash160!) + * BSV-21 GET /token/bsv21/{base58}/unspent (base58 address) + * + * The methods are intentionally DUCK-TYPE COMPATIBLE with the clients they + * replace so the discovery services swap in with a minimal diff: + * - `getUtxosForAddresses` matches `stas/IndexerClient` (STAS), + * - `getOwnedTxos` matches `bsv21/OneSatIndexerClient` (BSV-21), + * - `getDstasUtxosForOwners` is new (DSTAS gained a real indexer). + * + * Every request is fail-soft: a 404 (e.g. WOC's DSTAS endpoint not yet on + * mainnet, or an unactivated BSV-21) or a network error yields `[]`, never a + * throw — discovery degrades to empty rather than breaking. + * + * DSTAS/STAS responses include the full locking `script` with `?script=true` + * (surfaced as `WocUtxo.scriptHex`, letting the STAS scan skip a per-txid + * getRawTx for parsing). BSV-21's unspent response carries only `scriptHash`, + * so the BSV-21 scan still fetches the raw tx to parse the inscription. + */ + +import { wocFetch } from '../../../utils/RateLimitedFetch'; +import type { IndexedOutput } from '../bsv21/OneSatIndexerClient'; + +const WOC_BASE = 'https://api.whatsonchain.com/v1/bsv'; + +/** + * Reports how far a per-address fan-out has got. WOC has no bulk token endpoint, + * so a scan is one throttled request per derived address — tens of seconds for a + * grown wallet. Without this the UI can only show an indeterminate spinner. + */ +export type ScanProgressFn = (done: number, total: number) => void; + +/** A token UTXO as returned by WOC's per-address token endpoints. */ +export interface WocUtxo { + /** Transaction id (hex). */ + txid: string; + /** Output index. */ + vout: number; + /** Satoshis. For STAS/DSTAS this equals the token amount. */ + value: number; + /** Block height. WOC's token endpoints omit it; we pass a mempool-safe sentinel. */ + height: number; + /** Ticker, when the indexer decoded one. */ + symbol?: string; + /** tokenId / issuer PKH hex, when present in the response. */ + redeemAddr?: string; + /** Full locking script hex (`?script=true`) — lets the scan skip a getRawTx. */ + scriptHex?: string; +} + +export interface WocTokenIndexerOptions { + chain?: 'main' | 'test'; + /** Base URL override (tests). Defaults to `${WOC_BASE}/${chain}`. */ + baseUrl?: string; +} + +/** WOC's DSTAS/STAS per-address unspent shape (subset we consume). */ +interface WocTokenUtxo { + txid?: string; + tx_hash?: string; + index?: number; + vout?: number; + tx_pos?: number; + satoshis?: number; + amount?: number; + value?: number; + script?: string; + symbol?: string; + tokenId?: string; + redeemAddr?: string; +} + +export class WocTokenIndexerClient { + private readonly base: string; + + constructor(opts: WocTokenIndexerOptions = {}) { + const chain = opts.chain ?? 'main'; + this.base = (opts.baseUrl ?? `${WOC_BASE}/${chain}`).replace(/\/$/, ''); + } + + private async getJson(path: string): Promise { + try { + const res = await wocFetch.fetch(`${this.base}${path}`, { + headers: { Accept: 'application/json' }, + }); + if (!res.ok) return null; // 404 / 5xx → degrade to empty + return (await res.json()) as T; + } catch { + return null; + } + } + + /** Normalize a WOC STAS/DSTAS token utxo into the shared `WocUtxo` shape. */ + private toWocUtxo(u: WocTokenUtxo): WocUtxo { + return { + txid: (u.txid ?? u.tx_hash ?? '') as string, + vout: (u.index ?? u.vout ?? u.tx_pos ?? 0) as number, + value: (u.satoshis ?? u.amount ?? u.value ?? 0) as number, + height: 1, // sentinel — WOC token endpoints don't return height; mempool OK + symbol: u.symbol, + redeemAddr: u.tokenId ?? u.redeemAddr, + scriptHex: u.script, + }; + } + + /** + * Classic-STAS UTXOs across many base58 addresses. + * Drop-in for `IndexerClient.getUtxosForAddresses` (same return shape). + * WOC has no bulk STAS endpoint, so this fans out per-address through the + * shared rate limiter (same budget the wallet's other WOC polling uses). + */ + async getUtxosForAddresses( + addresses: string[], + opts: { onProgress?: ScanProgressFn } = {} + ): Promise> { + const out: Array<{ address: string; utxos: WocUtxo[] }> = []; + for (const address of addresses) { + opts.onProgress?.(out.length, addresses.length); + const res = await this.getJson<{ utxos?: WocTokenUtxo[] | null }>( + `/address/${encodeURIComponent(address)}/tokens/unspent?script=true` + ); + const utxos = Array.isArray(res?.utxos) ? res!.utxos!.map((u) => this.toWocUtxo(u)) : []; + out.push({ address, utxos }); + } + return out; + } + + /** + * DSTAS UTXOs across many owner HASH160s. NB: WOC's DSTAS address endpoint + * keys on the raw owner hash160, not a base58 address. Returns the same + * `WocUtxo` shape so the STAS discovery loop can consume it uniformly. + */ + async getDstasUtxosForOwners( + ownerHash160s: string[], + opts: { onProgress?: ScanProgressFn } = {} + ): Promise> { + const out: Array<{ ownerHash160: string; utxos: WocUtxo[] }> = []; + for (const ownerHash160 of ownerHash160s) { + opts.onProgress?.(out.length, ownerHash160s.length); + const res = await this.getJson<{ utxos?: WocTokenUtxo[] | null }>( + `/address/${encodeURIComponent(ownerHash160)}/tokens/dstas/unspent?script=true` + ); + const utxos = Array.isArray(res?.utxos) ? res!.utxos!.map((u) => this.toWocUtxo(u)) : []; + out.push({ ownerHash160, utxos }); + } + return out; + } + + /** + * BSV-21 unspent outputs at a single base58 address, mapped to the + * `IndexedOutput` shape so `BSV21DiscoveryService.scan()` consumes it + * unchanged (drop-in for `OneSatIndexerClient.getOwnedTxos`). + * + * WOC returns `{ tokens: [{ outpoint: "_", data:{ bsv20:{id,sym,amt}, + * insc:{json:{dec}} } }] }`. We emit `events:['bsv21']` + `id` so the scan's + * BSV-21 filter admits every row (the endpoint is already BSV-21-only). + */ + async getOwnedTxos(address: string): Promise { + const res = await this.getJson<{ tokens?: WocBsv21Unspent[] | null }>( + `/token/bsv21/${encodeURIComponent(address)}/unspent?script=true` + ); + if (!Array.isArray(res?.tokens)) return []; + return res!.tokens!.map((t) => { + const bsv20 = t.data?.bsv20 ?? {}; + const insc = t.data?.insc?.json ?? {}; + const decStr = insc.dec; + const dec = decStr !== undefined && decStr !== '' ? Number(decStr) : undefined; + return { + outpoint: t.outpoint ?? (t.vout !== undefined && t.current?.txid ? `${t.current.txid}_${t.vout}` : ''), + id: (bsv20.id ?? insc.id ?? t.outpoint) as string | undefined, + amt: bsv20.amt !== undefined ? String(bsv20.amt) : insc.amt, + dec: Number.isFinite(dec as number) ? (dec as number) : undefined, + // WOC names it `symbol` on the decoded `bsv20` object but `sym` inside + // the raw inscription JSON. Transfers carry neither — the parsed + // locking script is the caller's fallback. + sym: bsv20.symbol ?? bsv20.sym ?? insc.sym, + icon: bsv20.icon, + events: ['bsv21'], + } as IndexedOutput; + }); + } +} + +/** WOC's BSV-21 per-address unspent row (subset we consume). */ +interface WocBsv21Unspent { + outpoint?: string; + vout?: number; + current?: { txid?: string }; + data?: { + bsv20?: { + id?: string; + amt?: string | number; + /** WOC's decoded field name. `sym` is the raw-inscription spelling. */ + symbol?: string; + sym?: string; + icon?: string; + }; + insc?: { json?: { id?: string; amt?: string; dec?: string; sym?: string } }; + }; +} diff --git a/src/lib/types/StasTransferRequest.ts b/src/lib/types/StasTransferRequest.ts new file mode 100644 index 0000000..12d5537 --- /dev/null +++ b/src/lib/types/StasTransferRequest.ts @@ -0,0 +1,30 @@ +/** + * Permission request shape for the `/stas/transfer` HTTP route on the + * wallet's Apps API (port 3321). + * + * Each external `POST /stas/transfer` call enqueues one of these. The + * `StasTransferPermissionHandler` modal pops up in the wallet UI showing + * the request, the user clicks Approve or Deny, and the route handler + * resolves with the boolean. Only on `true` does + * `StasTransferService.transfer` actually run. + */ +export interface StasTransferRequest { + /** Internal id used to match approve/deny back to a pending request. */ + requestId: string; + /** Origin of the caller (e.g. `http://localhost:8090`). */ + originator: string; + /** Source UTXO outpoint, `.`. */ + outpoint: string; + /** Token symbol if known (classic STAS extracted it from OP_RETURN). */ + symbol: string | null; + /** Token id (CreateContract txid for classic STAS). */ + tokenId: string | null; + /** Satoshis on the UTXO. */ + satoshis: number; + /** Where the STAS is being sent. */ + recipient: string; + /** BRC-42 key id that owns the source (e.g. `recv 7`). */ + brc42KeyId: string | null; + /** Resolver invoked by the modal when the user clicks Approve / Deny. */ + resolve: (approved: boolean) => void; +} diff --git a/src/lib/utils/RateLimitedFetch.ts b/src/lib/utils/RateLimitedFetch.ts index 1f2d538..4104e2c 100644 --- a/src/lib/utils/RateLimitedFetch.ts +++ b/src/lib/utils/RateLimitedFetch.ts @@ -1,6 +1,22 @@ /** - * Rate-limited fetch queue to prevent overwhelming APIs - * Limits requests to a maximum rate (default: 3 requests per second) + * Rate-limited fetch queue with 429 retry/backoff. + * + * Caps outbound rate AND auto-retries on 429 with capped exponential backoff + * plus jitter. Two failure modes this guards against: + * 1. Discovery scans — a candidate address that's 429'd is silently treated + * as [] by the indexer client, so a real UTXO there is missed entirely. + * 2. Registration — findCreateContractTxid (ancestry walk) and + * buildChainedAtomicBeef (proof chain) fetch rawTx/merkle proofs here as a + * fallback when wallet-toolbox's own (UNTHROTTLED) `services.getRawTx/ + * getMerklePath` 429s. Those unthrottled primary calls are what push total + * WoC traffic over the limit, so the throttled fallback must be persistent + * enough to win — otherwise a freshly-discovered token fails to register + * and needs a manual register-by-txid. + * + * Honours `Retry-After` when present; otherwise backs off 1s, 2s, 4s, 8s, 8s, 8s + * (capped) with ±25% jitter across up to `maxRetries` attempts before surfacing + * the 429. The rate is deliberately below WoC's ceiling to leave headroom for + * wallet-toolbox's concurrent (unthrottled) traffic. */ class RateLimitedFetch { private queue: Array<{ @@ -12,10 +28,12 @@ class RateLimitedFetch { private processing = false private requestsPerSecond: number private minInterval: number + private maxRetries: number - constructor(requestsPerSecond: number = 3) { + constructor(requestsPerSecond: number = 1.5, maxRetries: number = 6) { this.requestsPerSecond = requestsPerSecond this.minInterval = 1000 / requestsPerSecond + this.maxRetries = maxRetries } async fetch(url: string, options?: RequestInit): Promise { @@ -27,6 +45,23 @@ class RateLimitedFetch { }) } + private async fetchWithRetry(url: string, options?: RequestInit): Promise { + for (let attempt = 0; attempt <= this.maxRetries; attempt++) { + const res = await fetch(url, options) + if (res.status !== 429) return res + if (attempt === this.maxRetries) return res + const retryAfter = parseInt(res.headers.get('Retry-After') ?? '', 10) + // Capped exponential (1s,2s,4s,8s,8s,…) + ±25% jitter so concurrent + // retries don't thunder back in lockstep. Retry-After wins when present. + const base = Number.isFinite(retryAfter) && retryAfter > 0 + ? retryAfter * 1000 + : Math.min(8000, 1000 * Math.pow(2, attempt)) + const backoff = base + Math.floor(base * 0.25 * Math.random()) + await new Promise((r) => setTimeout(r, backoff)) + } + return fetch(url, options) + } + private async processQueue() { if (this.queue.length === 0) { this.processing = false @@ -38,13 +73,12 @@ class RateLimitedFetch { const startTime = Date.now() try { - const response = await fetch(item.url, item.options) + const response = await this.fetchWithRetry(item.url, item.options) item.resolve(response) } catch (error) { item.reject(error as Error) } - // Ensure minimum interval between requests const elapsed = Date.now() - startTime const delay = Math.max(0, this.minInterval - elapsed) @@ -54,5 +88,8 @@ class RateLimitedFetch { } } -// Singleton instance for WhatsOnChain API calls -export const wocFetch = new RateLimitedFetch(3) +// Singleton for WhatsOnChain / Bitails API calls. 1.5 req/s leaves headroom +// for wallet-toolbox's own concurrent (unthrottled) WoC traffic, and 429s +// auto-retry with capped backoff across up to 6 attempts so registration +// fetches win under sustained pressure instead of failing to null. +export const wocFetch = new RateLimitedFetch(1.5, 6) diff --git a/src/onWalletReady.ts b/src/onWalletReady.ts index cfa8cf9..6399e8b 100644 --- a/src/onWalletReady.ts +++ b/src/onWalletReady.ts @@ -1,3 +1,5 @@ +import { stasQuery } from './lib/services/stas/stasIpc'; +import { loadPeerHoldings } from './lib/services/tokens/peer/loadPeerHoldings'; import { WalletInterface, CreateActionArgs, @@ -141,6 +143,73 @@ function parseOrigin(headers: Record): string | null { // Module-level wallet ref — survives React effect cleanup/re-runs let _currentWallet: WalletInterface | null = null; +let _currentStasDiscovery: any = null; +/** + * BSV-21 discovery service exposed to `/bsv-21/register-by-txid`. + * + * This is a localhost-only demo fast-path: the dex-shell hands the wallet + * a txid right after a faucet mint and the wallet fetches + parses + + * internalizes the matching output(s) for immediate UI feedback. It + * mirrors `/stas/register-by-txid`. + * + * The PRIMARY discovery mechanism is `BSV21DiscoveryService.scan()`, + * which queries the 1Sat overlay's per-address SSE stream + * (`/1sat/owner/{addr}/txos?unspent=true`). That path covers organic + * receive (third party sends to one of our addresses) provided the + * sender's broadcast routed through any `/1sat/tx`-capable endpoint — + * which the faucet now does automatically per-mint. + */ +let _currentBsv21Discovery: any = null; +/** + * STAS service bundle exposed to the Apps API routes (Task 7a). Set from + * WalletContext via setStasForHttpRoute as soon as the WalletService's + * StasServices snapshot becomes available. + */ +let _currentStasBundle: { + discovery: any; + transfer: any; + keyDeriver: any; + identityKey: string; + chain: 'main' | 'test'; +} | null = null; +/** + * Permission gate for /stas/transfer. Set by WalletContext, called by the + * route handler with the transfer details. Resolves true (approve) or false + * (deny) once the user clicks one of the modal buttons. + */ +type StasTransferPermissionArgs = { + originator: string; + outpoint: string; + symbol: string | null; + tokenId: string | null; + satoshis: number; + recipient: string; + brc42KeyId: string | null; +}; +let _currentStasTransferEnqueuer: + | ((args: StasTransferPermissionArgs) => Promise) + | null = null; +/** + * Peer-token client bundle exposed to the `/peerToken/*` routes (Phase B). + * The standalone web page drives the tester's own wallet through these: + * identity, holdings, send, incoming, accept. `client` is the vendored + * PeerTokenClient; wallet/identityKey/chain/originator let the routes + * re-resolve a holding's full source from just an outpoint. + */ +let _currentPeerTokensBundle: { + client: any; + wallet: WalletInterface; + identityKey: string; + chain: 'main' | 'test'; + originator?: string; + /** + * TokenProtocolRegistry — the SAME adapters the Assets page uses for + * legacy address sends (`tokens.getById(protocol).transfer(...)`). Hung + * off this bundle so the `/dstas/transfer` + `/bsv-21/transfer` routes can + * drive an on-chain, no-MessageBox transfer without touching PeerTokenClient. + */ + tokens?: any; +} | null = null; let _listenerRegistered = false; let _cancelListenerRegistered = false; @@ -151,15 +220,90 @@ export function _test_isListenerRegistered(): boolean { return _listenerRegister /** Test-only: reset module state */ export function _test_reset(): void { _currentWallet = null; + _currentStasDiscovery = null; _listenerRegistered = false; _cancelListenerRegistered = false; } +/** + * Inject (or clear) the STAS discovery service used by the + * `/stas/register-by-txid` HTTP route. Called from WalletContext as soon + * as the wallet's StasServices snapshot becomes available — kept separate + * from `onWalletReady` so the prop interface stays single-arg. + */ +export function setStasDiscoveryForHttpRoute( + discovery: { registerByTxid: (txid: string) => Promise } | null +): void { + _currentStasDiscovery = discovery; +} + +/** + * Inject (or clear) the full STAS service bundle for the Apps API routes + * (`/stas/list`, `/stas/tokens`, `/stas/receive-address`, `/stas/transfer`). + * Includes identityKey + chain so each route can drive stas:query without + * a separate lookup. + */ +export function setStasForHttpRoute( + bundle: { + discovery: any; + transfer: any; + keyDeriver: any; + identityKey: string; + chain: 'main' | 'test'; + } | null +): void { + _currentStasBundle = bundle; + // Backward-compat: the older single-purpose discovery setter remains + // populated for /stas/register-by-txid even if some callers haven't + // upgraded yet. + _currentStasDiscovery = bundle?.discovery ?? null; +} + +/** + * Inject (or clear) the BSV-21 discovery service used by the + * `/bsv-21/register-by-txid` HTTP route. Mirrors `setStasDiscoveryForHttpRoute`. + */ +export function setBsv21DiscoveryForHttpRoute( + discovery: { registerByTxid: (txid: string) => Promise } | null +): void { + _currentBsv21Discovery = discovery; +} + +/** + * Inject (or clear) the permission-prompt enqueuer used by /stas/transfer + * to gate external app calls on user approval. Set by WalletContext. + */ +export function setStasTransferEnqueuer( + fn: ((args: StasTransferPermissionArgs) => Promise) | null +): void { + _currentStasTransferEnqueuer = fn; +} + +/** + * Inject (or clear) the peer-token client bundle used by the `/peerToken/*` + * routes (Phase B standalone web page). Set from WalletContext alongside + * setStasForHttpRoute once the WalletService's StasServices snapshot is ready. + */ +export function setPeerTokensForHttpRoute( + bundle: { + client: any; + wallet: WalletInterface; + identityKey: string; + chain: 'main' | 'test'; + originator?: string; + tokens?: any; + } | null +): void { + _currentPeerTokensBundle = bundle; +} + /** * Update the wallet instance used by the HTTP listener. * First call also registers the IPC listener (once, never removed). */ -export const onWalletReady = async (wallet: WalletInterface): Promise<(() => void) | undefined> => { +export const onWalletReady = async ( + wallet: WalletInterface +): Promise<(() => void) | undefined> => { _currentWallet = wallet; console.log('[onWalletReady] wallet ref updated, listenerRegistered:', _listenerRegistered); @@ -883,6 +1027,738 @@ export const onWalletReady = async (wallet: WalletInterface): Promise<(() => voi break; } + // ===== STAS Apps API (Task 7a) ===== + // Five HTTP routes that wrap the wallet's STAS surface so external + // BRC-100 apps don't have to re-implement the createAction + + // signAction plumbing from §12. Hides: + // - basket fragmentation / spendable flag overrides + // - inputBEEF construction with WoC fallback + // - partialSTASUnlockingScript + signature digest semantics + // - chain-of-state across discovery → transfer + // Apps just call `fetch('http://127.0.0.1:3321/stas/...')`. + + case '/stas/list': { + if (!_currentStasBundle) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ error: 'STAS services not ready' }), + }; + break; + } + try { + const { identityKey, chain } = _currentStasBundle; + const outputs: any[] = + (await stasQuery( + identityKey, + chain, + 'listStasOutputs', + [] + )) ?? []; + const tokens: any[] = + (await stasQuery( + identityKey, + chain, + 'listStasTokens', + [] + )) ?? []; + const tokenMap: Record = {}; + for (const t of tokens) tokenMap[t.tokenId] = t; + const holdings = outputs.map((o: any) => ({ + outpoint: `${o.txid}.${o.vout}`, + txid: o.txid, + vout: o.vout, + satoshis: o.outputSatoshis ?? o.tokenSatoshis, + spendable: !!o.spendable, + tokenId: o.tokenId, + symbol: tokenMap[o.tokenId]?.symbol ?? null, + name: tokenMap[o.tokenId]?.name ?? null, + brc42KeyId: o.brc42KeyId ?? null, + ownerFieldHash160: o.ownerFieldHash160, + frozen: !!o.frozen, + confiscated: !!o.confiscated, + })); + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify({ holdings, total: holdings.length }), + }; + } catch (e) { + response = { + request_id: req.request_id, + status: 500, + body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }), + }; + } + break; + } + + case '/stas/tokens': { + if (!_currentStasBundle) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ error: 'STAS services not ready' }), + }; + break; + } + try { + const { identityKey, chain } = _currentStasBundle; + const tokens: any[] = + (await stasQuery( + identityKey, + chain, + 'listStasTokens', + [] + )) ?? []; + const outputs: any[] = + (await stasQuery( + identityKey, + chain, + 'listStasOutputs', + [] + )) ?? []; + // Aggregate counts + totalSatoshis per tokenId + const byToken: Record = {}; + for (const o of outputs) { + const tid = o.tokenId; + if (!tid) continue; + const stat = (byToken[tid] = byToken[tid] ?? { count: 0, total: 0 }); + stat.count += 1; + stat.total += o.outputSatoshis ?? o.tokenSatoshis ?? 0; + } + const enhanced = tokens.map((t: any) => ({ + tokenId: t.tokenId, + symbol: t.symbol, + name: t.name ?? null, + satoshisPerToken: t.satoshisPerToken, + freezeEnabled: !!t.freezeEnabled, + confiscationEnabled: !!t.confiscationEnabled, + redemptionPkh: t.redemptionPkh ?? null, + issuerIdentityKey: t.issuerIdentityKey ?? null, + outputCount: byToken[t.tokenId]?.count ?? 0, + totalSatoshis: byToken[t.tokenId]?.total ?? 0, + })); + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify({ tokens: enhanced }), + }; + } catch (e) { + response = { + request_id: req.request_id, + status: 500, + body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }), + }; + } + break; + } + + case '/stas/receive-address': { + if (!_currentStasBundle?.keyDeriver) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ error: 'STAS services not ready' }), + }; + break; + } + try { + const { keyDeriver } = _currentStasBundle; + const row = await keyDeriver.createNextReceiveContext(); + // hash160 → base58 P2PKH address. We import dxs-bsv-token-sdk's + // Address inline so the route handler doesn't drag the dep into + // the top-level import block. + const dxs = await import('dxs-bsv-token-sdk/bsv'); + const base58 = new (dxs as any).Address( + (dxs as any).fromHex(row.ownerFieldHash160) + ).Value as string; + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify({ + address: base58, + ownerFieldHash160: row.ownerFieldHash160, + brc42KeyId: row.keyId, + keyIndex: row.keyIndex, + }), + }; + } catch (e) { + response = { + request_id: req.request_id, + status: 500, + body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }), + }; + } + break; + } + + case '/stas/transfer': { + if (!_currentStasBundle?.transfer) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ error: 'STAS services not ready' }), + }; + break; + } + try { + const { transfer, identityKey, chain } = _currentStasBundle; + const parsed = (req.body ? JSON.parse(req.body) : {}) as { + outpoint?: string; + recipientAddress?: string; + }; + const outpoint = parsed.outpoint; + const recipientAddress = parsed.recipientAddress; + if (!outpoint || !recipientAddress) { + response = { + request_id: req.request_id, + status: 400, + body: JSON.stringify({ + error: 'outpoint and recipientAddress are required', + }), + }; + break; + } + const [txid, voutStr] = outpoint.split('.'); + const vout = parseInt(voutStr, 10); + if (!/^[0-9a-f]{64}$/i.test(txid) || !Number.isInteger(vout) || vout < 0) { + response = { + request_id: req.request_id, + status: 400, + body: JSON.stringify({ error: 'outpoint must be "."' }), + }; + break; + } + // Look up the source's metadata from our satellite table. + const allOutputs: any[] = + (await stasQuery( + identityKey, + chain, + 'listStasOutputs', + [] + )) ?? []; + const source = allOutputs.find( + (o: any) => o.txid === txid && o.vout === vout + ); + if (!source) { + response = { + request_id: req.request_id, + status: 404, + body: JSON.stringify({ + error: `STAS UTXO ${outpoint} not found in wallet`, + }), + }; + break; + } + + // Permission gate: surface a modal to the user before we sign + // and broadcast. The enqueuer is set by WalletContext; + // if it's missing (e.g. the page is still mounting on first + // boot) we fail closed with 503 rather than silently sign. + if (!_currentStasTransferEnqueuer) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ + ok: false, + reason: 'STAS transfer permission gate not ready', + }), + }; + break; + } + // Look up the token's symbol so the prompt shows something + // meaningful (otherwise it would just say "100 sats"). + let tokenSymbol: string | null = null; + try { + const tokens: any[] = + (await stasQuery(identityKey, chain, 'listStasTokens', [])) ?? []; + const tok = tokens.find((t: any) => t.tokenId === source.tokenId); + tokenSymbol = tok?.symbol ?? null; + } catch { /* best effort */ } + + const approved = await _currentStasTransferEnqueuer({ + originator: origin || 'unknown', + outpoint, + symbol: tokenSymbol, + tokenId: source.tokenId ?? null, + satoshis: source.outputSatoshis ?? source.tokenSatoshis, + recipient: recipientAddress, + brc42KeyId: source.brc42KeyId ?? null, + }); + if (!approved) { + response = { + request_id: req.request_id, + status: 403, + body: JSON.stringify({ + ok: false, + reason: 'transfer denied by user', + }), + }; + break; + } + + const result = await transfer.transfer({ + source: { + txid: source.txid, + vout: source.vout, + scriptHex: source.lockingScript, + satoshis: source.outputSatoshis ?? source.tokenSatoshis, + brc42KeyId: source.brc42KeyId, + }, + recipientAddress, + }); + // Always return 200 when the transfer service produced a result — + // success/failure is in the body's `ok` field. Reserve 500 for + // actual handler exceptions (caught below). Previously a + // failed-but-clean result mapped to 500, which made consumers' + // generic HTTP-error handlers print "Internal Server Error" + // instead of the real reason. + if (!result.ok) { + // eslint-disable-next-line no-console + console.warn('[stas/transfer] service reported failure:', result.reason); + } + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify(result), + }; + } catch (e) { + // Surface the actual exception so future failures are easier to + // diagnose than a bare 500. Goes to the renderer's DevTools + // console where you can read it. + // eslint-disable-next-line no-console + console.error('[stas/transfer] handler threw:', e); + response = { + request_id: req.request_id, + status: 500, + body: JSON.stringify({ + ok: false, + reason: e instanceof Error ? e.message : String(e), + }), + }; + } + break; + } + + // STAS auto-register (non-BRC-100, BSV Desktop extension). + // Faucets / senders POST { txid } after broadcast; the wallet runs + // discovery.registerByTxid which fetches the rawTx + merkle path, + // parses, matches owner field to a derived key, and internalizes. + case '/stas/register-by-txid': { + // DEMO-ONLY fast-path. The PRIMARY STAS discovery mechanism is + // `StasDiscoveryService.scan()` via Bitails, fired by the + // AssetsPage Refresh button + on wallet mount. This route lets + // a colocated mint flow (the demo faucet via the dex-shell) + // skip the indexer round-trip and get immediate UI feedback. + try { + if (!_currentStasDiscovery) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ error: 'STAS discovery service not ready' }), + }; + break; + } + const { txid } = (req.body ? JSON.parse(req.body) : {}) as { txid?: string }; + if (typeof txid !== 'string' || !/^[0-9a-f]{64}$/i.test(txid)) { + response = { + request_id: req.request_id, + status: 400, + body: JSON.stringify({ error: 'txid (64-hex) is required' }), + }; + break; + } + const result = await _currentStasDiscovery.registerByTxid(txid); + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify(result), + }; + } catch (e) { + response = { + request_id: req.request_id, + status: 500, + body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }), + }; + } + break; + } + + case '/bsv-21/receive-address': { + // Mirror of /stas/receive-address but for the BSV-21 BRC-42 + // namespace. Why this exists: BSV-21 receives are scanned at + // addresses derived under the BSV-21 protocol id only — a STAS + // receive address won't appear in the BSV-21 discovery service's + // gap, so a BSV-21 sent there is silently orphaned. External + // apps (faucet, dex-shell) need a way to ask the wallet + // "give me a BSV-21 receive address" without guessing the + // namespace internally. + if (!_currentBsv21Discovery) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ error: 'BSV-21 services not ready' }), + }; + break; + } + try { + const deriver = _currentBsv21Discovery.getDeriver?.(); + if (!deriver) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ error: 'BSV-21 key deriver unavailable' }), + }; + break; + } + const row = await deriver.createNextReceiveContext(); + const dxs = await import('dxs-bsv-token-sdk/bsv'); + const base58 = new (dxs as any).Address( + (dxs as any).fromHex(row.ownerFieldHash160) + ).Value as string; + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify({ + address: base58, + ownerFieldHash160: row.ownerFieldHash160, + brc42KeyId: row.keyId, + keyIndex: row.keyIndex, + }), + }; + } catch (e) { + response = { + request_id: req.request_id, + status: 500, + body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }), + }; + } + break; + } + + case '/bsv-21/register-by-txid': { + // DEMO-ONLY fast-path. The PRIMARY BSV-21 discovery mechanism + // is `BSV21DiscoveryService.scan()` via the 1Sat overlay's + // per-address SSE stream. That path covers organic receive — + // any sender whose broadcast routes through `/1sat/tx` (the + // faucet now does this per-mint) registers their tx with the + // overlay's BSV-21 topic-manager, after which the wallet's + // per-address sync surfaces the UTXO on Refresh. + // + // This route exists for immediate UI feedback: a colocated + // mint flow (dex-shell after a faucet mint) hands the wallet + // the txid and we register the output without waiting for the + // next Refresh. Mirror of `/stas/register-by-txid`. + try { + if (!_currentBsv21Discovery) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ error: 'BSV-21 discovery service not ready' }), + }; + break; + } + const { txid } = (req.body ? JSON.parse(req.body) : {}) as { txid?: string }; + if (typeof txid !== 'string' || !/^[0-9a-f]{64}$/i.test(txid)) { + response = { + request_id: req.request_id, + status: 400, + body: JSON.stringify({ error: 'txid (64-hex) is required' }), + }; + break; + } + const result = await _currentBsv21Discovery.registerByTxid(txid); + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify(result), + }; + } catch (e) { + response = { + request_id: req.request_id, + status: 500, + body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }), + }; + } + break; + } + + case '/bsv-21/recover-by-outpoint': { + // Recover a pre-fix orphaned BSV-21 output. Pre-PR-32 sends + // produced change outputs without basket+customInstructions+tags, + // so they sit in the `outputs` table as `basketId=NULL` and + // never show up in listOutputs({basket:'bsv-21-tokens'}). The + // recovery flow proves ownership via key derivation, then + // retroactively assigns the basket metadata so they become + // visible and spendable again. + // + // Idempotent — already-recovered outputs return alreadyHadBasket=true. + try { + if (!_currentBsv21Discovery || !_currentStasBundle) { + response = { + request_id: req.request_id, + status: 503, + body: JSON.stringify({ error: 'BSV-21 discovery service not ready' }), + }; + break; + } + const { txid, vout } = (req.body ? JSON.parse(req.body) : {}) as { + txid?: string; + vout?: number; + }; + if (typeof txid !== 'string' || !/^[0-9a-f]{64}$/i.test(txid)) { + response = { + request_id: req.request_id, + status: 400, + body: JSON.stringify({ error: 'txid (64-hex) is required' }), + }; + break; + } + if (typeof vout !== 'number' || !Number.isInteger(vout) || vout < 0) { + response = { + request_id: req.request_id, + status: 400, + body: JSON.stringify({ error: 'vout (non-negative integer) is required' }), + }; + break; + } + const { identityKey, chain } = _currentStasBundle; + const result = await _currentBsv21Discovery.recoverByOutpoint({ + txid, + vout, + identityKey, + chain, + }); + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify(result), + }; + } catch (e) { + response = { + request_id: req.request_id, + status: 500, + body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }), + }; + } + break; + } + + // ── Peer-token routes (Phase B) ───────────────────────────────────── + // Drive the tester's own wallet from a standalone web page: + // GET /peerToken/identity → { identityKey } + // GET /peerToken/holdings → { holdings: [{ outpoint, protocol, label, amount, assetId }] } + // POST /peerToken/send → { outpoint, recipient, amount, dryRun? } + // GET /peerToken/incoming → { incoming: [...] } + // POST /peerToken/accept → { messageId } + // Source resolution (incl. BRC-29 owner derivation) stays server-side: + // the page references a holding by outpoint and never sees key material. + + case '/peerToken/identity': { + if (!_currentPeerTokensBundle) { + response = { request_id: req.request_id, status: 503, body: JSON.stringify({ error: 'Peer tokens not ready' }) }; + break; + } + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify({ identityKey: _currentPeerTokensBundle.identityKey }), + }; + break; + } + + case '/peerToken/holdings': { + if (!_currentPeerTokensBundle) { + response = { request_id: req.request_id, status: 503, body: JSON.stringify({ error: 'Peer tokens not ready' }) }; + break; + } + try { + const { wallet: w, identityKey, chain, originator } = _currentPeerTokensBundle; + const holdings = await loadPeerHoldings({ wallet: w, identityKey, chain, originator }); + response = { + request_id: req.request_id, + status: 200, + body: JSON.stringify({ + holdings: holdings.map((h) => ({ + outpoint: h.key, + protocol: h.protocol, + label: h.label, + amount: h.amount, + assetId: h.source.assetId, + })), + }), + }; + } catch (e) { + response = { request_id: req.request_id, status: 500, body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }) }; + } + break; + } + + case '/peerToken/send': { + if (!_currentPeerTokensBundle) { + response = { request_id: req.request_id, status: 503, body: JSON.stringify({ error: 'Peer tokens not ready' }) }; + break; + } + try { + const { client, wallet: w, identityKey, chain, originator } = _currentPeerTokensBundle; + const { outpoint, recipient, amount, dryRun } = (req.body ? JSON.parse(req.body) : {}) as { + outpoint?: string; recipient?: string; amount?: string | number; dryRun?: boolean; + }; + if (!outpoint || !recipient) { + response = { request_id: req.request_id, status: 400, body: JSON.stringify({ error: 'outpoint and recipient are required' }) }; + break; + } + // Re-resolve the full source (incl. owner override) from the outpoint. + const holdings = await loadPeerHoldings({ wallet: w, identityKey, chain, originator }); + const holding = holdings.find((h) => h.key === outpoint); + if (!holding) { + response = { request_id: req.request_id, status: 404, body: JSON.stringify({ error: `holding ${outpoint} not found (already spent or wrong wallet)` }) }; + break; + } + const params = { + recipient: String(recipient).trim(), + protocol: holding.protocol, + source: holding.source, + amount: String(amount ?? holding.amount), + }; + if (dryRun) { + const token = await client.createTokenToken(params, true); + response = { request_id: req.request_id, status: 200, body: JSON.stringify({ dryRun: true, token }) }; + } else { + const sent = await client.sendToken(params); + response = { request_id: req.request_id, status: 200, body: JSON.stringify({ dryRun: false, txid: sent?.txid ?? null, token: sent }) }; + } + } catch (e) { + response = { request_id: req.request_id, status: 500, body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }) }; + } + break; + } + + case '/peerToken/incoming': { + if (!_currentPeerTokensBundle) { + response = { request_id: req.request_id, status: 503, body: JSON.stringify({ error: 'Peer tokens not ready' }) }; + break; + } + try { + const incoming = await _currentPeerTokensBundle.client.listIncomingTokens(); + response = { request_id: req.request_id, status: 200, body: JSON.stringify({ incoming }) }; + } catch (e) { + response = { request_id: req.request_id, status: 500, body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }) }; + } + break; + } + + case '/peerToken/accept': { + if (!_currentPeerTokensBundle) { + response = { request_id: req.request_id, status: 503, body: JSON.stringify({ error: 'Peer tokens not ready' }) }; + break; + } + try { + const { client } = _currentPeerTokensBundle; + const { messageId } = (req.body ? JSON.parse(req.body) : {}) as { messageId?: string }; + if (!messageId) { + response = { request_id: req.request_id, status: 400, body: JSON.stringify({ error: 'messageId is required' }) }; + break; + } + const incoming = await client.listIncomingTokens(); + const tok = incoming.find((t: any) => t.messageId === messageId); + if (!tok) { + response = { request_id: req.request_id, status: 404, body: JSON.stringify({ error: `incoming token ${messageId} not found` }) }; + break; + } + const r = await client.acceptToken(tok); + if (typeof r === 'string') { + response = { request_id: req.request_id, status: 500, body: JSON.stringify({ error: r }) }; + } else { + response = { request_id: req.request_id, status: 200, body: JSON.stringify({ accepted: true, protocol: tok.token?.protocol }) }; + } + } catch (e) { + response = { request_id: req.request_id, status: 500, body: JSON.stringify({ error: e instanceof Error ? e.message : String(e) }) }; + } + break; + } + + // Legacy address sends for DSTAS + BSV-21 — the terminal analog of the + // Assets page's Send button. Sends a token on-chain to a plain address + // WITHOUT MessageBox (receiver discovers it via WOC), using the SAME + // TokenProtocolRegistry adapters the Assets page uses + // (`tokens.getById(protocol).transfer(...)`). PeerTokenClient is not + // involved. STAS keeps its own `/stas/transfer` (with permission modal). + // POST /dstas/transfer { outpoint, recipientAddress } (whole UTXO) + // POST /bsv-21/transfer { outpoint, recipientAddress, amount? } (amount = raw units, default whole) + case '/dstas/transfer': + case '/bsv-21/transfer': { + if (!_currentPeerTokensBundle?.tokens) { + response = { request_id: req.request_id, status: 503, body: JSON.stringify({ error: 'Token services not ready' }) }; + break; + } + const wantProtocol = req.path === '/dstas/transfer' ? 'dstas' : 'bsv-21'; + try { + const { wallet: w, identityKey, chain, originator, tokens } = _currentPeerTokensBundle; + const { outpoint, recipientAddress, amount } = (req.body ? JSON.parse(req.body) : {}) as { + outpoint?: string; recipientAddress?: string; amount?: string | number; + }; + if (!outpoint || !recipientAddress) { + response = { request_id: req.request_id, status: 400, body: JSON.stringify({ error: 'outpoint and recipientAddress are required' }) }; + break; + } + // Resolve the holding's full source from just the outpoint — the + // same uniform resolver the Assets page + /peerToken routes use. + const holdings = await loadPeerHoldings({ wallet: w, identityKey, chain, originator }); + const holding = holdings.find((h) => h.key === outpoint); + if (!holding) { + response = { request_id: req.request_id, status: 404, body: JSON.stringify({ error: `holding ${outpoint} not found (already spent or wrong wallet)` }) }; + break; + } + if (holding.protocol !== wantProtocol) { + response = { request_id: req.request_id, status: 400, body: JSON.stringify({ error: `outpoint is ${holding.protocol}, not ${wantProtocol}` }) }; + break; + } + const adapter = tokens.getById(holding.protocol); + if (!adapter?.transferSupported || !adapter.transfer) { + response = { request_id: req.request_id, status: 400, body: JSON.stringify({ error: `send not supported for ${holding.protocol}` }) }; + break; + } + const s: any = holding.source; + const baseArgs: any = { + source: { + txid: s.txid, + vout: s.outputIndex, + scriptHex: s.lockingScriptHex, + satoshis: s.satoshis, + brc42KeyId: s.brc42KeyId ?? 'recv 0', + }, + recipientAddress: String(recipientAddress).trim(), + }; + let args: any = baseArgs; + if (holding.protocol === 'bsv-21') { + // BSV-21 is divisible: amount is a raw bigint string; default to + // the whole balance. The service builds a token-change output + // when amount < balance. (DSTAS goes whole-UTXO via the registry + // adapter, matching the Assets page.) + const sendAmt = amount != null ? String(amount) : String(s.amt ?? '0'); + if (!/^\d+$/.test(sendAmt) || BigInt(sendAmt) <= 0n) { + response = { request_id: req.request_id, status: 400, body: JSON.stringify({ error: `amount must be a positive integer (raw token units); got ${sendAmt}` }) }; + break; + } + if (BigInt(sendAmt) > BigInt(s.amt ?? '0')) { + response = { request_id: req.request_id, status: 400, body: JSON.stringify({ error: `amount ${sendAmt} exceeds balance ${s.amt}` }) }; + break; + } + args = { ...baseArgs, tokenId: s.tokenId ?? s.assetId, sourceAmt: String(s.amt), amount: sendAmt, dec: s.dec, sym: s.sym, icon: s.icon }; + } + // No permission modal here (unlike /stas/transfer): these are + // Origin-gated routes, parity with /peerToken/send, which also + // avoids the 30s HTTP-bridge timeout racing a human click. + const result = await adapter.transfer(args); + response = { request_id: req.request_id, status: 200, body: JSON.stringify(result) }; + } catch (e) { + response = { request_id: req.request_id, status: 500, body: JSON.stringify({ ok: false, reason: e instanceof Error ? e.message : String(e) }) }; + } + break; + } + default: { response = { request_id: req.request_id, diff --git a/test/stas/derivation.test.ts b/test/stas/derivation.test.ts new file mode 100644 index 0000000..ee1e047 --- /dev/null +++ b/test/stas/derivation.test.ts @@ -0,0 +1,45 @@ +/** + * V2 — STAS receive-key derivation determinism. + * + * A ProtoWallet over a fixed root key exercises only `getPublicKey`, which is + * all StasKeyDeriver needs. Pure local logic — no chain interaction. + */ + +import { describe, test, expect } from 'vitest' +import { ProtoWallet, PrivateKey } from '@bsv/sdk' +import { StasKeyDeriver } from '../../src/lib/services/stas/StasKeyDeriver' + +function deriver() { + const wallet = new ProtoWallet(PrivateKey.fromRandom()) + return new StasKeyDeriver(wallet as any, 'test-identity', 'main') +} + +describe('StasKeyDeriver.deriveReceiveKey', () => { + test('is deterministic — same index yields the same key', async () => { + const d = deriver() + const a = await d.deriveReceiveKey(1) + const b = await d.deriveReceiveKey(1) + expect(a.publicKey).toBe(b.publicKey) + expect(a.ownerFieldHash160).toBe(b.ownerFieldHash160) + expect(a.keyId).toBe('recv 1') + }) + + test('distinct indices yield distinct keys', async () => { + const d = deriver() + const k1 = await d.deriveReceiveKey(1) + const k2 = await d.deriveReceiveKey(2) + expect(k1.publicKey).not.toBe(k2.publicKey) + expect(k1.ownerFieldHash160).not.toBe(k2.ownerFieldHash160) + }) + + test('owner field is a 20-byte hash160', async () => { + const k = await deriver().deriveReceiveKey(7) + expect(k.ownerFieldHash160).toMatch(/^[0-9a-f]{40}$/) + }) + + test('different roots derive different keys for the same index', async () => { + const a = await deriver().deriveReceiveKey(1) + const b = await deriver().deriveReceiveKey(1) + expect(a.ownerFieldHash160).not.toBe(b.ownerFieldHash160) + }) +}) diff --git a/test/stas/discovery.test.ts b/test/stas/discovery.test.ts new file mode 100644 index 0000000..0c251a9 --- /dev/null +++ b/test/stas/discovery.test.ts @@ -0,0 +1,235 @@ +/** + * V5 — StasDiscoveryService orchestrator unit tests. + * + * Wires a real BRC-42 key deriver (ProtoWallet) into the discovery service + * with mocked IndexerClient, StasRegistration, and wallet.getServices(). Real + * DSTAS scripts are built per scenario so the parser is exercised end-to-end; + * only the network/storage seams are mocked. + */ + +import { describe, test, expect } from 'vitest' +import { ProtoWallet, PrivateKey, Transaction, LockingScript } from '@bsv/sdk' +import { + buildDstasLockingScriptForOwnerField, + fromHex, + Address, +} from 'dxs-bsv-token-sdk/bsv' +import { StasKeyDeriver } from '../../src/lib/services/stas/StasKeyDeriver' +import { StasDiscoveryService } from '../../src/lib/services/stas/StasDiscoveryService' +import { + TokenProtocolRegistry, + StasProtocolAdapter, + DstasProtocolAdapter, +} from '../../src/lib/services/tokens' + +function mkDeriver(): StasKeyDeriver { + const wallet = new ProtoWallet(PrivateKey.fromRandom()) + return new StasKeyDeriver(wallet as any, 'test-identity', 'main') +} + +/** + * Test-only registry — the discovery scan dispatches via `registry.find()` + * after the multi-protocol refactor. Production wires this in WalletService; + * tests pass a minimal one with parse-only adapters (no transfer service). + */ +function mkRegistry(): TokenProtocolRegistry { + const r = new TokenProtocolRegistry() + // StasProtocolAdapter only needs a transfer service for its `.transfer()` + // method — `parseOutput` doesn't touch it. Cast `null` through `any`. + r.register(new StasProtocolAdapter(null as any)) + r.register(new DstasProtocolAdapter()) + return r +} + +function makeDstasTxFor(ownerFieldHash160Hex: string) { + const z20 = new Uint8Array(20) + const sb: any = buildDstasLockingScriptForOwnerField({ + ownerField: fromHex(ownerFieldHash160Hex), + tokenIdHex: 'ab'.repeat(20), + freezable: true, + confiscatable: true, + authorityServiceField: z20, + confiscationAuthorityServiceField: z20, + frozen: false, + }) + const tx = new Transaction() + tx.addOutput({ lockingScript: LockingScript.fromHex(sb.toHex()), satoshis: 100 }) + return { rawTx: tx.toBinary(), txid: tx.id('hex') } +} + +function ownerAddress(ownerFieldHash160Hex: string): string { + return new (Address as any)(fromHex(ownerFieldHash160Hex)).Value as string +} + +describe('StasDiscoveryService.scan', () => { + test('scans the derived gap range and returns empty counts when the indexer finds nothing', async () => { + const deriver = mkDeriver() + const indexer: any = { + // WOC serves DSTAS by owner hash160; these cases exercise the STAS path. + getDstasUtxosForOwners: async () => [], + getUtxosForAddresses: async (addrs: string[]) => + addrs.map((a) => ({ address: a, utxos: [] })), + } + const registration: any = { register: async () => ({ registered: false, txid: 'x', vout: 0 }) } + const wallet: any = { getServices: () => ({ getRawTx: async () => ({ rawTx: [0] }) }) } + const svc = new StasDiscoveryService({ deriver, indexer, registration, wallet, registry: mkRegistry(), gapLimit: 5 }) + + const result = await svc.scan() + expect(result.scannedAddresses).toBeGreaterThanOrEqual(5) + expect(result.candidates).toBe(0) + expect(result.registered).toBe(0) + expect(result.ownedAndDstas).toBe(0) + }) + + test('recognises a wallet-owned DSTAS UTXO and forwards it to registration', async () => { + const deriver = mkDeriver() + const k3 = await deriver.deriveReceiveKey(3) + const { rawTx, txid } = makeDstasTxFor(k3.ownerFieldHash160) + const targetAddress = ownerAddress(k3.ownerFieldHash160) + + const indexer: any = { + // WOC serves DSTAS by owner hash160; these cases exercise the STAS path. + getDstasUtxosForOwners: async () => [], + getUtxosForAddresses: async (addrs: string[]) => + addrs.map((a) => ({ + address: a, + utxos: + a === targetAddress + ? [{ txid, vout: 0, value: 100, height: 950000 }] + : [], + })), + } + const registerCalls: any[] = [] + const registration: any = { + register: async (args: any) => { + registerCalls.push(args) + return { registered: true, txid: args.txid, vout: args.vout } + }, + } + const wallet: any = { + getServices: () => ({ + getRawTx: async (id: string) => + id === txid ? { rawTx } : { error: { message: 'not found' } }, + }), + } + const svc = new StasDiscoveryService({ deriver, indexer, registration, wallet, registry: mkRegistry(), gapLimit: 5 }) + + const result = await svc.scan() + expect(result.dstas).toBe(1) + expect(result.ownedAndDstas).toBe(1) + expect(result.registered).toBe(1) + expect(result.deferred).toBe(0) + expect(registerCalls).toHaveLength(1) + expect(registerCalls[0].brc42KeyId).toBe('recv 3') + expect(registerCalls[0].ownerFieldHash160).toBe(k3.ownerFieldHash160) + expect(result.registeredOutpoints[0].txid).toBe(txid) + }) + + test('mempool (height 0) UTXOs still go through registration (Task 4c: chained BEEF handles it)', async () => { + // Previously the discovery loop deferred height === 0. Now Bitails surfaces + // mempool STAS and buildChainedAtomicBeef walks input ancestry to a confirmed + // bump — registration is called regardless of height. + const deriver = mkDeriver() + const k1 = await deriver.deriveReceiveKey(1) + const { rawTx, txid } = makeDstasTxFor(k1.ownerFieldHash160) + const targetAddress = ownerAddress(k1.ownerFieldHash160) + + const indexer: any = { + // WOC serves DSTAS by owner hash160; these cases exercise the STAS path. + getDstasUtxosForOwners: async () => [], + getUtxosForAddresses: async (addrs: string[]) => + addrs.map((a) => ({ + address: a, + utxos: + a === targetAddress + ? [{ txid, vout: 0, value: 100, height: 0 }] + : [], + })), + } + const registerCalls: any[] = [] + const registration: any = { + register: async (args: any) => { + registerCalls.push(args) + return { registered: true, txid: args.txid, vout: args.vout } + }, + } + const wallet: any = { + getServices: () => ({ + getRawTx: async () => ({ rawTx }), + }), + } + const svc = new StasDiscoveryService({ deriver, indexer, registration, wallet, registry: mkRegistry(), gapLimit: 5 }) + + const result = await svc.scan() + expect(result.dstas).toBe(1) + expect(result.ownedAndDstas).toBe(1) + expect(result.deferred).toBe(0) + expect(result.registered).toBe(1) + expect(registerCalls).toHaveLength(1) + }) + + test('bootstrap mode: hwm=0 caps the scan at the small bootstrap window', async () => { + const deriver = mkDeriver() + let addressesSeen = 0 + const indexer: any = { + // WOC serves DSTAS by owner hash160; these cases exercise the STAS path. + getDstasUtxosForOwners: async () => [], + getUtxosForAddresses: async (addrs: string[]) => { + addressesSeen = addrs.length + return addrs.map((a) => ({ address: a, utxos: [] })) + }, + } + const registration: any = { register: async () => ({ registered: false }) } + const wallet: any = { getServices: () => ({ getRawTx: async () => ({ rawTx: [0] }) }) } + // Caller asks for a large gap, but hwm=0 should cap the actual scan range. + const svc = new StasDiscoveryService({ deriver, indexer, registration, wallet, registry: mkRegistry(), gapLimit: 100 }) + await svc.scan() + expect(addressesSeen).toBe(5) + }) + + test('ignores a foreign owner field even when the indexer returns it', async () => { + const deriver = mkDeriver() + // Build a tx for a foreign key (a different random root). + const foreignWallet = new ProtoWallet(PrivateKey.fromRandom()) + const foreignDeriver = new StasKeyDeriver(foreignWallet as any, 'other-identity', 'main') + const foreign = await foreignDeriver.deriveReceiveKey(1) + + const { rawTx, txid } = makeDstasTxFor(foreign.ownerFieldHash160) + // The indexer returns it at one of OUR addresses anyway (defensive scenario). + const ourFirstKey = await deriver.deriveReceiveKey(1) + const ourAddress = ownerAddress(ourFirstKey.ownerFieldHash160) + + const indexer: any = { + // WOC serves DSTAS by owner hash160; these cases exercise the STAS path. + getDstasUtxosForOwners: async () => [], + getUtxosForAddresses: async (addrs: string[]) => + addrs.map((a) => ({ + address: a, + utxos: + a === ourAddress + ? [{ txid, vout: 0, value: 100, height: 950000 }] + : [], + })), + } + const registerCalls: any[] = [] + const registration: any = { + register: async (args: any) => { + registerCalls.push(args) + return { registered: true, txid: args.txid, vout: args.vout } + }, + } + const wallet: any = { + getServices: () => ({ + getRawTx: async () => ({ rawTx }), + }), + } + const svc = new StasDiscoveryService({ deriver, indexer, registration, wallet, registry: mkRegistry(), gapLimit: 5 }) + + const result = await svc.scan() + // Parses as DSTAS, but the owner field is not in our derived set. + expect(result.dstas).toBe(1) + expect(result.ownedAndDstas).toBe(0) + expect(result.registered).toBe(0) + expect(registerCalls).toHaveLength(0) + }) +}) diff --git a/test/stas/migration.test.ts b/test/stas/migration.test.ts new file mode 100644 index 0000000..9d1fc02 --- /dev/null +++ b/test/stas/migration.test.ts @@ -0,0 +1,139 @@ +/** + * V1 — STAS storage migration. + * + * Verifies that the bsv-desktop-owned STAS migration creates its three tables, + * tracks itself in the isolated `knex_migrations_stas` ledger, and is idempotent. + * Pure local logic — no chain interaction. + */ + +import { describe, test, expect } from 'vitest' +import knex from 'knex' +import { stasMigrationSource } from '../../electron/stas-migrations/index' + +// `better-sqlite3` is a native module rebuilt against Electron's Node ABI by +// the project's `postinstall: electron-builder install-app-deps` hook. Plain +// `node` (which Vitest uses by default) then can't load it. These tests still +// pass when better-sqlite3 happens to match the runtime ABI (e.g. you ran +// `npm rebuild better-sqlite3` first — see `npm run test:stas:db`). We skip +// gracefully otherwise so the rest of the suite stays runnable in plain node. +async function canUseBetterSqlite3(): Promise { + try { + const probe = knex({ + client: 'better-sqlite3', + connection: { filename: ':memory:' }, + useNullAsDefault: true, + }) + await probe.raw('SELECT 1') + await probe.destroy() + return true + } catch { + return false + } +} + +const sqliteAvailable = await canUseBetterSqlite3() + +const MIGRATOR = { migrationSource: stasMigrationSource, tableName: 'knex_migrations_stas' } + +async function freshDb() { + const db = knex({ + client: 'better-sqlite3', + connection: { filename: ':memory:' }, + useNullAsDefault: true, + }) + // Stand-in for wallet-toolbox's `outputs` table (FK target of stas_outputs). + // Migration 0002's DSTAS backfill joins on lockingScript + userId, so the + // stand-in must carry them or the whole chain fails at 0002. + await db.schema.createTable('outputs', (t: any) => { + t.integer('outputId').primary() + t.text('lockingScript') + t.integer('userId') + }) + return db +} + +describe.skipIf(!sqliteAvailable)('STAS migration 0001', () => { + test('creates the three STAS tables and records the migration', async () => { + const db = await freshDb() + await db.migrate.latest(MIGRATOR) + + expect(await db.schema.hasTable('stas_tokens')).toBe(true) + expect(await db.schema.hasTable('stas_outputs')).toBe(true) + expect(await db.schema.hasTable('stas_receive_contexts')).toBe(true) + + const ledger = await db('knex_migrations_stas').select('name') + expect(ledger.map((r: any) => r.name)).toContain('0001_create_stas_tables') + + await db.destroy() + }) + + test('is idempotent — a second run applies nothing new', async () => { + const db = await freshDb() + await db.migrate.latest(MIGRATOR) + const after1 = Number((await db('knex_migrations_stas').count('* as c'))[0].c) + await db.migrate.latest(MIGRATOR) + const after2 = Number((await db('knex_migrations_stas').count('* as c'))[0].c) + + // One ledger row per applied migration, unchanged by a repeat run. + expect(after1).toBeGreaterThan(0) + expect(after2).toBe(after1) + + await db.destroy() + }) + + test('stas_receive_contexts enforces unique (profile, keyIndex)', async () => { + const db = await freshDb() + await db.migrate.latest(MIGRATOR) + + const row = { + profileIdentityKey: 'p1', + keyIndex: 1, + keyId: 'recv 1', + ownerFieldHash160: '00'.repeat(20), + derivedPublicKey: '02'.padEnd(66, '0'), + createdAt: new Date().toISOString(), + } + await db('stas_receive_contexts').insert(row) + await expect(db('stas_receive_contexts').insert(row)).rejects.toThrow() + + await db.destroy() + }) +}) + +describe.skipIf(!sqliteAvailable)('STAS migration 0004 — token_verifications', () => { + test('creates the table and StasQueries roundtrips a verdict', async () => { + const db = await freshDb() + await db.migrate.latest(MIGRATOR) + expect(await db.schema.hasTable('token_verifications')).toBe(true) + + const { StasQueries } = await import('../../electron/stas-queries') + const q = new StasQueries(db) + + const now = new Date().toISOString() + await q.upsertTokenVerification({ + txid: 'aa', vout: 0, protocol: 'stas', result: 'authentic', + genesis: 'aa_0', genesisDepth: 0, reason: null, verifiedAt: now, + }) + // Upsert is keyed on the outpoint — a re-verify overwrites, not duplicates. + await q.upsertTokenVerification({ + txid: 'aa', vout: 0, protocol: 'stas', result: 'not-authentic', + genesis: null, genesisDepth: null, reason: 'no-genesis', verifiedAt: now, + }) + // A different outpoint is a separate row. + await q.upsertTokenVerification({ + txid: 'bb', vout: 1, protocol: 'bsv-21', result: 'authentic', + genesis: 'bb_1', genesisDepth: 2, reason: null, verifiedAt: now, + }) + + const rows = await q.listTokenVerifications() + expect(rows).toHaveLength(2) + const aa = rows.find((r: any) => r.txid === 'aa') + expect(aa.result).toBe('not-authentic') + expect(aa.reason).toBe('no-genesis') + const bb = rows.find((r: any) => r.txid === 'bb') + expect(bb.protocol).toBe('bsv-21') + expect(bb.genesisDepth).toBe(2) + + await db.destroy() + }) +}) diff --git a/test/stas/ownership.test.ts b/test/stas/ownership.test.ts new file mode 100644 index 0000000..5bbeec0 --- /dev/null +++ b/test/stas/ownership.test.ts @@ -0,0 +1,68 @@ +/** + * V3 — STAS ownership recognition (Task 3 acceptance criterion). + * + * Builds real DSTAS locking scripts with dxs-bsv-token-sdk and checks that + * StasOwnershipService recognises a wallet-derived owner field, rejects a + * foreign one, and rejects a non-DSTAS script. Pure local logic — no chain. + * + * No high-water mark is persisted in this environment, so getHighWaterMark() + * returns 0 and the scan covers `recv 1..gapLimit` (100) — the test key at + * index 3 is well within range. + */ + +import { describe, test, expect } from 'vitest' +import { ProtoWallet, PrivateKey } from '@bsv/sdk' +import { buildDstasLockingScriptForOwnerField, fromHex } from 'dxs-bsv-token-sdk/bsv' +import { StasKeyDeriver } from '../../src/lib/services/stas/StasKeyDeriver' +import { StasOwnershipService } from '../../src/lib/services/stas/StasOwnershipService' +import { parseDstasLockingScript } from '../../src/lib/services/stas/dstasParser' + +/** Build a freeze+confiscation-enabled DSTAS locking script for an owner field. */ +function buildDstas(ownerFieldHash160Hex: string): string { + const zero20 = new Uint8Array(20) + const sb: any = buildDstasLockingScriptForOwnerField({ + ownerField: fromHex(ownerFieldHash160Hex), + tokenIdHex: 'ab'.repeat(20), + freezable: true, + confiscatable: true, + authorityServiceField: zero20, + confiscationAuthorityServiceField: zero20, + frozen: false, + }) + return sb.toHex() +} + +function freshWallet() { + const wallet = new ProtoWallet(PrivateKey.fromRandom()) + const deriver = new StasKeyDeriver(wallet as any, 'test-identity', 'main') + return { deriver, ownership: new StasOwnershipService(deriver) } +} + +describe('StasOwnershipService.isOwnedByWallet', () => { + test('builder/parser agree on the owner field round-trip', async () => { + const { deriver } = freshWallet() + const k = await deriver.deriveReceiveKey(3) + const parsed = parseDstasLockingScript(buildDstas(k.ownerFieldHash160)) + expect(parsed).not.toBeNull() + expect(parsed!.ownerFieldHash160).toBe(k.ownerFieldHash160) + }) + + test('recognises a wallet-derived owner field', async () => { + const { deriver, ownership } = freshWallet() + const k3 = await deriver.deriveReceiveKey(3) + const result = await ownership.isOwnedByWallet(buildDstas(k3.ownerFieldHash160)) + expect(result).toEqual({ owned: true, keyIndex: 3 }) + }) + + test('rejects a foreign owner field', async () => { + const { ownership } = freshWallet() + const result = await ownership.isOwnedByWallet(buildDstas('cd'.repeat(20))) + expect(result).toEqual({ owned: false }) + }) + + test('rejects a non-DSTAS (P2PKH) script', async () => { + const { ownership } = freshWallet() + const p2pkh = '76a914' + '00'.repeat(20) + '88ac' + expect(await ownership.isOwnedByWallet(p2pkh)).toEqual({ owned: false }) + }) +}) diff --git a/test/stas/registration.test.ts b/test/stas/registration.test.ts new file mode 100644 index 0000000..3341ccf --- /dev/null +++ b/test/stas/registration.test.ts @@ -0,0 +1,179 @@ +/** + * V4 — StasRegistration call-shape unit tests. + * + * Builds a real DSTAS locking script with `dxs-bsv-token-sdk`, wraps it in a + * minimal Transaction + single-leaf MerklePath via `@bsv/sdk`, then runs + * `register` against a stubbed wallet. We never call internalizeAction's real + * BEEF verifier; the assertion is on the args shape and the AtomicBEEF prefix. + */ + +import { describe, test, expect } from 'vitest' +import { Transaction, MerklePath, LockingScript } from '@bsv/sdk' +import { + buildDstasLockingScriptForOwnerField, + fromHex, +} from 'dxs-bsv-token-sdk/bsv' +import { StasRegistration } from '../../src/lib/services/stas/StasRegistration' + +function makeDstasTx(ownerFieldHash160: string) { + const zero20 = new Uint8Array(20) + const sb: any = buildDstasLockingScriptForOwnerField({ + ownerField: fromHex(ownerFieldHash160), + tokenIdHex: 'ab'.repeat(20), + freezable: true, + confiscatable: true, + authorityServiceField: zero20, + confiscationAuthorityServiceField: zero20, + frozen: false, + }) + const tx = new Transaction() + tx.addOutput({ lockingScript: LockingScript.fromHex(sb.toHex()), satoshis: 100 }) + const rawTx = tx.toBinary() + return { rawTx, txid: tx.id('hex') } +} + +interface CapturedCall { + args: any + originator: any +} + +function mkWallet(rawTx: number[], txid: string, opts: { withProof?: boolean } = {}) { + const calls: CapturedCall[] = [] + const merklePath = new MerklePath(100, [ + [{ offset: 0, hash: txid, txid: true }], + ]) + const wallet: any = { + internalizeAction: async (args: any, originator: any) => { + calls.push({ args, originator }) + return { accepted: true } + }, + getServices: () => ({ + getRawTx: async () => ({ rawTx }), + getMerklePath: async () => + opts.withProof === false ? {} : { merklePath }, + }), + } + return { wallet, calls } +} + +describe('StasRegistration.register', () => { + test('calls internalizeAction with the basket-insertion shape and AtomicBEEF prefix', async () => { + const ownerHash = 'cd'.repeat(20) + const { rawTx, txid } = makeDstasTx(ownerHash) + const { wallet, calls } = mkWallet(rawTx, txid) + + const reg = new StasRegistration(wallet, 'test-identity', 'main') + const result = await reg.register({ + txid, + vout: 0, + tokenSatoshis: 100, + ownerFieldHash160: ownerHash, + brc42KeyId: 'recv 3', + parsed: { + ownerFieldHash160: ownerHash, + tokenId: 'ab'.repeat(20), + freezeEnabled: true, + confiscationEnabled: true, + flagsHex: '03', + serviceFields: ['00'.repeat(20), '00'.repeat(20)], + }, + }) + + expect(result.registered).toBe(true) + expect(calls).toHaveLength(1) + const { args, originator } = calls[0] + expect(originator).toBe('admin.stas-discovery') + expect(args.description).toBe('STAS discovery') + expect(args.seekPermission).toBe(false) + expect(args.outputs).toHaveLength(1) + expect(args.outputs[0].outputIndex).toBe(0) + expect(args.outputs[0].protocol).toBe('basket insertion') + expect(args.outputs[0].insertionRemittance.basket).toBe('stas-tokens') + // Multi-protocol PR: tags now reflect the actual protocol id rather + // than the legacy 'dstas' string the original wallet hardcoded for + // every STAS-family output. With no `protocol` arg supplied, the + // default protocol is STAS (id: 'stas'). DSTAS rows in the new + // dstas-tokens basket carry the 'dstas' tag instead. + expect(args.outputs[0].insertionRemittance.tags).toContain('stas') + + // AtomicBEEF prefix (BRC-95) is 0x01010101 followed by the txid bytes. + const txBytes = Array.from(args.tx as number[]) + expect(txBytes.slice(0, 4)).toEqual([1, 1, 1, 1]) + + // customInstructions JSON shape + const ci = JSON.parse(args.outputs[0].insertionRemittance.customInstructions) + expect(ci.tokenId).toBe('ab'.repeat(20)) + expect(ci.brc42KeyId).toBe('recv 3') + expect(ci.flagsHex).toBe('03') + }) + + test('mempool target (no proof on target) walks back through inputs to a confirmed ancestor', async () => { + // Mempool target tx with one input; ancestor has the merkle proof. + const ownerHash = 'cd'.repeat(20) + const ancestor = makeDstasTx('ee'.repeat(20)) + const targetTx = new Transaction() + // Reference the ancestor as the input (one input, no script needed for this + // unit test — the validator never runs because internalizeAction is stubbed). + targetTx.addInput({ + sourceTransaction: Transaction.fromBinary(ancestor.rawTx), + sourceOutputIndex: 0, + unlockingScript: LockingScript.fromHex(''), + sequence: 0xffffffff, + }) + targetTx.addOutput({ + lockingScript: LockingScript.fromHex( + // Tiny push-only script; the test only cares about wiring. + '00', + ), + satoshis: 100, + }) + const targetRaw = targetTx.toBinary() + const targetId = targetTx.id('hex') + + const ancestorMp = new MerklePath(100, [ + [{ offset: 0, hash: ancestor.txid, txid: true }], + ]) + const calls: CapturedCall[] = [] + const wallet: any = { + internalizeAction: async (args: any, originator: any) => { + calls.push({ args, originator }) + return { accepted: true } + }, + getServices: () => ({ + getRawTx: async (id: string) => { + if (id === targetId) return { rawTx: targetRaw } + if (id === ancestor.txid) return { rawTx: ancestor.rawTx } + throw new Error(`unexpected getRawTx for ${id}`) + }, + getMerklePath: async (id: string) => { + // Target tx is mempool → no proof. Ancestor is confirmed. + if (id === ancestor.txid) return { merklePath: ancestorMp } + return {} + }, + }), + } + + const reg = new StasRegistration(wallet, 'test-identity', 'main') + const result = await reg.register({ + txid: targetId, + vout: 0, + tokenSatoshis: 100, + ownerFieldHash160: ownerHash, + brc42KeyId: 'recv 1', + parsed: { + ownerFieldHash160: ownerHash, + tokenId: 'ab'.repeat(20), + freezeEnabled: false, + confiscationEnabled: false, + flagsHex: '00', + serviceFields: [], + }, + }) + + // The chained BEEF was assembled and internalizeAction was called. + expect(result.registered).toBe(true) + expect(calls).toHaveLength(1) + const txBytes = Array.from(calls[0].args.tx as number[]) + expect(txBytes.slice(0, 4)).toEqual([1, 1, 1, 1]) // AtomicBEEF prefix + }) +}) diff --git a/test/tokens/back-to-genesis.test.ts b/test/tokens/back-to-genesis.test.ts new file mode 100644 index 0000000..3d6cbca --- /dev/null +++ b/test/tokens/back-to-genesis.test.ts @@ -0,0 +1,159 @@ +/** + * BackToGenesisClient tests. + * + * B2G is the wallet's counterfeit detector, so the two things that must never + * regress are: (1) the URL/query construction per standard + expectedGenesis, + * and (2) the fail-SAFE contract — a transport failure becomes `undetermined` + * ("unknown"), never a throw and never a false `not-authentic`. + * + * The response fixtures below are captured live from WOC mainnet (2026-07-14): + * a genuine STAS mint, and a real broadcast counterfeit that clones EXSTAS1's + * tokenId + amount but has no valid ancestor. + */ + +import { describe, test, expect, vi, beforeEach } from 'vitest' + +const fetchMock = vi.fn() +vi.mock('../../src/lib/utils/RateLimitedFetch', () => ({ + wocFetch: { fetch: (...args: any[]) => fetchMock(...args) }, +})) + +import { BackToGenesisClient, formatGenesisRef } from '../../src/lib/services/tokens/woc/BackToGenesisClient' + +const BASE = 'https://woc.test/v1/bsv/main' +const ok = (body: unknown) => ({ ok: true, json: async () => body }) +const httpErr = (status: number) => ({ ok: false, status, json: async () => ({}) }) + +const client = () => new BackToGenesisClient({ baseUrl: BASE }) + +beforeEach(() => fetchMock.mockReset()) + +describe('verify — URL construction', () => { + test('hits /token/{std}/tx/{txid}/out/{index}/verify', async () => { + fetchMock.mockResolvedValueOnce(ok({ outpoint: { txid: 'aa', index: 0 }, result: 'authentic' })) + await client().verify('stas', 'aa', 0) + expect(fetchMock.mock.calls[0][0]).toBe(`${BASE}/token/stas/tx/aa/out/0/verify`) + }) + + test('appends ?expectedGenesis when supplied', async () => { + fetchMock.mockResolvedValueOnce(ok({ outpoint: { txid: 'aa', index: 2 }, result: 'authentic' })) + await client().verify('dstas', 'aa', 2, { expectedGenesis: 'gg_0' }) + expect(fetchMock.mock.calls[0][0]).toBe(`${BASE}/token/dstas/tx/aa/out/2/verify?expectedGenesis=gg_0`) + }) +}) + +describe('verify — real response shapes (WOC mainnet 2026-07-14)', () => { + test('genuine STAS mint → authentic, depth 0', async () => { + fetchMock.mockResolvedValueOnce( + ok({ + outpoint: { txid: '4d43e232', index: 0 }, + result: 'authentic', + assetKey: { tokenId: '783eadfd045de5484fc4b81ab875df3d96380251' }, + genesis: { txid: '4d43e232', index: 0 }, + genesisDepth: 0, + amount: '1000', + conservationOk: true, + }) + ) + const r = await client().verify('stas', '4d43e232', 0) + expect(r.result).toBe('authentic') + expect(r.genesisDepth).toBe(0) + expect(r.genesis).toEqual({ txid: '4d43e232', index: 0 }) + expect(r.amount).toBe('1000') + }) + + test('broadcast counterfeit (same tokenId+amount as EXSTAS1) → not-authentic', async () => { + // f8609b32… — a real forgery: EXSTAS1's locking script funded by a + // non-issuer key, no token ancestor. Decodes as the real identity, still + // rejected. This is the whole feature's reason to exist. + fetchMock.mockResolvedValueOnce( + ok({ + outpoint: { txid: 'f8609b32', index: 0 }, + result: 'not-authentic', + reason: 'no-genesis', + assetKey: { tokenId: '783eadfd045de5484fc4b81ab875df3d96380251' }, + genesisDepth: 0, + amount: '1000', + conservationOk: true, + failedAt: { txid: 'f8609b32', index: 0 }, + }) + ) + const r = await client().verify('stas', 'f8609b32', 0) + expect(r.result).toBe('not-authentic') + expect(r.reason).toBe('no-genesis') + // The forgery carries the genuine identity fields — proving the verdict is + // driven by provenance, not by the decoded tokenId. + expect(r.assetKey?.tokenId).toBe('783eadfd045de5484fc4b81ab875df3d96380251') + }) + + test('expectedGenesis mismatch stays authentic with matchesExpectedGenesis:false', async () => { + fetchMock.mockResolvedValueOnce( + ok({ + outpoint: { txid: 'a8859452', index: 0 }, + result: 'authentic', + genesis: { txid: '4d43e232', index: 0 }, + genesisDepth: 1, + matchesExpectedGenesis: false, + }) + ) + const r = await client().verify('stas', 'a8859452', 0, { expectedGenesis: '8c57bb64_0' }) + expect(r.result).toBe('authentic') + expect(r.matchesExpectedGenesis).toBe(false) + }) +}) + +describe('fail-safe contract', () => { + test('HTTP 404 → undetermined, never a throw', async () => { + fetchMock.mockResolvedValueOnce(httpErr(404)) + const r = await client().verify('stas', 'deadbeef', 0) + expect(r.result).toBe('undetermined') + expect(r.reason).toBe('source-unavailable') + }) + + test('HTTP 400 (bad standard/index) → undetermined', async () => { + fetchMock.mockResolvedValueOnce(httpErr(400)) + const r = await client().verify('stas', 'aa', 0) + expect(r.result).toBe('undetermined') + }) + + test('network throw → undetermined, never propagates', async () => { + fetchMock.mockRejectedValueOnce(new Error('offline')) + const r = await client().verify('bsv21', 'aa', 0) + expect(r.result).toBe('undetermined') + }) +}) + +describe('trace', () => { + test('hits the trace path and returns the ordered path', async () => { + fetchMock.mockResolvedValueOnce( + ok({ + outpoint: { txid: 'cc', index: 0 }, + result: 'authentic', + genesis: { txid: 'gg', index: 0 }, + genesisDepth: 2, + path: [ + { txid: 'cc', index: 0, amount: '30', op: 'split', parentOutpoint: 'bb_0' }, + { txid: 'bb', index: 0, amount: '100', op: 'transfer', parentOutpoint: 'gg_0' }, + { txid: 'gg', index: 0, amount: '100', op: 'genesis' }, + ], + truncated: false, + }) + ) + const r = await client().trace('dstas', 'cc', 0) + expect(fetchMock.mock.calls[0][0]).toBe(`${BASE}/token/dstas/tx/cc/out/0/trace`) + expect(r.path?.[2].op).toBe('genesis') + expect(r.truncated).toBe(false) + }) + + test('maxDepth is passed through', async () => { + fetchMock.mockResolvedValueOnce(ok({ outpoint: { txid: 'cc', index: 0 }, result: 'authentic' })) + await client().trace('stas', 'cc', 0, { maxDepth: 50 }) + expect(fetchMock.mock.calls[0][0]).toBe(`${BASE}/token/stas/tx/cc/out/0/trace?maxDepth=50`) + }) +}) + +describe('formatGenesisRef', () => { + test('formats as _', () => { + expect(formatGenesisRef({ txid: 'abc', index: 3 })).toBe('abc_3') + }) +}) diff --git a/test/tokens/bsv21-inscription.test.ts b/test/tokens/bsv21-inscription.test.ts new file mode 100644 index 0000000..35a44dd --- /dev/null +++ b/test/tokens/bsv21-inscription.test.ts @@ -0,0 +1,253 @@ +/** + * BSV-21 inscription round-trip tests. + * + * The inscription builder and parser are pure functions that own the wire + * format the wallet uses to recognise BSV-21 receives. A bug here would be + * silent — the wallet would broadcast txs the indexer can't index, or fail + * to recognise inscriptions sent by other senders. Worth pinning down. + */ + +import { describe, test, expect } from 'vitest' +import { + buildBsv21Transfer, + parseBsv21LockingScript, +} from '../../src/lib/services/tokens/bsv21/inscription' + +// A real-looking owner PKH (20 bytes hex). Doesn't matter that it's not a +// valid hash160 of anything — the builder/parser don't verify, they just +// shuffle bytes. +const OWNER_HASH160 = '675d894f5ea1dbc6f1677850d07eef4d35fcdff6' + +describe('buildBsv21Transfer / parseBsv21LockingScript round-trip', () => { + test('minimal payload (id + amt only) survives a round trip', () => { + const hex = buildBsv21Transfer({ + payload: { + id: 'abc123_0', + amt: '1000', + }, + ownerHash160: OWNER_HASH160, + }) + const parsed = parseBsv21LockingScript(hex) + expect(parsed).not.toBeNull() + expect(parsed!.id).toBe('abc123_0') + expect(parsed!.amt).toBe('1000') + expect(parsed!.dec).toBeUndefined() + expect(parsed!.sym).toBeUndefined() + expect(parsed!.icon).toBeUndefined() + expect(parsed!.ownerHash160).toBe(OWNER_HASH160) + }) + + test('full payload (id + amt + dec + sym + icon) survives a round trip', () => { + const hex = buildBsv21Transfer({ + payload: { + id: 'deadbeef_3', + amt: '123456789', + dec: 8, + sym: 'TEST', + icon: 'icon_outpoint_xyz_0', + }, + ownerHash160: OWNER_HASH160, + }) + const parsed = parseBsv21LockingScript(hex) + expect(parsed).not.toBeNull() + expect(parsed!.id).toBe('deadbeef_3') + expect(parsed!.amt).toBe('123456789') + expect(parsed!.dec).toBe(8) + expect(parsed!.sym).toBe('TEST') + expect(parsed!.icon).toBe('icon_outpoint_xyz_0') + expect(parsed!.ownerHash160).toBe(OWNER_HASH160) + }) + + test('built script starts with the ord envelope opcodes', () => { + const hex = buildBsv21Transfer({ + payload: { id: 'abc_0', amt: '1' }, + ownerHash160: OWNER_HASH160, + }) + // 00 = OP_FALSE, 63 = OP_IF, 03 = push 3 bytes, 6f7264 = "ord" + expect(hex.startsWith('0063036f7264')).toBe(true) + }) + + test('built script ends with the recipient P2PKH (DUP HASH160 push EQUALVERIFY CHECKSIG)', () => { + const hex = buildBsv21Transfer({ + payload: { id: 'abc_0', amt: '1' }, + ownerHash160: OWNER_HASH160, + }) + // 68 = OP_ENDIF (closes ord envelope) + // 76 a9 14 88 ac = canonical P2PKH + expect(hex).toContain(`6876a914${OWNER_HASH160}88ac`) + expect(hex.endsWith(`76a914${OWNER_HASH160}88ac`)).toBe(true) + }) + + test('JSON payload uses fixed field order for reproducible bytes', () => { + // Two builds with the same inputs produce byte-identical scripts. + const a = buildBsv21Transfer({ + payload: { id: 'x_0', amt: '42', dec: 6, sym: 'X' }, + ownerHash160: OWNER_HASH160, + }) + const b = buildBsv21Transfer({ + payload: { id: 'x_0', amt: '42', dec: 6, sym: 'X' }, + ownerHash160: OWNER_HASH160, + }) + expect(a).toBe(b) + }) + + test('JSON payload encodes dec as a string, not a number', () => { + // The 1sat-stack go-templates/bsv21 decoder unmarshals the inscription + // body into map[string]string — a numeric `dec` (`"dec":6`) breaks the + // unmarshal and the topic-manager silently rejects the output. The + // canonical form is `"dec":"6"`. This test locks in the fix. + const hex = buildBsv21Transfer({ + payload: { id: 'x_0', amt: '42', dec: 6 }, + ownerHash160: OWNER_HASH160, + }) + // Find the JSON payload bytes inside the inscription envelope and + // assert the substring `"dec":"6"` is present (string form), not + // `"dec":6` (number form). + expect(hex).toContain( + Buffer.from('"dec":"6"', 'utf8').toString('hex'), + ) + expect(hex).not.toContain( + Buffer.from('"dec":6,', 'utf8').toString('hex'), + ) + }) + + test('JSON payload encodes content-type tag as OP_1 (0x51), not 0101', () => { + // 1sat-stack's go-templates/bsv21 + JungleBus auto-pickup both require + // canonical minimal-push encoding for the ord content-type tag. The + // non-minimal `01 01` form caused our outputs to be skipped entirely. + const hex = buildBsv21Transfer({ + payload: { id: 'abc_0', amt: '1' }, + ownerHash160: OWNER_HASH160, + }) + // The 'ord' push (`036f7264`) is immediately followed by the content- + // type tag. Canonical form: `036f7264 51 12...` (OP_1, then push of + // 18-byte "application/bsv-20"). Legacy non-canonical: `036f7264 0101 12...`. + expect(hex).toContain('036f72645112') + expect(hex).not.toContain('036f7264010112') + }) + + test('builder embeds the id verbatim — caller must pass underscore form', () => { + // Per BSV-21 spec, the transfer inscription's `id` field is + // `_` (UNDERSCORE), not the dot form used for outpoints. + // The builder doesn't normalize — it embeds whatever the caller + // passes. BSV21TransferService is the canonical normalization point; + // this test documents the contract. + const underscoreId = 'deadbeef_0' + const hex = buildBsv21Transfer({ + payload: { id: underscoreId, amt: '1' }, + ownerHash160: OWNER_HASH160, + }) + // The id appears in the JSON payload as `"id":"deadbeef_0"`. + const jsonFragment = Buffer.from(`"id":"${underscoreId}"`, 'utf8').toString('hex') + expect(hex).toContain(jsonFragment) + // And the dot form would be wrong — assert it's absent. + expect(hex).not.toContain( + Buffer.from('"id":"deadbeef.0"', 'utf8').toString('hex'), + ) + }) +}) + +describe('parseBsv21LockingScript rejection cases', () => { + test('non-string input returns null', () => { + expect(parseBsv21LockingScript(null as any)).toBeNull() + expect(parseBsv21LockingScript(undefined as any)).toBeNull() + expect(parseBsv21LockingScript(42 as any)).toBeNull() + }) + + test('empty / too-short scripts return null', () => { + expect(parseBsv21LockingScript('')).toBeNull() + expect(parseBsv21LockingScript('00')).toBeNull() + expect(parseBsv21LockingScript('00'.repeat(10))).toBeNull() + }) + + test('plain P2PKH (no ord envelope) returns null', () => { + // 76 a9 14 88 ac + const p2pkh = `76a914${OWNER_HASH160}88ac` + expect(parseBsv21LockingScript(p2pkh)).toBeNull() + }) + + test('ord envelope with non-BSV20 content-type returns null', () => { + // Build manually: OP_FALSE OP_IF push "ord" push 0x01 push "text/plain" OP_0 push "{}" OP_ENDIF + P2PKH + const hex = + '00' + + '63' + + '03' + '6f7264' + // "ord" + '01' + '01' + // field-id marker + '0a' + '746578742f706c61696e' + // "text/plain" (10 bytes) + '00' + // OP_0 separator + '02' + '7b7d' + // "{}" (2 bytes) + '68' + + `76a914${OWNER_HASH160}88ac` + expect(parseBsv21LockingScript(hex)).toBeNull() + }) + + test('ord envelope with invalid JSON returns null', () => { + // application/bsv-20 content type, but body is not JSON + const ct = Buffer.from('application/bsv-20', 'utf8').toString('hex') + const body = Buffer.from('not json', 'utf8').toString('hex') + const hex = + '00' + '63' + + '03' + '6f7264' + + '01' + '01' + + '12' + ct + + '00' + + body.length / 2 < 0x4c + ? (body.length / 2).toString(16).padStart(2, '0') + body + : '4c' + (body.length / 2).toString(16).padStart(2, '0') + body + // (Sloppy — just construct fully) + const bodyHex = Buffer.from('not json', 'utf8').toString('hex') + const fullHex = + '00' + '63' + + '03' + '6f7264' + + '01' + '01' + + '12' + ct + + '00' + + (bodyHex.length / 2).toString(16).padStart(2, '0') + bodyHex + + '68' + + `76a914${OWNER_HASH160}88ac` + expect(parseBsv21LockingScript(fullHex)).toBeNull() + }) + + test('ord envelope with JSON missing `p` field returns null', () => { + const ct = Buffer.from('application/bsv-20', 'utf8').toString('hex') + const bodyHex = Buffer.from('{"op":"transfer","amt":"1"}', 'utf8').toString('hex') + const fullHex = + '00' + '63' + + '03' + '6f7264' + + '01' + '01' + + '12' + ct + + '00' + + (bodyHex.length / 2).toString(16).padStart(2, '0') + bodyHex + + '68' + + `76a914${OWNER_HASH160}88ac` + expect(parseBsv21LockingScript(fullHex)).toBeNull() + }) +}) + +describe('parseBsv21LockingScript deploy+mint vs transfer', () => { + test('deploy+mint payloads have no id in JSON — parser surfaces empty id', () => { + // Mints don't carry `id` in the BSV-20 JSON; the outpoint IS the id. + // The parser's contract: return id='' when missing, callers resolve + // the canonical id from the outpoint. + const ct = Buffer.from('application/bsv-20', 'utf8').toString('hex') + const bodyHex = Buffer.from( + '{"p":"bsv-20","op":"deploy+mint","amt":"1000","dec":0,"sym":"NEW"}', + 'utf8', + ).toString('hex') + const fullHex = + '00' + '63' + + '03' + '6f7264' + + '01' + '01' + + '12' + ct + + '00' + + '4c' + (bodyHex.length / 2).toString(16).padStart(2, '0') + bodyHex + + '68' + + `76a914${OWNER_HASH160}88ac` + const parsed = parseBsv21LockingScript(fullHex) + expect(parsed).not.toBeNull() + expect(parsed!.id).toBe('') + expect(parsed!.amt).toBe('1000') + expect(parsed!.dec).toBe(0) + expect(parsed!.sym).toBe('NEW') + }) +}) diff --git a/test/tokens/dstas-transfer.test.ts b/test/tokens/dstas-transfer.test.ts new file mode 100644 index 0000000..eb5b074 --- /dev/null +++ b/test/tokens/dstas-transfer.test.ts @@ -0,0 +1,306 @@ +/** + * DSTAS transfer test surface (F3). + * + * Three layers exercised here: + * + * 1. **Parser propagation** — the extended `parseDstasLockingScript` + * now surfaces `optionalData`, `actionData` and `frozen` (required + * by the transfer flow to construct the new output's locking script + * correctly per DSTAS_SCRIPT_INVARIANTS.md §7). + * + * 2. **Unlock-script builder** — `buildDstasUnlockingScript` mirrors + * the SDK's `InputBuilder.sign` DSTAS branch. We exercise the + * byte-encoding primitives + the structural layout (preimage push, + * spending-type, sig push, pubkey push) so a future change can't + * silently drift from the SDK's expected witness shape. + * + * 3. **DstasTransferService source validation** — early rejection + * paths that don't require mocking wallet-toolbox (non-DSTAS + * source, frozen UTXO). A full happy-path test for the service + * would need a fake wallet implementing createAction/signAction — + * out of scope for this iteration; manual verification will cover + * the on-chain happy path. + */ + +import { describe, test, expect, vi } from 'vitest' +import { fromHex, toHex } from 'dxs-bsv-token-sdk/bsv' +import * as DstasLockingBuilderModule from 'dxs-bsv-token-sdk/script/build/dstas-locking-builder' +const { buildDstasLockingScript } = DstasLockingBuilderModule +import { parseDstasLockingScript } from '../../src/lib/services/stas/dstasParser' +import { buildDstasUnlockingScript } from '../../src/lib/services/tokens/dstas/buildDstasUnlockingScript' +import { DstasTransferService } from '../../src/lib/services/tokens/dstas/DstasTransferService' + +// 20-byte placeholders. +const OWNER_HASH160 = '11'.repeat(20) +const RECIPIENT_HASH160 = '33'.repeat(20) +const TOKEN_ID = 'ab'.repeat(20) + +function makeDstasScriptHex(opts: { + ownerHash160?: string + optionalData?: string[] +} = {}): string { + const z20 = new Uint8Array(20) + // `buildDstasLockingScript` is the full builder — it accepts + // optionalData and propagates it into the locking template + // (unlike `buildDstasLockingScriptForOwnerField` which hardcodes + // `optionalData: []`). + const lockingBytes = buildDstasLockingScript({ + ownerPkh: fromHex(opts.ownerHash160 ?? OWNER_HASH160), + redemptionPkh: fromHex(TOKEN_ID), + actionData: null, + frozen: false, + flags: new Uint8Array([0x03]), // freezable + confiscatable + serviceFields: [z20, z20], + optionalData: (opts.optionalData ?? []).map((s) => fromHex(s)), + }) + return toHex(lockingBytes) +} + +// ──────────────── Parser propagation ──────────────── + +describe('parseDstasLockingScript — extended fields for DSTAS send', () => { + test('surfaces optionalData when present (byte-exact)', () => { + const data = ['deadbeef', '1234'] + const hex = makeDstasScriptHex({ optionalData: data }) + const parsed = parseDstasLockingScript(hex) + expect(parsed).not.toBeNull() + expect(parsed!.optionalData).toEqual(data) + }) + + test('surfaces empty optionalData when absent', () => { + const hex = makeDstasScriptHex({ optionalData: [] }) + const parsed = parseDstasLockingScript(hex) + expect(parsed).not.toBeNull() + expect(parsed!.optionalData).toEqual([]) + }) + + test('exposes actionData + frozen flag (default unfrozen for fresh issue)', () => { + const hex = makeDstasScriptHex() + const parsed = parseDstasLockingScript(hex) + expect(parsed).not.toBeNull() + expect(parsed!.frozen).toBe(false) + expect(parsed!.actionData).toBeDefined() + }) +}) + +// ──────────────── Unlock-script builder ──────────────── + +/** + * Build a synthetic bsv-js Transaction with: + * - 1 DSTAS input (with prev-output attached) + * - 1 BSV funding input + * - 1 DSTAS output (recipient) + * - 1 P2PKH change output + * + * Enough structure to exercise the unlock builder's output-walk and + * funding-pointer logic without needing a real wallet. + */ +async function makeUnsignedTx(opts: { withChange?: boolean } = {}) { + const bsv: any = (await import('bsv')).default ?? (await import('bsv')) + const tx = new bsv.Transaction() + + // Build a real P2PKH locking script from a hash160 (bypassing base58 + // address parsing — we just need a script with the right shape). + function p2pkhHexForHash160(hex: string): string { + return '76a914' + hex + '88ac' + } + + // Input 0: DSTAS source (txid '11', vout 0). + const sourceScriptHex = makeDstasScriptHex() + tx.from({ + txId: '11'.repeat(32), + outputIndex: 0, + script: sourceScriptHex, + satoshis: 100, + }) + + // Input 1: BSV funding (txid '22', vout 1) — fake P2PKH for the + // funding owner. The actual locking script of the funding input + // doesn't matter to the unlock builder; only its outpoint pointers + // (txid + vout) are read. + tx.from({ + txId: '22'.repeat(32), + outputIndex: 1, + script: p2pkhHexForHash160('aa'.repeat(20)), + satoshis: 1000, + }) + + // Output 0: new DSTAS to recipient. + const recipientScriptHex = makeDstasScriptHex({ ownerHash160: RECIPIENT_HASH160 }) + tx.addOutput( + new bsv.Transaction.Output({ + script: bsv.Script.fromHex(recipientScriptHex), + satoshis: 100, + }), + ) + // Output 1 (optional): P2PKH change. + if (opts.withChange ?? true) { + tx.addOutput( + new bsv.Transaction.Output({ + script: bsv.Script.fromHex(p2pkhHexForHash160('bb'.repeat(20))), + satoshis: 800, + }), + ) + } + return { tx, sourceScriptHex, recipientScriptHex } +} + +describe('buildDstasUnlockingScript — DSTAS regular-spend witness', () => { + test('produces a well-formed unlock script with all required pushes', async () => { + const { tx } = await makeUnsignedTx() + // 73-byte placeholder DER signature, 33-byte compressed pubkey, + // 100-byte placeholder preimage. + const fakeSig = new Uint8Array(72).fill(0xab) + const fakePub = new Uint8Array(33) + fakePub[0] = 0x02 + const fakePreimage = new Uint8Array(50).fill(0xcd) + + const hex = buildDstasUnlockingScript({ + unsignedTx: tx, + inputIdx: 0, + fundingInputIdx: 1, + preimage: fakePreimage, + signatureDer: fakeSig, + publicKey: fakePub, + spendingType: 1, + }) + + // Sanity: the unlock script contains: + // - the preimage bytes (pushed somewhere mid-script) + // - the sig + sighash type byte (0x41) appended + // - the pubkey + // - the funding outpoint's reversed txid (`22` repeating) + const sigWithType = toHex(fakeSig) + '41' + expect(hex).toContain(sigWithType) + expect(hex).toContain(toHex(fakePub)) + expect(hex).toContain(toHex(fakePreimage)) + // Reversed funding txid '22' repeated. + expect(hex).toContain('2022' + '22'.repeat(31)) + }) + + test('emits OP_1..OP_16 for small-integer pushes (BSV minimality)', async () => { + // Regression for the production bug surfaced by the script evaluator + // ("data is not minimally encoded. PC: 6") on the first DSTAS send. + // scriptNumPush(1..16) must emit OP_1..OP_16 (0x51..0x60), NOT the + // data-push form `01 NN`. + // + // We walk the unlock script's push opcodes by length-decoding from + // the front and verify the funding-vout / spending-type slots — + // which fall at known positions in the SDK's layout — are OP_1 (0x51), + // not the non-minimal `01 01` form. + const { tx } = await makeUnsignedTx() // funding vout = 1, spending type = 1 + const fakeSig = new Uint8Array(72) + const fakePub = new Uint8Array(33) + fakePub[0] = 0x02 + const hex = buildDstasUnlockingScript({ + unsignedTx: tx, + inputIdx: 0, + fundingInputIdx: 1, + preimage: new Uint8Array(20), + signatureDer: fakeSig, + publicKey: fakePub, + spendingType: 1, + }) + const bytes = new Uint8Array(hex.match(/.{2}/g)!.map((b) => parseInt(b, 16))) + + // Walk pushes by opcode-decoding. For each, capture the opcode + payload. + type Push = { opcode: number; payloadLen: number; offset: number } + const pushes: Push[] = [] + let i = 0 + while (i < bytes.length) { + const op = bytes[i] + if (op === 0x00) { + pushes.push({ opcode: op, payloadLen: 0, offset: i }) + i += 1 + } else if (op >= 0x51 && op <= 0x60) { + // OP_1 .. OP_16 — single-byte numeric push, no payload. + pushes.push({ opcode: op, payloadLen: 0, offset: i }) + i += 1 + } else if (op >= 0x01 && op <= 0x4b) { + // Direct push of N bytes. + pushes.push({ opcode: op, payloadLen: op, offset: i }) + i += 1 + op + } else if (op === 0x4c) { + // OP_PUSHDATA1. + const len = bytes[i + 1] + pushes.push({ opcode: op, payloadLen: len, offset: i }) + i += 2 + len + } else if (op === 0x4d) { + const len = bytes[i + 1] | (bytes[i + 2] << 8) + pushes.push({ opcode: op, payloadLen: len, offset: i }) + i += 3 + len + } else { + throw new Error(`Unexpected opcode 0x${op.toString(16)} at offset ${i}`) + } + } + + // Per SDK layout for our makeUnsignedTx fixture (2 outputs, funding vout=1): + // push 0: sats(100=0x64) — direct push `01 64` + // push 1: recipient pkh (20 bytes) + // push 2: action-data OP_0 + // push 3: change sats (800) + // push 4: change pkh (20 bytes) + // push 5: OP_0 (no null-data) + // push 6: funding vout (=1) ← MUST be OP_1 (0x51), not `01 01` + // push 7: reversed funding txid (32 bytes) + // push 8: OP_0 (not merge) + // push 9: preimage (20 bytes) + // push 10: spending type (=1) ← MUST be OP_1 (0x51), not `01 01` + // push 11: sig + // push 12: pubkey + expect(pushes[6].opcode).toBe(0x51) // funding vout = OP_1 minimal + expect(pushes[10].opcode).toBe(0x51) // spending type = OP_1 minimal + }) + + test('emits OP_0 OP_0 when there is no P2PKH change output', async () => { + const { tx } = await makeUnsignedTx({ withChange: false }) + const fakeSig = new Uint8Array(72) + const fakePub = new Uint8Array(33) + fakePub[0] = 0x02 + const hex = buildDstasUnlockingScript({ + unsignedTx: tx, + inputIdx: 0, + fundingInputIdx: 1, + preimage: new Uint8Array(10), + signatureDer: fakeSig, + publicKey: fakePub, + spendingType: 1, + }) + // Two adjacent OP_0 bytes (the "no change" marker), followed by an + // OP_0 (the "no null-data" marker). Three OP_0 bytes in a row. + expect(hex).toContain('000000') + }) +}) + +// ──────────────── Service source-validation paths ──────────────── + +describe('DstasTransferService — source validation', () => { + function fakeWallet(): any { + return { + getPublicKey: vi.fn(), + createSignature: vi.fn(), + createAction: vi.fn(), + signAction: vi.fn(), + } + } + + test('rejects a non-DSTAS source script (no wallet calls made)', async () => { + const wallet = fakeWallet() + const svc = new DstasTransferService(wallet, 'test-identity', 'main') + const result = await svc.transfer({ + source: { + // P2PKH locking script — not DSTAS. + scriptHex: '76a914' + '11'.repeat(20) + '88ac', + txid: 'a'.repeat(64), + vout: 0, + satoshis: 100, + brc42KeyId: 'recv 1', + }, + recipientAddress: '1' + 'A'.repeat(33), + }) + expect(result.ok).toBe(false) + expect(result.reason).toMatch(/doesn't parse as DSTAS/i) + expect(wallet.getPublicKey).not.toHaveBeenCalled() + expect(wallet.createAction).not.toHaveBeenCalled() + }) +}) diff --git a/test/tokens/token-verification.test.ts b/test/tokens/token-verification.test.ts new file mode 100644 index 0000000..d3b4de4 --- /dev/null +++ b/test/tokens/token-verification.test.ts @@ -0,0 +1,128 @@ +/** + * TokenVerificationService tests — the caching + aggregation layer over B2G. + * + * The security-relevant invariants: a counterfeit output taints its card's + * badge, an `undetermined` never reads as verified, settled verdicts are cached + * (and `undetermined` ones are NOT — they must be retried), and the + * protocol→std mapping is right (`bsv-21` → `bsv21`). + */ + +import { describe, test, expect, vi, beforeEach } from 'vitest' +import { + TokenVerificationService, + aggregateBadge, + type OutpointVerification, +} from '../../src/lib/services/tokens/TokenVerificationService' + +// A stub B2G client we can drive per outpoint. +function stubClient(byTxid: Record) { + return { + verify: vi.fn(async (_std: string, txid: string, index: number) => { + const base = byTxid[txid] ?? { result: 'undetermined', reason: 'source-unavailable' } + return { outpoint: { txid, index }, ...base } + }), + } as any +} + +beforeEach(() => vi.clearAllMocks()) + +describe('aggregateBadge — worst verdict wins', () => { + const v = (result: string): OutpointVerification => ({ outpoint: 'x_0', result: result as any }) + test('all authentic → verified', () => { + expect(aggregateBadge([v('authentic'), v('authentic')])).toBe('verified') + }) + test('any counterfeit → counterfeit, even amid authentic', () => { + expect(aggregateBadge([v('authentic'), v('not-authentic')])).toBe('counterfeit') + }) + test('undetermined present, none counterfeit → unknown', () => { + expect(aggregateBadge([v('authentic'), v('undetermined')])).toBe('unknown') + }) + test('empty → unknown', () => { + expect(aggregateBadge([])).toBe('unknown') + }) +}) + +describe('verifyOutput — protocol→std mapping + shape', () => { + test('bsv-21 protocol maps to the bsv21 endpoint segment', async () => { + const client = stubClient({ tx1: { result: 'authentic', genesis: { txid: 'tx1', index: 0 }, genesisDepth: 0 } }) + const svc = new TokenVerificationService({ chain: 'main', client }) + await svc.verifyOutput({ txid: 'tx1', vout: 0, protocol: 'bsv-21' }) + expect(client.verify).toHaveBeenCalledWith('bsv21', 'tx1', 0, { expectedGenesis: undefined }) + }) + + test('maps genesis outpoint to the string form', async () => { + const client = stubClient({ tx1: { result: 'authentic', genesis: { txid: 'gen', index: 2 }, genesisDepth: 3 } }) + const svc = new TokenVerificationService({ chain: 'main', client }) + const r = await svc.verifyOutput({ txid: 'tx1', vout: 0, protocol: 'stas' }) + expect(r.genesis).toBe('gen_2') + expect(r.genesisDepth).toBe(3) + }) +}) + +describe('caching', () => { + test('a settled verdict is not re-fetched', async () => { + const client = stubClient({ tx1: { result: 'authentic', genesis: { txid: 'tx1', index: 0 } } }) + const svc = new TokenVerificationService({ chain: 'main', client }) + await svc.verifyOutput({ txid: 'tx1', vout: 0, protocol: 'stas' }) + await svc.verifyOutput({ txid: 'tx1', vout: 0, protocol: 'stas' }) + expect(client.verify).toHaveBeenCalledTimes(1) + }) + + test('an undetermined verdict IS retried (it means "unknown", not "no")', async () => { + const client = stubClient({ tx1: { result: 'undetermined', reason: 'source-unavailable' } }) + const svc = new TokenVerificationService({ chain: 'main', client }) + await svc.verifyOutput({ txid: 'tx1', vout: 0, protocol: 'stas' }) + await svc.verifyOutput({ txid: 'tx1', vout: 0, protocol: 'stas' }) + expect(client.verify).toHaveBeenCalledTimes(2) + }) + + test('force re-fetches a settled verdict (the explicit re-verify path)', async () => { + const client = stubClient({ tx1: { result: 'authentic', genesis: { txid: 'tx1', index: 0 } } }) + const svc = new TokenVerificationService({ chain: 'main', client }) + await svc.verifyOutput({ txid: 'tx1', vout: 0, protocol: 'stas' }) + await svc.verifyOutput({ txid: 'tx1', vout: 0, protocol: 'stas' }, { force: true }) + expect(client.verify).toHaveBeenCalledTimes(2) // cache bypassed only under force + }) + + test('seed() primes the cache from durable storage; a seeded outpoint is not re-fetched', async () => { + const client = stubClient({ good: { result: 'authentic', genesis: { txid: 'good', index: 0 } } }) + const svc = new TokenVerificationService({ chain: 'main', client }) + svc.seed([ + { + output: { txid: 'good', vout: 0, protocol: 'stas' }, + verdict: { outpoint: 'good_0', result: 'authentic', genesis: 'good_0' }, + }, + ]) + await svc.verifyOutput({ txid: 'good', vout: 0, protocol: 'stas' }) + expect(client.verify).not.toHaveBeenCalled() + }) + + test('seed() ignores undetermined verdicts (they must be re-verified)', async () => { + const client = stubClient({ pend: { result: 'authentic', genesis: { txid: 'pend', index: 0 } } }) + const svc = new TokenVerificationService({ chain: 'main', client }) + svc.seed([ + { + output: { txid: 'pend', vout: 0, protocol: 'stas' }, + verdict: { outpoint: 'pend_0', result: 'undetermined', reason: 'source-unavailable' }, + }, + ]) + await svc.verifyOutput({ txid: 'pend', vout: 0, protocol: 'stas' }) + expect(client.verify).toHaveBeenCalledTimes(1) // seed skipped it; had to fetch + }) +}) + +describe('verifyOutputs — batch', () => { + test('returns a map keyed by outpoint', async () => { + const client = stubClient({ + a: { result: 'authentic', genesis: { txid: 'a', index: 0 } }, + b: { result: 'not-authentic', reason: 'no-genesis' }, + }) + const svc = new TokenVerificationService({ chain: 'main', client }) + const m = await svc.verifyOutputs([ + { txid: 'a', vout: 0, protocol: 'stas' }, + { txid: 'b', vout: 1, protocol: 'dstas' }, + ]) + expect(m.get('a_0')?.result).toBe('authentic') + expect(m.get('b_1')?.result).toBe('not-authentic') + }) +}) diff --git a/test/tokens/verify-on-receive.test.ts b/test/tokens/verify-on-receive.test.ts new file mode 100644 index 0000000..5093bb3 --- /dev/null +++ b/test/tokens/verify-on-receive.test.ts @@ -0,0 +1,95 @@ +/** + * verifyAndPersistOnReceive tests. + * + * The receive-path hook: it must persist a settled verdict to the wallet DB via + * the stas:query IPC, skip `undetermined` (leave it for the load-time retry), + * map the protocol to the right endpoint segment, and — the safety contract — + * never throw into the receive path, even if verify or the IPC fails. + */ + +import { describe, test, expect, vi, beforeEach } from 'vitest' + +const verifyMock = vi.fn() +vi.mock('../../src/lib/services/tokens/woc/BackToGenesisClient', async (orig) => { + const mod: any = await orig() + return { ...mod, BackToGenesisClient: class { verify = verifyMock } } +}) + +const stasQueryMock = vi.fn() +vi.mock('../../src/lib/services/stas/stasIpc', () => ({ + stasQuery: (...args: any[]) => stasQueryMock(...args), +})) + +import { verifyAndPersistOnReceive } from '../../src/lib/services/tokens/verifyOnReceive' + +// The helper is fire-and-forget (returns void, work happens in a floating +// promise). Yield the microtask queue so the async body runs before asserting. +const flush = () => new Promise((r) => setTimeout(r, 0)) + +beforeEach(() => { + verifyMock.mockReset() + stasQueryMock.mockReset() + stasQueryMock.mockResolvedValue(undefined) +}) + +describe('verifyAndPersistOnReceive', () => { + test('persists a settled authentic verdict via upsertTokenVerification', async () => { + verifyMock.mockResolvedValueOnce({ + outpoint: { txid: 'aa', index: 0 }, + result: 'authentic', + genesis: { txid: 'gen', index: 2 }, + genesisDepth: 3, + }) + verifyAndPersistOnReceive('idk', 'main', { txid: 'aa', vout: 0, protocol: 'stas' }) + await flush() + + expect(verifyMock).toHaveBeenCalledWith('stas', 'aa', 0) + expect(stasQueryMock).toHaveBeenCalledTimes(1) + const [idk, chain, method, args] = stasQueryMock.mock.calls[0] + expect([idk, chain, method]).toEqual(['idk', 'main', 'upsertTokenVerification']) + expect(args[0]).toMatchObject({ + txid: 'aa', vout: 0, protocol: 'stas', result: 'authentic', + genesis: 'gen_2', genesisDepth: 3, reason: null, + }) + }) + + test('persists a counterfeit verdict with its reason', async () => { + verifyMock.mockResolvedValueOnce({ outpoint: { txid: 'bb', index: 1 }, result: 'not-authentic', reason: 'no-genesis' }) + verifyAndPersistOnReceive('idk', 'main', { txid: 'bb', vout: 1, protocol: 'dstas' }) + await flush() + expect(stasQueryMock.mock.calls[0][3][0]).toMatchObject({ + result: 'not-authentic', reason: 'no-genesis', genesis: null, + }) + }) + + test('does NOT persist an undetermined verdict (left for load-time retry)', async () => { + verifyMock.mockResolvedValueOnce({ outpoint: { txid: 'cc', index: 0 }, result: 'undetermined', reason: 'source-unavailable' }) + verifyAndPersistOnReceive('idk', 'main', { txid: 'cc', vout: 0, protocol: 'bsv-21' }) + await flush() + expect(stasQueryMock).not.toHaveBeenCalled() + }) + + test('maps bsv-21 protocol to the bsv21 endpoint segment', async () => { + verifyMock.mockResolvedValueOnce({ outpoint: { txid: 'dd', index: 0 }, result: 'authentic', genesis: { txid: 'dd', index: 0 }, genesisDepth: 0 }) + verifyAndPersistOnReceive('idk', 'test', { txid: 'dd', vout: 0, protocol: 'bsv-21' }) + await flush() + expect(verifyMock).toHaveBeenCalledWith('bsv21', 'dd', 0) + }) + + test('never throws into the receive path when verify rejects', async () => { + verifyMock.mockRejectedValueOnce(new Error('offline')) + // The call itself is synchronous (returns void); the rejection is swallowed + // inside the floating promise. Flushing must not surface an unhandled throw. + expect(() => verifyAndPersistOnReceive('idk', 'main', { txid: 'ee', vout: 0, protocol: 'stas' })).not.toThrow() + await flush() + expect(stasQueryMock).not.toHaveBeenCalled() + }) + + test('swallows a persistence (IPC) failure', async () => { + verifyMock.mockResolvedValueOnce({ outpoint: { txid: 'ff', index: 0 }, result: 'authentic', genesis: { txid: 'ff', index: 0 }, genesisDepth: 0 }) + stasQueryMock.mockRejectedValueOnce(new Error('ipc down')) + verifyAndPersistOnReceive('idk', 'main', { txid: 'ff', vout: 0, protocol: 'stas' }) + await flush() + expect(stasQueryMock).toHaveBeenCalledTimes(1) // attempted, failure swallowed + }) +}) diff --git a/test/tokens/woc-indexer.test.ts b/test/tokens/woc-indexer.test.ts new file mode 100644 index 0000000..218e6b4 --- /dev/null +++ b/test/tokens/woc-indexer.test.ts @@ -0,0 +1,123 @@ +/** + * WocTokenIndexerClient tests. + * + * This client is the single discovery source for STAS / DSTAS / BSV-21. A bug + * in its URL construction (wrong path, base58 where hash160 is required, a + * dropped `?script=true`) or its response mapping would silently break organic + * token receive. We pin: per-protocol URL + address format, the WocUtxo / + * IndexedOutput mapping, and fail-soft (404 → []). + */ + +import { describe, test, expect, vi, beforeEach } from 'vitest' + +// Mock the shared rate-limited fetch the client routes through. +const fetchMock = vi.fn() +vi.mock('../../src/lib/utils/RateLimitedFetch', () => ({ + wocFetch: { fetch: (...args: any[]) => fetchMock(...args) }, +})) + +import { WocTokenIndexerClient } from '../../src/lib/services/tokens/woc/WocTokenIndexerClient' + +const BASE = 'https://woc.test/v1/bsv/test' +const ok = (body: unknown) => ({ ok: true, json: async () => body }) +const notFound = () => ({ ok: false, status: 404, json: async () => ({}) }) + +function client() { + return new WocTokenIndexerClient({ baseUrl: BASE }) +} + +beforeEach(() => fetchMock.mockReset()) + +describe('STAS — getUtxosForAddresses', () => { + test('hits /address/{base58}/tokens/unspent?script=true and maps rows', async () => { + fetchMock.mockResolvedValueOnce( + ok({ utxos: [{ txid: 'aa', index: 2, satoshis: 100, script: 'deadbeef', symbol: 'X', tokenId: 'tok' }] }) + ) + const res = await client().getUtxosForAddresses(['1AddrBase58']) + expect(fetchMock).toHaveBeenCalledTimes(1) + expect(fetchMock.mock.calls[0][0]).toBe(`${BASE}/address/1AddrBase58/tokens/unspent?script=true`) + expect(res).toEqual([ + { address: '1AddrBase58', utxos: [{ txid: 'aa', vout: 2, value: 100, height: 1, symbol: 'X', redeemAddr: 'tok', scriptHex: 'deadbeef' }] }, + ]) + }) + + test('null/empty utxos → []', async () => { + fetchMock.mockResolvedValueOnce(ok({ address: '1A', utxos: null })) + const res = await client().getUtxosForAddresses(['1A']) + expect(res).toEqual([{ address: '1A', utxos: [] }]) + }) +}) + +describe('DSTAS — getDstasUtxosForOwners', () => { + test('keys on the raw hash160 (not base58) and maps satoshis→value, script→scriptHex', async () => { + const H160 = 'fcfad9b14f0cd788c548b4e14cdba715c31c0c08' + fetchMock.mockResolvedValueOnce( + ok({ address: H160, utxos: [{ txid: 'bb', index: 0, tokenId: H160, ownerHash160: H160, satoshis: 5, frozen: false, script: 'cafe' }] }) + ) + const res = await client().getDstasUtxosForOwners([H160]) + expect(fetchMock.mock.calls[0][0]).toBe(`${BASE}/address/${H160}/tokens/dstas/unspent?script=true`) + expect(res).toEqual([ + { ownerHash160: H160, utxos: [{ txid: 'bb', vout: 0, value: 5, height: 1, symbol: undefined, redeemAddr: H160, scriptHex: 'cafe' }] }, + ]) + }) + + test('404 (endpoint not yet on this network) → [] (fail-soft)', async () => { + fetchMock.mockResolvedValueOnce(notFound()) + const res = await client().getDstasUtxosForOwners(['abcd']) + expect(res).toEqual([{ ownerHash160: 'abcd', utxos: [] }]) + }) +}) + +describe('BSV-21 — getOwnedTxos', () => { + test('hits /token/bsv21/{addr}/unspent and maps to IndexedOutput with events', async () => { + fetchMock.mockResolvedValueOnce( + ok({ + tokens: [ + { + outpoint: 'cc_0', + vout: 0, + data: { bsv20: { id: 'cc_0', amt: 1000, sym: 'WOCB21' }, insc: { json: { dec: '2' } } }, + }, + ], + }) + ) + const res = await client().getOwnedTxos('1Addr') + expect(fetchMock.mock.calls[0][0]).toBe(`${BASE}/token/bsv21/1Addr/unspent?script=true`) + expect(res).toEqual([ + { outpoint: 'cc_0', id: 'cc_0', amt: '1000', dec: 2, sym: 'WOCB21', icon: undefined, events: ['bsv21'] }, + ]) + }) + + // Captured live from WOC mainnet (EXB21C, our test fleet). WOC's *decoded* + // bsv20 object spells the ticker `symbol`; only the raw inscription JSON uses + // `sym`. Reading `bsv20.sym` alone silently yielded an undefined ticker. + test('maps WOC mainnet shape: bsv20.symbol (not sym), amt as number, dec from insc', async () => { + fetchMock.mockResolvedValueOnce( + ok({ + tokens: [ + { + outpoint: 'c0f0ba_0', + vout: 0, + funderAddress: '13NpehPMQXHqrUQeVbv29tbiBsXGjMBESx', + data: { + bsv20: { amt: 10000, id: 'c0f0ba_0', op: 'deploy+mint', protocol: 'bsv-20', symbol: 'EXB21C' }, + insc: { json: { amt: '10000', dec: '0', op: 'deploy+mint', p: 'bsv-20', sym: 'EXB21C' } }, + }, + current: { txid: 'c0f0ba', blockHeight: 957666 }, + }, + ], + total_count: 1, + }) + ) + const res = await client().getOwnedTxos('13NpehPMQXHqrUQeVbv29tbiBsXGjMBESx') + expect(res).toEqual([ + { outpoint: 'c0f0ba_0', id: 'c0f0ba_0', amt: '10000', dec: 0, sym: 'EXB21C', icon: undefined, events: ['bsv21'] }, + ]) + }) + + test('network error → [] (fail-soft)', async () => { + fetchMock.mockRejectedValueOnce(new Error('offline')) + const res = await client().getOwnedTxos('1Addr') + expect(res).toEqual([]) + }) +}) diff --git a/vendor/dxs-bsv-token-sdk/README.md b/vendor/dxs-bsv-token-sdk/README.md new file mode 100644 index 0000000..2b0739a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/README.md @@ -0,0 +1,378 @@ +# dxs-bsv-token-sdk + +TypeScript SDK for building, reading, and validating Bitcoin SV transactions. + +This SDK implements the [official STAS 3.0 version](https://github.com/stassso/STAS-3-script-templates) through its DSTAS surface. + +The public surface is split into three entrypoints: + +- `dxs-bsv-token-sdk/dstas`: canonical Divisible STAS flow API +- `dxs-bsv-token-sdk/stas`: older STAS workflow helpers +- `dxs-bsv-token-sdk/bsv`: low-level blockchain primitives, script tooling, and transaction utilities + +Root imports expose only the `dstas`, `stas`, and `bsv` namespaces. + +## Install + +```bash +npm install dxs-bsv-token-sdk +``` + +## Choose your entrypoint + +Use the narrowest surface that matches your task. + +- `dxs-bsv-token-sdk/dstas` + Use for protocol-facing DSTAS flows: issue, transfer, split, merge, freeze, unfreeze, confiscation, swap, redeem. +- `dxs-bsv-token-sdk/stas` + Use for the older STAS transaction workflow. +- `dxs-bsv-token-sdk/bsv` + Use for low-level work: keys, addresses, scripts, transaction parsing, transaction building, and script evaluation. +- `dxs-bsv-token-sdk` + Use only if you explicitly want namespace aggregation for `dstas`, `stas`, and `bsv`. + +## Quickstart: DSTAS issue and transfer + +```ts +import { dstas } from "dxs-bsv-token-sdk/dstas"; +import { bsv } from "dxs-bsv-token-sdk/bsv"; + +const { + OutPoint, + PrivateKey, + TokenScheme, + TransactionReader, + fromHex, + toHex, + utf8ToBytes, +} = bsv; + +const issuer = new PrivateKey( + fromHex("b62fd57a07804f79291317261054eb9b19c9ccec49146c38b30a29d48636c368"), +); +const alice = new PrivateKey( + fromHex("77b1b7d5bfe1288d94f829baba86d503e1a06b571aaa5d36820be19ef2fe520e"), +); + +const scheme = new TokenScheme( + "Divisible STAS", + toHex(issuer.Address.Hash160), + "DSTAS", + 1, + { + isDivisible: true, + freeze: true, + confiscation: true, + freezeAuthority: { m: 1, publicKeys: [toHex(issuer.PublicKey)] }, + confiscationAuthority: { m: 1, publicKeys: [toHex(issuer.PublicKey)] }, + }, +); + +const fundingTx = TransactionReader.readHex(""); +const fundingOut = OutPoint.fromTransaction(fundingTx, 0); + +const { issueTxHex } = dstas.BuildDstasIssueTxs({ + fundingPayment: { OutPoint: fundingOut, Owner: issuer }, + scheme, + destinations: [{ Satoshis: 100, To: issuer.Address }], + feeRate: 0.1, +}); + +const issueTx = TransactionReader.readHex(issueTxHex); +const stasOut = OutPoint.fromTransaction(issueTx, 0); +const feeOut = OutPoint.fromTransaction(issueTx, 1); + +const transferTxHex = dstas.BuildDstasTransferTx({ + stasPayment: { OutPoint: stasOut, Owner: issuer }, + feePayment: { OutPoint: feeOut, Owner: issuer }, + destination: { Satoshis: 100, To: alice.Address }, + scheme, + note: [utf8ToBytes("DSTAS"), utf8ToBytes("transfer")], +}); +``` + +## High-level DSTAS APIs + +Use these first. + +### Single-flow builders + +`dxs-bsv-token-sdk/dstas` exports `BuildDstas*` helpers for individual transactions: + +- `BuildDstasIssueTxs` +- `BuildDstasTransferTx` +- `BuildDstasSplitTx` +- `BuildDstasMergeTx` +- `BuildDstasFreezeTx` +- `BuildDstasUnfreezeTx` +- `BuildDstasConfiscateTx` +- `BuildDstasRedeemTx` +- `BuildDstasSwapTx` + +These helpers are the right starting point when you already know the exact flow you need to build. + +### Multi-step planning with `DstasBundleFactory` + +Use `DstasBundleFactory` when you want the SDK to plan merge/split/service transactions for you. + +Typical use cases: + +- many-recipient payouts +- preparing UTXO sizes automatically +- chaining service transactions before final transfers +- building flows where intermediate DSTAS UTXOs must be reshaped before delivery + +```ts +import { dstas } from "dxs-bsv-token-sdk/dstas"; +import { bsv } from "dxs-bsv-token-sdk/bsv"; + +const { Address, LockingScriptReader, Transaction, Wallet, utf8ToBytes } = bsv; + +const { DstasBundleFactory, DstasSpendType } = dstas; + +const stasWallet = + Wallet.fromMnemonic("").deriveWallet("m/44'/236'/0'/0/0"); +const feeWallet = + Wallet.fromMnemonic("").deriveWallet("m/44'/236'/0'/0/1"); + +const getStasUtxoSet = async (minSats = 0) => { + return await fetchDstasUtxosForAddress(stasWallet.Address, minSats); +}; + +const getFundingUtxo = async ({ estimatedFeeSatoshis }) => { + return await fetchFeeUtxoForAddress(feeWallet.Address, estimatedFeeSatoshis); +}; + +const getTransactions = async ( + ids: string[], +): Promise> => { + return await fetchTransactionsByIds(ids); +}; + +const mapSpendTypeToCode = (spendType: DstasSpendType): number => { + if (spendType === "swap") return 4; + if (spendType === "confiscation") return 3; + if (spendType === "freeze" || spendType === "unfreeze") return 2; + return 1; +}; + +const factory = new DstasBundleFactory( + stasWallet, + feeWallet, + getFundingUtxo, + getStasUtxoSet, + getTransactions, + ({ fromOutPoint, recipient, spendType, isFreezeLike, isChange }) => { + const parsed = LockingScriptReader.read(fromOutPoint.LockingScript).Dstas; + if (!parsed) throw new Error("Expected DSTAS input locking script"); + if (recipient.m !== 1 || recipient.addresses.length !== 1) { + throw new Error("Example keeps recipient handling at m=1"); + } + + return { + owner: recipient.addresses[0].Hash160, + actionData: + spendType === "swap" && !isChange ? parsed.ActionDataRaw : null, + redemptionPkh: parsed.Redemption, + frozen: + spendType === "freeze" + ? true + : spendType === "unfreeze" + ? false + : isFreezeLike, + flags: parsed.Flags, + serviceFields: parsed.ServiceFields, + optionalData: parsed.OptionalData, + }; + }, + ({ txBuilder, inputIndex, spendType, isMerge }) => { + const input = txBuilder.Inputs[inputIndex]; + input.Merge = isMerge; + input.DstasSpendingType = mapSpendTypeToCode(spendType); + input.sign(true); + if (!input.UnlockingScript) { + throw new Error("Failed to build DSTAS unlocking script"); + } + return input.UnlockingScript; + }, +); + +const bundle = await factory.transfer({ + outputs: [ + { + recipient: { m: 1, addresses: [Address.fromBase58("")] }, + satoshis: 150, + }, + { + recipient: { m: 1, addresses: [Address.fromBase58("")] }, + satoshis: 200, + }, + ], + spendType: "transfer", + note: [utf8ToBytes("DSTAS"), utf8ToBytes("bundle transfer")], +}); +``` + +Notes: + +- `DstasBundleFactory` plans merge/split/transfer service transactions automatically. +- `note` is attached only to final transfer transaction(s), not to intermediate service transactions. +- `spendType` supports `transfer`, `freeze`, `unfreeze`, `confiscation`, and `swap`. + +## Low-level BSV toolkit + +Use `dxs-bsv-token-sdk/bsv` when you need direct blockchain primitives. + +Typical surface: + +- keys and wallets: `PrivateKey`, `Wallet` +- addressing: `Address` +- UTXOs: `OutPoint` +- transactions: `Transaction`, `TransactionReader`, `TransactionBuilder` +- script tooling: `ScriptBuilder`, `LockingScriptReader`, `evaluateTransactionHex` +- byte and hash helpers: `fromHex`, `toHex`, `utf8ToBytes`, `hash160`, `hash256` + +### Example: build a simple P2PKH transaction + +```ts +import { bsv } from "dxs-bsv-token-sdk/bsv"; + +const { + Address, + OutPoint, + PrivateKey, + ScriptType, + TransactionBuilder, + fromHex, +} = bsv; + +const pk = new PrivateKey( + fromHex("b62fd57a07804f79291317261054eb9b19c9ccec49146c38b30a29d48636c368"), +); +const from = pk.Address; +const to = Address.fromBase58("1MkvWa82XHFqmRHaiRZ8BqZS7Uc83wekjp"); +const lockingScript = fromHex( + "76a914e3b111de8fec527b41f4189e313638075d96ccd688ac", +); + +const utxo = new OutPoint( + "11".repeat(32), + 0, + lockingScript, + 10_000, + from, + ScriptType.p2pkh, +); + +const txHex = TransactionBuilder.init() + .addInput(utxo, pk) + .addP2PkhOutput(1_000, to) + .addChangeOutputWithFee(pk.Address, utxo.Satoshis - 1_000, 0.1) + .sign() + .toHex(); +``` + +## Older STAS workflow surface + +Use `dxs-bsv-token-sdk/stas` only when you need the older STAS flow helpers. + +```ts +import { stas } from "dxs-bsv-token-sdk/stas"; +import { bsv } from "dxs-bsv-token-sdk/bsv"; + +const { + Address, + OutPoint, + PrivateKey, + TokenScheme, + TransactionReader, + fromHex, + utf8ToBytes, +} = bsv; + +const issuer = new PrivateKey( + fromHex("b62fd57a07804f79291317261054eb9b19c9ccec49146c38b30a29d48636c368"), +); +const alice = new PrivateKey( + fromHex("77b1b7d5bfe1288d94f829baba86d503e1a06b571aaa5d36820be19ef2fe520e"), +); + +const tokenScheme = new TokenScheme( + "Token Name", + "e3b111de8fec527b41f4189e313638075d96ccd6", + "TokenSymbol", + 1, +); + +const prevTx = TransactionReader.readHex(""); +const stasOut = OutPoint.fromTransaction(prevTx, 0); +const feeOut = OutPoint.fromTransaction(prevTx, 1); + +const txHex = stas.BuildTransferTx({ + tokenScheme, + stasPayment: { OutPoint: stasOut, Owner: alice }, + feePayment: { OutPoint: feeOut, Owner: issuer }, + to: Address.fromBase58("1C2dVLqv1kjNn7pztpQ51bpXVEJfoWUNxe"), + note: [utf8ToBytes("DXS"), utf8ToBytes("Transfer test")], +}); +``` + +## Binary and data model rules + +- Public binary inputs and outputs are `Uint8Array`, not Node.js `Buffer`. +- `OutPoint` represents a spendable UTXO: txid, vout, locking script, satoshis, and owner address. +- `LockingScript` is the canonical property name in API objects. +- `OutPoint.TxId` is stored as big-endian hex and serialized little-endian inside transactions. + +## Security and strict mode + +Defaults already enabled: + +- deterministic ECDSA signing +- `lowS: true` +- `strictTxParse: true` +- `strictOutPointValidation: true` +- `strictFeeRateValidation: true` +- `strictScriptReader: true` +- `strictScriptEvaluation: true` +- strict script-eval max element size of `1024 * 1024` +- compressed secp256k1 multisig key validation with `n <= 5` + +Other checks remain opt-in because they are more compatibility-sensitive: + +- `strictPresetUnlockingScript` +- `strictMultisigKeys` + +```ts +import { bsv } from "dxs-bsv-token-sdk/bsv"; + +bsv.configureStrictMode({ + strictTxParse: true, + strictOutPointValidation: true, + strictFeeRateValidation: true, + strictPresetUnlockingScript: true, + strictMultisigKeys: true, + strictScriptReader: true, + strictScriptEvaluation: true, + maxFeeRateSatsPerByte: 5, + scriptEvaluationLimits: { + maxScriptSizeBytes: 100000, + maxOps: 50000, + maxStackDepth: 1000, + maxElementSizeBytes: 1024 * 1024, + }, +}); +``` + +## AI agent onboarding + +If you are integrating this SDK through an AI coding agent, start with: + +- `AGENTS.md` +- `docs/AGENT_RUNBOOK.md` +- `docs/DSTAS_SDK_SPEC.md` + +## Author + +- Author: [Oleg Panagushin](https://github.com/panagushin) + CTO / System Architect - Crypto & FinTech diff --git a/vendor/dxs-bsv-token-sdk/dist/base.d.ts b/vendor/dxs-bsv-token-sdk/dist/base.d.ts new file mode 100644 index 0000000..1f66641 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/base.d.ts @@ -0,0 +1,2 @@ +export declare const bs58check: import("@scure/base").BytesCoder; +//# sourceMappingURL=base.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/base.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/base.d.ts.map new file mode 100644 index 0000000..a7f4663 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/base.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,kCAA4B,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/base.js b/vendor/dxs-bsv-token-sdk/dist/base.js new file mode 100644 index 0000000..0fc6c97 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/base.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.bs58check = void 0; +const sha2_js_1 = require("@noble/hashes/sha2.js"); +const base_1 = require("@scure/base"); +exports.bs58check = (0, base_1.createBase58check)(sha2_js_1.sha256); +//# sourceMappingURL=base.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/base.js.map b/vendor/dxs-bsv-token-sdk/dist/base.js.map new file mode 100644 index 0000000..4e89482 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/base.js.map @@ -0,0 +1 @@ +{"version":3,"file":"base.js","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":";;;AAAA,mDAA+C;AAC/C,sCAAgD;AAEnC,QAAA,SAAS,GAAG,IAAA,wBAAiB,EAAC,gBAAM,CAAC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/binary.d.ts b/vendor/dxs-bsv-token-sdk/dist/binary.d.ts new file mode 100644 index 0000000..b2f52e1 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/binary.d.ts @@ -0,0 +1,30 @@ +import { Bytes } from "./bytes"; +export declare class ByteReader { + buffer: Bytes; + view: DataView; + offset: number; + constructor(buffer: Bytes, offset?: number); + readUInt8(): number; + readUInt16(): number; + readInt32(): number; + readUInt32(): number; + readUInt64(): number; + readVarInt(): number; + readChunk(n: number): Uint8Array; + readVarChunk(): Uint8Array; +} +export declare class ByteWriter { + buffer: Bytes; + view: DataView; + offset: number; + constructor(buffer: Bytes, offset?: number); + static fromSize: (size: number) => ByteWriter; + writeUInt8(value: number): void; + writeUInt16(value: number): void; + writeUInt32(value: number): void; + writeUInt64(value: number): void; + writeVarInt(value: number): void; + writeChunk(chunk: Bytes): void; + writeVarChunk(chunk: Bytes): void; +} +//# sourceMappingURL=binary.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/binary.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/binary.d.ts.map new file mode 100644 index 0000000..dcbc89b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/binary.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"binary.d.ts","sourceRoot":"","sources":["../src/binary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,qBAAa,UAAU;IACrB,MAAM,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;gBAEH,MAAM,EAAE,KAAK,EAAE,MAAM,SAAI;IAUrC,SAAS;IAMT,UAAU;IAMV,SAAS;IAMT,UAAU;IAMV,UAAU;IASV,UAAU;IAQV,SAAS,CAAC,CAAC,EAAE,MAAM;IAUnB,YAAY;CAGb;AAED,qBAAa,UAAU;IACrB,MAAM,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;gBAEH,MAAM,EAAE,KAAK,EAAE,MAAM,SAAI;IAUrC,MAAM,CAAC,QAAQ,GAAI,MAAM,MAAM,gBAA0C;IAEzE,UAAU,CAAC,KAAK,EAAE,MAAM;IAKxB,WAAW,CAAC,KAAK,EAAE,MAAM;IAKzB,WAAW,CAAC,KAAK,EAAE,MAAM;IAKzB,WAAW,CAAC,KAAK,EAAE,MAAM;IAWzB,WAAW,CAAC,KAAK,EAAE,MAAM;IAezB,UAAU,CAAC,KAAK,EAAE,KAAK;IAcvB,aAAa,CAAC,KAAK,EAAE,KAAK;CAI3B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/binary.js b/vendor/dxs-bsv-token-sdk/dist/binary.js new file mode 100644 index 0000000..46d3f7f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/binary.js @@ -0,0 +1,117 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ByteWriter = exports.ByteReader = void 0; +const buffer_utils_1 = require("./buffer/buffer-utils"); +class ByteReader { + constructor(buffer, offset = 0) { + this.buffer = buffer; + this.view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); + this.offset = offset; + } + readUInt8() { + const result = this.view.getUint8(this.offset); + this.offset += 1; + return result; + } + readUInt16() { + const result = this.view.getUint16(this.offset, true); + this.offset += 2; + return result; + } + readInt32() { + const result = this.view.getInt32(this.offset, true); + this.offset += 4; + return result; + } + readUInt32() { + const result = this.view.getUint32(this.offset, true); + this.offset += 4; + return result; + } + readUInt64() { + const a = this.view.getUint32(this.offset, true); + const b = this.view.getUint32(this.offset + 4, true); + const result = b * 0x100000000 + a; + (0, buffer_utils_1.ensureUInt)(result, 0x001fffffffffffff); + this.offset += 8; + return result; + } + readVarInt() { + const first = this.readUInt8(); + if (first < 0xfd) + return first; + if (first === 0xfd) + return this.readUInt16(); + if (first === 0xfe) + return this.readUInt32(); + return this.readUInt64(); + } + readChunk(n) { + if (this.buffer.length < this.offset + n) + throw new Error("Cannot read chunk out of bounds"); + const result = this.buffer.slice(this.offset, this.offset + n); + this.offset += n; + return result; + } + readVarChunk() { + return this.readChunk(this.readVarInt()); + } +} +exports.ByteReader = ByteReader; +class ByteWriter { + constructor(buffer, offset = 0) { + this.buffer = buffer; + this.view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); + this.offset = offset; + } + writeUInt8(value) { + this.view.setUint8(this.offset, value); + this.offset += 1; + } + writeUInt16(value) { + this.view.setUint16(this.offset, value, true); + this.offset += 2; + } + writeUInt32(value) { + this.view.setUint32(this.offset, value, true); + this.offset += 4; + } + writeUInt64(value) { + (0, buffer_utils_1.ensureUInt)(value, 0x001fffffffffffff); + const low = value & -1; + const high = Math.floor(value / 0x100000000); + this.view.setInt32(this.offset, low, true); + this.view.setUint32(this.offset + 4, high, true); + this.offset += 8; + } + writeVarInt(value) { + if (value <= 0xfc) { + this.writeUInt8(value); + } + else if (value <= 0xffff) { + this.writeUInt8(0xfd); + this.writeUInt16(value); + } + else if (value <= 0xffffffff) { + this.writeUInt8(0xfe); + this.writeUInt32(value); + } + else { + this.writeUInt8(0xff); + this.writeUInt64(value); + } + } + writeChunk(chunk) { + if (this.buffer.length < this.offset + chunk.length) + throw new Error(`Cannot writte chunk out of bounds; total size: ${this.buffer.length}; position: ${this.offset}; excess: ${this.offset + chunk.length - this.buffer.length}`); + this.buffer.set(chunk, this.offset); + this.offset += chunk.length; + } + writeVarChunk(chunk) { + this.writeVarInt(chunk.length); + this.writeChunk(chunk); + } +} +exports.ByteWriter = ByteWriter; +ByteWriter.fromSize = (size) => new ByteWriter(new Uint8Array(size)); +//# sourceMappingURL=binary.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/binary.js.map b/vendor/dxs-bsv-token-sdk/dist/binary.js.map new file mode 100644 index 0000000..a336e5f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/binary.js.map @@ -0,0 +1 @@ +{"version":3,"file":"binary.js","sourceRoot":"","sources":["../src/binary.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.d.ts new file mode 100644 index 0000000..6d6c5eb --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.d.ts @@ -0,0 +1,12 @@ +import { Bytes } from "../bytes"; +import { Network } from "./network"; +export declare class Address { + Value: string; + Hash160: Bytes; + Network: Network; + constructor(hash160: Bytes); + static fromBase58: (address: string) => Address; + static fromPublicKey: (publicKey: Bytes) => Address; + static fromHash160Hex: (hash160: string) => Address; +} +//# sourceMappingURL=address.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.d.ts.map new file mode 100644 index 0000000..3e0e778 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"address.d.ts","sourceRoot":"","sources":["../../src/bitcoin/address.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAW,MAAM,UAAU,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAY,MAAM,WAAW,CAAC;AAE9C,qBAAa,OAAO;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,OAAO,CAAoB;gBAKxB,OAAO,EAAE,KAAK;IAW1B,MAAM,CAAC,UAAU,GAAI,SAAS,MAAM,aASlC;IAEF,MAAM,CAAC,aAAa,GAAI,WAAW,KAAK,aACE;IAE1C,MAAM,CAAC,cAAc,GAAI,SAAS,MAAM,aAAmC;CAC5E"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.js new file mode 100644 index 0000000..b3fb28e --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Address = void 0; +const base_1 = require("../base"); +const bytes_1 = require("../bytes"); +const hashes_1 = require("../hashes"); +const network_1 = require("./network"); +class Address { + constructor(hash160) { + this.Network = network_1.Networks.Mainnet; + if (hash160.length !== 20) + throw new Error("Invalid hash160"); + const buffer = new Uint8Array(21); + buffer[0] = this.Network.pubKeyHash; + buffer.set(hash160, 1); + this.Value = base_1.bs58check.encode(buffer); + this.Hash160 = hash160; + } +} +exports.Address = Address; +Address.fromBase58 = (address) => { + const buffer = base_1.bs58check.decode(address); + if (buffer[0] !== network_1.Networks.Mainnet.pubKeyHash) + throw new Error("Only mainnet supported"); + const hash160 = buffer.subarray(1); + return new Address(hash160); +}; +Address.fromPublicKey = (publicKey) => new Address((0, hashes_1.hash160)(publicKey)); +Address.fromHash160Hex = (hash160) => new Address((0, bytes_1.fromHex)(hash160)); +//# sourceMappingURL=address.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.js.map new file mode 100644 index 0000000..17c6f54 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/address.js.map @@ -0,0 +1 @@ +{"version":3,"file":"address.js","sourceRoot":"","sources":["../../src/bitcoin/address.ts"],"names":[],"mappings":";;;AAAA,kCAAoC;AACpC,oCAA0C;AAC1C,sCAAuD;AACvD,uCAA8C;AAE9C,MAAa,OAAO;IAQlB,YAAY,OAAc;QAL1B,YAAO,GAAY,kBAAQ,CAAC,OAAO,CAAC;QAMlC,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAE9D,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAEvB,IAAI,CAAC,KAAK,GAAG,gBAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;;AAjBH,0BAkCC;AAfQ,kBAAU,GAAG,CAAC,OAAe,EAAE,EAAE;IACtC,MAAM,MAAM,GAAG,gBAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEzC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,kBAAQ,CAAC,OAAO,CAAC,UAAU;QAC3C,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEnC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC,AATgB,CASf;AAEK,qBAAa,GAAG,CAAC,SAAgB,EAAE,EAAE,CAC1C,IAAI,OAAO,CAAC,IAAA,gBAAe,EAAC,SAAS,CAAC,CAAC,AADrB,CACsB;AAEnC,sBAAc,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,IAAA,eAAO,EAAC,OAAO,CAAC,CAAC,AAArD,CAAsD"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.d.ts new file mode 100644 index 0000000..5a64ba4 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.d.ts @@ -0,0 +1,8 @@ +import { Address } from "./address"; +import { Bytes } from "../bytes"; +export type TDestination = { + Address: Address; + Satoshis: number; + Data?: Bytes[]; +}; +//# sourceMappingURL=destination.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.d.ts.map new file mode 100644 index 0000000..bee0e8c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"destination.d.ts","sourceRoot":"","sources":["../../src/bitcoin/destination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;CAChB,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.js new file mode 100644 index 0000000..d290050 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=destination.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.js.map new file mode 100644 index 0000000..21c25ec --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/destination.js.map @@ -0,0 +1 @@ +{"version":3,"file":"destination.js","sourceRoot":"","sources":["../../src/bitcoin/destination.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.d.ts new file mode 100644 index 0000000..d3b19b8 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.d.ts @@ -0,0 +1,16 @@ +export * from "./address"; +export * from "./destination"; +export * from "./mnemonic"; +export * from "./network"; +export * from "./op-codes"; +export * from "./out-point"; +export * from "./payment"; +export * from "./private-key"; +export * from "./script-type"; +export * from "./sig-hash-type"; +export * from "./token-scheme"; +export * from "./transaction-input"; +export * from "./transaction-output"; +export * from "./transaction"; +export * from "./wallet"; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.d.ts.map new file mode 100644 index 0000000..8b5c418 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bitcoin/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.js new file mode 100644 index 0000000..537c38e --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.js @@ -0,0 +1,32 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./address"), exports); +__exportStar(require("./destination"), exports); +__exportStar(require("./mnemonic"), exports); +__exportStar(require("./network"), exports); +__exportStar(require("./op-codes"), exports); +__exportStar(require("./out-point"), exports); +__exportStar(require("./payment"), exports); +__exportStar(require("./private-key"), exports); +__exportStar(require("./script-type"), exports); +__exportStar(require("./sig-hash-type"), exports); +__exportStar(require("./token-scheme"), exports); +__exportStar(require("./transaction-input"), exports); +__exportStar(require("./transaction-output"), exports); +__exportStar(require("./transaction"), exports); +__exportStar(require("./wallet"), exports); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.js.map new file mode 100644 index 0000000..9d752f6 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bitcoin/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,gDAA8B;AAC9B,6CAA2B;AAC3B,4CAA0B;AAC1B,6CAA2B;AAC3B,8CAA4B;AAC5B,4CAA0B;AAC1B,gDAA8B;AAC9B,gDAA8B;AAC9B,kDAAgC;AAChC,iDAA+B;AAC/B,sDAAoC;AACpC,uDAAqC;AACrC,gDAA8B;AAC9B,2CAAyB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.d.ts new file mode 100644 index 0000000..c004f56 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.d.ts @@ -0,0 +1,15 @@ +export { wordlist } from "@scure/bip39/wordlists/english.js"; +export type TWords = { + [idxs: string]: string; +}; +export declare class Mnemonic { + phrase: string; + words: TWords; + constructor(phrase: string, words: TWords); + static generate: () => Mnemonic; + private static sanitize; + static fromWords: (words: TWords) => Mnemonic; + static fromPhrase: (phrase: string) => Mnemonic; + static fromRandomText: (text: string) => Mnemonic | undefined; +} +//# sourceMappingURL=mnemonic.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.d.ts.map new file mode 100644 index 0000000..85c53bd --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"mnemonic.d.ts","sourceRoot":"","sources":["../../src/bitcoin/mnemonic.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAE7D,MAAM,MAAM,MAAM,GAAG;IAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AAEhD,qBAAa,QAAQ;IAEV,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,MAAM;gBADb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM;IAGtB,OAAc,QAAQ,QAAO,QAAQ,CACkB;IAEvD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAIX;IAEZ,OAAc,SAAS,GAAI,OAAO,MAAM,KAAG,QAAQ,CAOjD;IAEF,OAAc,UAAU,GAAI,QAAQ,MAAM,KAAG,QAAQ,CAUnD;IAEF,OAAc,cAAc,GAAI,MAAM,MAAM,KAAG,QAAQ,GAAG,SAAS,CAWjE;CACH"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.js new file mode 100644 index 0000000..6e7f8bc --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Mnemonic = exports.wordlist = void 0; +const bip39_1 = require("@scure/bip39"); +const english_js_1 = require("@scure/bip39/wordlists/english.js"); +var english_js_2 = require("@scure/bip39/wordlists/english.js"); +Object.defineProperty(exports, "wordlist", { enumerable: true, get: function () { return english_js_2.wordlist; } }); +class Mnemonic { + constructor(phrase, words) { + this.phrase = phrase; + this.words = words; + } +} +exports.Mnemonic = Mnemonic; +Mnemonic.generate = () => Mnemonic.fromPhrase((0, bip39_1.generateMnemonic)(english_js_1.wordlist, 128)); +Mnemonic.sanitize = (value) => value + .replace(/\r?\n|\r/g, " ") + .replace(/\s{2,}/g, " ") + .trim(); +Mnemonic.fromWords = (words) => { + const orderedWords = Object.entries(words) + .sort((a, b) => Number(a[0]) - Number(b[0])) + .map(([, word]) => word); + const phrase = Mnemonic.sanitize(orderedWords.join(" ")); + return Mnemonic.fromPhrase(phrase); +}; +Mnemonic.fromPhrase = (phrase) => { + const sanitized = Mnemonic.sanitize(phrase); + const words = sanitized.split(" ").reduce((a, v, i) => { + a[`${i}`] = v; + return a; + }, {}); + return new Mnemonic(sanitized, words); +}; +Mnemonic.fromRandomText = (text) => { + const sanitized = Mnemonic.sanitize(text); + if (!sanitized) + return undefined; + try { + if ((0, bip39_1.validateMnemonic)(sanitized, english_js_1.wordlist)) + return Mnemonic.fromPhrase(sanitized); + } + catch (_a) { + return undefined; + } +}; +//# sourceMappingURL=mnemonic.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.js.map new file mode 100644 index 0000000..832fc60 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/mnemonic.js.map @@ -0,0 +1 @@ +{"version":3,"file":"mnemonic.js","sourceRoot":"","sources":["../../src/bitcoin/mnemonic.ts"],"names":[],"mappings":";;;AAAA,wCAAkE;AAClE,kEAA6D;AAE7D,gEAA6D;AAApD,sGAAA,QAAQ,OAAA;AAIjB,MAAa,QAAQ;IACnB,YACS,MAAc,EACd,KAAa;QADb,WAAM,GAAN,MAAM,CAAQ;QACd,UAAK,GAAL,KAAK,CAAQ;IACnB,CAAC;;AAJN,4BAgDC;AA1Ce,iBAAQ,GAAG,GAAa,EAAE,CACtC,QAAQ,CAAC,UAAU,CAAC,IAAA,wBAAgB,EAAC,qBAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;AAExC,iBAAQ,GAAG,CAAC,KAAa,EAAU,EAAE,CAClD,KAAK;KACF,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;KACzB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;KACvB,IAAI,EAAE,CAAC;AAEE,kBAAS,GAAG,CAAC,KAAa,EAAY,EAAE;IACpD,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SACvC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3C,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAEzD,OAAO,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC,CAAC;AAEY,mBAAU,GAAG,CAAC,MAAc,EAAY,EAAE;IACtD,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE5C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;QAC5D,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QAEd,OAAO,CAAC,CAAC;IACX,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,IAAI,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACxC,CAAC,CAAC;AAEY,uBAAc,GAAG,CAAC,IAAY,EAAwB,EAAE;IACpE,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE1C,IAAI,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IAEjC,IAAI,CAAC;QACH,IAAI,IAAA,wBAAgB,EAAC,SAAS,EAAE,qBAAQ,CAAC;YACvC,OAAO,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.d.ts new file mode 100644 index 0000000..752578d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.d.ts @@ -0,0 +1,8 @@ +export type Network = { + pubKeyHash: number; + wif: number; +}; +export declare const Networks: { + [name: string]: Network; +}; +//# sourceMappingURL=network.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.d.ts.map new file mode 100644 index 0000000..476477a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/bitcoin/network.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE;IAAE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAK/C,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.js new file mode 100644 index 0000000..60b5da9 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Networks = void 0; +exports.Networks = { + Mainnet: { + pubKeyHash: 0x00, + wif: 0x80, + }, +}; +//# sourceMappingURL=network.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.js.map new file mode 100644 index 0000000..694338e --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/network.js.map @@ -0,0 +1 @@ +{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/bitcoin/network.ts"],"names":[],"mappings":";;;AAKa,QAAA,QAAQ,GAAgC;IACnD,OAAO,EAAE;QACP,UAAU,EAAE,IAAI;QAChB,GAAG,EAAE,IAAI;KACV;CACF,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.d.ts new file mode 100644 index 0000000..1bda393 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.d.ts @@ -0,0 +1,123 @@ +export declare enum OpCode { + OP_0 = 0, + OP_PUSHDATA1 = 76, + OP_PUSHDATA2 = 77, + OP_PUSHDATA4 = 78, + OP_1NEGATE = 79, + OP_RESERVED = 80, + OP_TRUE = 81, + OP_1 = 81, + OP_2 = 82, + OP_3 = 83, + OP_4 = 84, + OP_5 = 85, + OP_6 = 86, + OP_7 = 87, + OP_8 = 88, + OP_9 = 89, + OP_10 = 90, + OP_11 = 91, + OP_12 = 92, + OP_13 = 93, + OP_14 = 94, + OP_15 = 95, + OP_16 = 96, + OP_NOP = 97, + OP_VER = 98, + OP_IF = 99, + OP_NOTIF = 100, + OP_VERIF = 101, + OP_VERNOTIF = 102, + OP_ELSE = 103, + OP_ENDIF = 104, + OP_VERIFY = 105, + OP_RETURN = 106, + OP_TOALTSTACK = 107, + OP_FROMALTSTACK = 108, + OP_2DROP = 109, + OP_2DUP = 110, + OP_3DUP = 111, + OP_2OVER = 112, + OP_2ROT = 113, + OP_2SWAP = 114, + OP_IFDUP = 115, + OP_DEPTH = 116, + OP_DROP = 117, + OP_DUP = 118, + OP_NIP = 119, + OP_OVER = 120, + OP_PICK = 121, + OP_ROLL = 122, + OP_ROT = 123, + OP_SWAP = 124, + OP_TUCK = 125, + OP_CAT = 126, + OP_SPLIT = 127, + OP_NUM2BIN = 128, + OP_BIN2NUM = 129, + OP_SIZE = 130, + OP_INVERT = 131, + OP_AND = 132, + OP_OR = 133, + OP_XOR = 134, + OP_EQUAL = 135, + OP_EQUALVERIFY = 136, + OP_RESERVED1 = 137, + OP_RESERVED2 = 138, + OP_1ADD = 139, + OP_1SUB = 140, + OP_2MUL = 141, + OP_2DIV = 142, + OP_NEGATE = 143, + OP_ABS = 144, + OP_NOT = 145, + OP_0NOTEQUAL = 146, + OP_ADD = 147, + OP_SUB = 148, + OP_MUL = 149, + OP_DIV = 150, + OP_MOD = 151, + OP_LSHIFT = 152, + OP_RSHIFT = 153, + OP_BOOLAND = 154, + OP_BOOLOR = 155, + OP_NUMEQUAL = 156, + OP_NUMEQUALVERIFY = 157, + OP_NUMNOTEQUAL = 158, + OP_LESSTHAN = 159, + OP_GREATERTHAN = 160, + OP_LESSTHANOREQUAL = 161, + OP_GREATERTHANOREQUAL = 162, + OP_MIN = 163, + OP_MAX = 164, + OP_WITHIN = 165, + OP_RIPEMD160 = 166, + OP_SHA1 = 167, + OP_SHA256 = 168, + OP_HASH160 = 169, + OP_HASH256 = 170, + OP_CODESEPARATOR = 171, + OP_CHECKSIG = 172, + OP_CHECKSIGVERIFY = 173, + OP_CHECKMULTISIG = 174, + OP_CHECKMULTISIGVERIFY = 175, + OP_NOP1 = 176, + OP_NOP2 = 177, + OP_CHECKLOCKTIMEVERIFY = 177, + OP_NOP3 = 178, + OP_CHECKSEQUENCEVERIFY = 178, + OP_NOP4 = 179, + OP_NOP5 = 180, + OP_NOP6 = 181, + OP_NOP7 = 182, + OP_NOP8 = 183, + OP_NOP9 = 184, + OP_NOP10 = 185, + OP_SMALLDATA = 249, + OP_SMALLINTEGER = 250, + OP_PUBKEYS = 251, + OP_PUBKEYHASH = 253, + OP_PUBKEY = 254, + OP_INVALIDOPCODE = 255 +} +//# sourceMappingURL=op-codes.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.d.ts.map new file mode 100644 index 0000000..edad338 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"op-codes.d.ts","sourceRoot":"","sources":["../../src/bitcoin/op-codes.ts"],"names":[],"mappings":"AAAA,oBAAY,MAAM;IAEhB,IAAI,IAAO;IACX,YAAY,KAAO;IACnB,YAAY,KAAO;IACnB,YAAY,KAAO;IACnB,UAAU,KAAO;IACjB,WAAW,KAAO;IAClB,OAAO,KAAO;IACd,IAAI,KAAO;IACX,IAAI,KAAO;IACX,IAAI,KAAO;IACX,IAAI,KAAO;IACX,IAAI,KAAO;IACX,IAAI,KAAO;IACX,IAAI,KAAO;IACX,IAAI,KAAO;IACX,IAAI,KAAO;IACX,KAAK,KAAO;IACZ,KAAK,KAAO;IACZ,KAAK,KAAO;IACZ,KAAK,KAAO;IACZ,KAAK,KAAO;IACZ,KAAK,KAAO;IACZ,KAAK,KAAO;IAGZ,MAAM,KAAO;IACb,MAAM,KAAO;IACb,KAAK,KAAO;IACZ,QAAQ,MAAO;IACf,QAAQ,MAAO;IACf,WAAW,MAAO;IAClB,OAAO,MAAO;IACd,QAAQ,MAAO;IACf,SAAS,MAAO;IAChB,SAAS,MAAO;IAGhB,aAAa,MAAO;IACpB,eAAe,MAAO;IACtB,QAAQ,MAAO;IACf,OAAO,MAAO;IACd,OAAO,MAAO;IACd,QAAQ,MAAO;IACf,OAAO,MAAO;IACd,QAAQ,MAAO;IACf,QAAQ,MAAO;IACf,QAAQ,MAAO;IACf,OAAO,MAAO;IACd,MAAM,MAAO;IACb,MAAM,MAAO;IACb,OAAO,MAAO;IACd,OAAO,MAAO;IACd,OAAO,MAAO;IACd,MAAM,MAAO;IACb,OAAO,MAAO;IACd,OAAO,MAAO;IAGd,MAAM,MAAO;IACb,QAAQ,MAAO;IACf,UAAU,MAAO;IACjB,UAAU,MAAO;IACjB,OAAO,MAAO;IAGd,SAAS,MAAO;IAChB,MAAM,MAAO;IACb,KAAK,MAAO;IACZ,MAAM,MAAO;IACb,QAAQ,MAAO;IACf,cAAc,MAAO;IACrB,YAAY,MAAO;IACnB,YAAY,MAAO;IAGnB,OAAO,MAAO;IACd,OAAO,MAAO;IACd,OAAO,MAAO;IACd,OAAO,MAAO;IACd,SAAS,MAAO;IAChB,MAAM,MAAO;IACb,MAAM,MAAO;IACb,YAAY,MAAO;IAEnB,MAAM,MAAO;IACb,MAAM,MAAO;IACb,MAAM,MAAO;IACb,MAAM,MAAO;IACb,MAAM,MAAO;IACb,SAAS,MAAO;IAChB,SAAS,MAAO;IAEhB,UAAU,MAAO;IACjB,SAAS,MAAO;IAChB,WAAW,MAAO;IAClB,iBAAiB,MAAO;IACxB,cAAc,MAAO;IACrB,WAAW,MAAO;IAClB,cAAc,MAAO;IACrB,kBAAkB,MAAO;IACzB,qBAAqB,MAAO;IAC5B,MAAM,MAAO;IACb,MAAM,MAAO;IAEb,SAAS,MAAO;IAGhB,YAAY,MAAO;IACnB,OAAO,MAAO;IACd,SAAS,MAAO;IAChB,UAAU,MAAO;IACjB,UAAU,MAAO;IACjB,gBAAgB,MAAO;IACvB,WAAW,MAAO;IAClB,iBAAiB,MAAO;IACxB,gBAAgB,MAAO;IACvB,sBAAsB,MAAO;IAG7B,OAAO,MAAO;IACd,OAAO,MAAO;IACd,sBAAsB,MAAO;IAC7B,OAAO,MAAO;IACd,sBAAsB,MAAO;IAC7B,OAAO,MAAO;IACd,OAAO,MAAO;IACd,OAAO,MAAO;IACd,OAAO,MAAO;IACd,OAAO,MAAO;IACd,OAAO,MAAO;IACd,QAAQ,MAAO;IAGf,YAAY,MAAO;IACnB,eAAe,MAAO;IACtB,UAAU,MAAO;IACjB,aAAa,MAAO;IACpB,SAAS,MAAO;IAEhB,gBAAgB,MAAO;CACxB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.js new file mode 100644 index 0000000..72cbc6a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.js @@ -0,0 +1,127 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.OpCode = void 0; +var OpCode; +(function (OpCode) { + OpCode[OpCode["OP_0"] = 0] = "OP_0"; + OpCode[OpCode["OP_PUSHDATA1"] = 76] = "OP_PUSHDATA1"; + OpCode[OpCode["OP_PUSHDATA2"] = 77] = "OP_PUSHDATA2"; + OpCode[OpCode["OP_PUSHDATA4"] = 78] = "OP_PUSHDATA4"; + OpCode[OpCode["OP_1NEGATE"] = 79] = "OP_1NEGATE"; + OpCode[OpCode["OP_RESERVED"] = 80] = "OP_RESERVED"; + OpCode[OpCode["OP_TRUE"] = 81] = "OP_TRUE"; + OpCode[OpCode["OP_1"] = 81] = "OP_1"; + OpCode[OpCode["OP_2"] = 82] = "OP_2"; + OpCode[OpCode["OP_3"] = 83] = "OP_3"; + OpCode[OpCode["OP_4"] = 84] = "OP_4"; + OpCode[OpCode["OP_5"] = 85] = "OP_5"; + OpCode[OpCode["OP_6"] = 86] = "OP_6"; + OpCode[OpCode["OP_7"] = 87] = "OP_7"; + OpCode[OpCode["OP_8"] = 88] = "OP_8"; + OpCode[OpCode["OP_9"] = 89] = "OP_9"; + OpCode[OpCode["OP_10"] = 90] = "OP_10"; + OpCode[OpCode["OP_11"] = 91] = "OP_11"; + OpCode[OpCode["OP_12"] = 92] = "OP_12"; + OpCode[OpCode["OP_13"] = 93] = "OP_13"; + OpCode[OpCode["OP_14"] = 94] = "OP_14"; + OpCode[OpCode["OP_15"] = 95] = "OP_15"; + OpCode[OpCode["OP_16"] = 96] = "OP_16"; + OpCode[OpCode["OP_NOP"] = 97] = "OP_NOP"; + OpCode[OpCode["OP_VER"] = 98] = "OP_VER"; + OpCode[OpCode["OP_IF"] = 99] = "OP_IF"; + OpCode[OpCode["OP_NOTIF"] = 100] = "OP_NOTIF"; + OpCode[OpCode["OP_VERIF"] = 101] = "OP_VERIF"; + OpCode[OpCode["OP_VERNOTIF"] = 102] = "OP_VERNOTIF"; + OpCode[OpCode["OP_ELSE"] = 103] = "OP_ELSE"; + OpCode[OpCode["OP_ENDIF"] = 104] = "OP_ENDIF"; + OpCode[OpCode["OP_VERIFY"] = 105] = "OP_VERIFY"; + OpCode[OpCode["OP_RETURN"] = 106] = "OP_RETURN"; + OpCode[OpCode["OP_TOALTSTACK"] = 107] = "OP_TOALTSTACK"; + OpCode[OpCode["OP_FROMALTSTACK"] = 108] = "OP_FROMALTSTACK"; + OpCode[OpCode["OP_2DROP"] = 109] = "OP_2DROP"; + OpCode[OpCode["OP_2DUP"] = 110] = "OP_2DUP"; + OpCode[OpCode["OP_3DUP"] = 111] = "OP_3DUP"; + OpCode[OpCode["OP_2OVER"] = 112] = "OP_2OVER"; + OpCode[OpCode["OP_2ROT"] = 113] = "OP_2ROT"; + OpCode[OpCode["OP_2SWAP"] = 114] = "OP_2SWAP"; + OpCode[OpCode["OP_IFDUP"] = 115] = "OP_IFDUP"; + OpCode[OpCode["OP_DEPTH"] = 116] = "OP_DEPTH"; + OpCode[OpCode["OP_DROP"] = 117] = "OP_DROP"; + OpCode[OpCode["OP_DUP"] = 118] = "OP_DUP"; + OpCode[OpCode["OP_NIP"] = 119] = "OP_NIP"; + OpCode[OpCode["OP_OVER"] = 120] = "OP_OVER"; + OpCode[OpCode["OP_PICK"] = 121] = "OP_PICK"; + OpCode[OpCode["OP_ROLL"] = 122] = "OP_ROLL"; + OpCode[OpCode["OP_ROT"] = 123] = "OP_ROT"; + OpCode[OpCode["OP_SWAP"] = 124] = "OP_SWAP"; + OpCode[OpCode["OP_TUCK"] = 125] = "OP_TUCK"; + OpCode[OpCode["OP_CAT"] = 126] = "OP_CAT"; + OpCode[OpCode["OP_SPLIT"] = 127] = "OP_SPLIT"; + OpCode[OpCode["OP_NUM2BIN"] = 128] = "OP_NUM2BIN"; + OpCode[OpCode["OP_BIN2NUM"] = 129] = "OP_BIN2NUM"; + OpCode[OpCode["OP_SIZE"] = 130] = "OP_SIZE"; + OpCode[OpCode["OP_INVERT"] = 131] = "OP_INVERT"; + OpCode[OpCode["OP_AND"] = 132] = "OP_AND"; + OpCode[OpCode["OP_OR"] = 133] = "OP_OR"; + OpCode[OpCode["OP_XOR"] = 134] = "OP_XOR"; + OpCode[OpCode["OP_EQUAL"] = 135] = "OP_EQUAL"; + OpCode[OpCode["OP_EQUALVERIFY"] = 136] = "OP_EQUALVERIFY"; + OpCode[OpCode["OP_RESERVED1"] = 137] = "OP_RESERVED1"; + OpCode[OpCode["OP_RESERVED2"] = 138] = "OP_RESERVED2"; + OpCode[OpCode["OP_1ADD"] = 139] = "OP_1ADD"; + OpCode[OpCode["OP_1SUB"] = 140] = "OP_1SUB"; + OpCode[OpCode["OP_2MUL"] = 141] = "OP_2MUL"; + OpCode[OpCode["OP_2DIV"] = 142] = "OP_2DIV"; + OpCode[OpCode["OP_NEGATE"] = 143] = "OP_NEGATE"; + OpCode[OpCode["OP_ABS"] = 144] = "OP_ABS"; + OpCode[OpCode["OP_NOT"] = 145] = "OP_NOT"; + OpCode[OpCode["OP_0NOTEQUAL"] = 146] = "OP_0NOTEQUAL"; + OpCode[OpCode["OP_ADD"] = 147] = "OP_ADD"; + OpCode[OpCode["OP_SUB"] = 148] = "OP_SUB"; + OpCode[OpCode["OP_MUL"] = 149] = "OP_MUL"; + OpCode[OpCode["OP_DIV"] = 150] = "OP_DIV"; + OpCode[OpCode["OP_MOD"] = 151] = "OP_MOD"; + OpCode[OpCode["OP_LSHIFT"] = 152] = "OP_LSHIFT"; + OpCode[OpCode["OP_RSHIFT"] = 153] = "OP_RSHIFT"; + OpCode[OpCode["OP_BOOLAND"] = 154] = "OP_BOOLAND"; + OpCode[OpCode["OP_BOOLOR"] = 155] = "OP_BOOLOR"; + OpCode[OpCode["OP_NUMEQUAL"] = 156] = "OP_NUMEQUAL"; + OpCode[OpCode["OP_NUMEQUALVERIFY"] = 157] = "OP_NUMEQUALVERIFY"; + OpCode[OpCode["OP_NUMNOTEQUAL"] = 158] = "OP_NUMNOTEQUAL"; + OpCode[OpCode["OP_LESSTHAN"] = 159] = "OP_LESSTHAN"; + OpCode[OpCode["OP_GREATERTHAN"] = 160] = "OP_GREATERTHAN"; + OpCode[OpCode["OP_LESSTHANOREQUAL"] = 161] = "OP_LESSTHANOREQUAL"; + OpCode[OpCode["OP_GREATERTHANOREQUAL"] = 162] = "OP_GREATERTHANOREQUAL"; + OpCode[OpCode["OP_MIN"] = 163] = "OP_MIN"; + OpCode[OpCode["OP_MAX"] = 164] = "OP_MAX"; + OpCode[OpCode["OP_WITHIN"] = 165] = "OP_WITHIN"; + OpCode[OpCode["OP_RIPEMD160"] = 166] = "OP_RIPEMD160"; + OpCode[OpCode["OP_SHA1"] = 167] = "OP_SHA1"; + OpCode[OpCode["OP_SHA256"] = 168] = "OP_SHA256"; + OpCode[OpCode["OP_HASH160"] = 169] = "OP_HASH160"; + OpCode[OpCode["OP_HASH256"] = 170] = "OP_HASH256"; + OpCode[OpCode["OP_CODESEPARATOR"] = 171] = "OP_CODESEPARATOR"; + OpCode[OpCode["OP_CHECKSIG"] = 172] = "OP_CHECKSIG"; + OpCode[OpCode["OP_CHECKSIGVERIFY"] = 173] = "OP_CHECKSIGVERIFY"; + OpCode[OpCode["OP_CHECKMULTISIG"] = 174] = "OP_CHECKMULTISIG"; + OpCode[OpCode["OP_CHECKMULTISIGVERIFY"] = 175] = "OP_CHECKMULTISIGVERIFY"; + OpCode[OpCode["OP_NOP1"] = 176] = "OP_NOP1"; + OpCode[OpCode["OP_NOP2"] = 177] = "OP_NOP2"; + OpCode[OpCode["OP_CHECKLOCKTIMEVERIFY"] = 177] = "OP_CHECKLOCKTIMEVERIFY"; + OpCode[OpCode["OP_NOP3"] = 178] = "OP_NOP3"; + OpCode[OpCode["OP_CHECKSEQUENCEVERIFY"] = 178] = "OP_CHECKSEQUENCEVERIFY"; + OpCode[OpCode["OP_NOP4"] = 179] = "OP_NOP4"; + OpCode[OpCode["OP_NOP5"] = 180] = "OP_NOP5"; + OpCode[OpCode["OP_NOP6"] = 181] = "OP_NOP6"; + OpCode[OpCode["OP_NOP7"] = 182] = "OP_NOP7"; + OpCode[OpCode["OP_NOP8"] = 183] = "OP_NOP8"; + OpCode[OpCode["OP_NOP9"] = 184] = "OP_NOP9"; + OpCode[OpCode["OP_NOP10"] = 185] = "OP_NOP10"; + OpCode[OpCode["OP_SMALLDATA"] = 249] = "OP_SMALLDATA"; + OpCode[OpCode["OP_SMALLINTEGER"] = 250] = "OP_SMALLINTEGER"; + OpCode[OpCode["OP_PUBKEYS"] = 251] = "OP_PUBKEYS"; + OpCode[OpCode["OP_PUBKEYHASH"] = 253] = "OP_PUBKEYHASH"; + OpCode[OpCode["OP_PUBKEY"] = 254] = "OP_PUBKEY"; + OpCode[OpCode["OP_INVALIDOPCODE"] = 255] = "OP_INVALIDOPCODE"; +})(OpCode || (exports.OpCode = OpCode = {})); +//# sourceMappingURL=op-codes.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.js.map new file mode 100644 index 0000000..5e9e0b0 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/op-codes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"op-codes.js","sourceRoot":"","sources":["../../src/bitcoin/op-codes.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.d.ts new file mode 100644 index 0000000..f25ba16 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.d.ts @@ -0,0 +1,23 @@ +import { Address } from "./address"; +import { ScriptType } from "./script-type"; +import { Transaction } from "./transaction"; +import { Bytes } from "../bytes"; +export declare class OutPoint { + TxId: string; + Vout: number; + private _lockingScript; + Satoshis: number; + Address?: Address; + ScriptType: ScriptType; + Transaction?: Transaction; + constructor(txId: string, vout: number, lockingScript: Bytes, satoshis: number, address: Address | undefined, scriptType: ScriptType); + static fromTransaction: (transaction: Transaction, vout: number) => OutPointFull; + static fromHex: (hex: string, vout: number) => OutPointFull; + toString: () => string; + get LockingScript(): Bytes; + set LockingScript(value: Bytes); +} +export declare class OutPointFull extends OutPoint { + constructor(transaction: Transaction, vout: number); +} +//# sourceMappingURL=out-point.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.d.ts.map new file mode 100644 index 0000000..4c121d1 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"out-point.d.ts","sourceRoot":"","sources":["../../src/bitcoin/out-point.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAIjC,qBAAa,QAAQ;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,cAAc,CAAQ;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,CAAC,EAAE,WAAW,CAAC;gBAGxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,KAAK,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,UAAU,EAAE,UAAU;IA0BxB,MAAM,CAAC,eAAe,GAAI,aAAa,WAAW,EAAE,MAAM,MAAM,kBAC1B;IAEtC,MAAM,CAAC,OAAO,GAAI,KAAK,MAAM,EAAE,MAAM,MAAM,kBACc;IAEzD,QAAQ,eAAqC;IAE7C,IAAI,aAAa,IAAI,KAAK,CAEzB;IAED,IAAI,aAAa,CAAC,KAAK,EAAE,KAAK,EAE7B;CACF;AAED,qBAAa,YAAa,SAAQ,QAAQ;gBAC5B,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM;CA8BnD"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.js new file mode 100644 index 0000000..ee52736 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.OutPointFull = exports.OutPoint = void 0; +const transaction_1 = require("../transaction"); +const script_type_1 = require("./script-type"); +const strict_mode_1 = require("../security/strict-mode"); +const locking_script_reader_1 = require("../script/read/locking-script-reader"); +class OutPoint { + constructor(txId, vout, lockingScript, satoshis, address, scriptType) { + this.toString = () => `${this.TxId}:${this.Vout}`; + this.TxId = txId; + this.Vout = vout; + this._lockingScript = lockingScript; + this.Satoshis = satoshis; + this.Address = address; + this.ScriptType = scriptType; + if ((0, strict_mode_1.getStrictModeConfig)().strictOutPointValidation) { + const reader = locking_script_reader_1.LockingScriptReader.read(lockingScript); + if (reader.ScriptType !== scriptType) { + throw new Error(`OutPoint scriptType mismatch: expected ${scriptType}, got ${reader.ScriptType}`); + } + if (address && reader.Address && reader.Address.Value !== address.Value) { + throw new Error(`OutPoint address mismatch: expected ${address.Value}, got ${reader.Address.Value}`); + } + } + } + get LockingScript() { + return this._lockingScript; + } + set LockingScript(value) { + this._lockingScript = value; + } +} +exports.OutPoint = OutPoint; +OutPoint.fromTransaction = (transaction, vout) => new OutPointFull(transaction, vout); +OutPoint.fromHex = (hex, vout) => new OutPointFull(transaction_1.TransactionReader.readHex(hex), vout); +class OutPointFull extends OutPoint { + constructor(transaction, vout) { + const output = transaction.Outputs[vout]; + if (output.ScriptType !== script_type_1.ScriptType.p2pkh && + output.ScriptType !== script_type_1.ScriptType.p2mpkh && + output.ScriptType !== script_type_1.ScriptType.p2stas && + output.ScriptType !== script_type_1.ScriptType.dstas) + throw new Error("p2pkh, p2mpkh, p2stas or dstas output must be provided"); + if ((output.ScriptType === script_type_1.ScriptType.p2pkh || + output.ScriptType === script_type_1.ScriptType.p2mpkh) && + !output.Address) { + throw new Error("p2pkh and p2mpkh outputs must expose address"); + } + super(transaction.Id, vout, output.LockingScript, output.Satoshis, output.Address, output.ScriptType); + this.Transaction = transaction; + } +} +exports.OutPointFull = OutPointFull; +//# sourceMappingURL=out-point.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.js.map new file mode 100644 index 0000000..8ad6ae8 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/out-point.js.map @@ -0,0 +1 @@ +{"version":3,"file":"out-point.js","sourceRoot":"","sources":["../../src/bitcoin/out-point.ts"],"names":[],"mappings":";;;AAAA,gDAAmD;AAEnD,+CAA2C;AAG3C,yDAA8D;AAC9D,gFAA2E;AAE3E,MAAa,QAAQ;IASnB,YACE,IAAY,EACZ,IAAY,EACZ,aAAoB,EACpB,QAAgB,EAChB,OAA4B,EAC5B,UAAsB;QAgCxB,aAAQ,GAAG,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QA9B3C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAE7B,IAAI,IAAA,iCAAmB,GAAE,CAAC,wBAAwB,EAAE,CAAC;YACnD,MAAM,MAAM,GAAG,2CAAmB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAEvD,IAAI,MAAM,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACrC,MAAM,IAAI,KAAK,CACb,0CAA0C,UAAU,SAAS,MAAM,CAAC,UAAU,EAAE,CACjF,CAAC;YACJ,CAAC;YAED,IAAI,OAAO,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;gBACxE,MAAM,IAAI,KAAK,CACb,uCAAuC,OAAO,CAAC,KAAK,SAAS,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CACpF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAUD,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,IAAI,aAAa,CAAC,KAAY;QAC5B,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;IAC9B,CAAC;;AAvDH,4BAwDC;AAfQ,wBAAe,GAAG,CAAC,WAAwB,EAAE,IAAY,EAAE,EAAE,CAClE,IAAI,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,AADf,CACgB;AAE/B,gBAAO,GAAG,CAAC,GAAW,EAAE,IAAY,EAAE,EAAE,CAC7C,IAAI,YAAY,CAAC,+BAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,AAD1C,CAC2C;AAa3D,MAAa,YAAa,SAAQ,QAAQ;IACxC,YAAY,WAAwB,EAAE,IAAY;QAChD,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEzC,IACE,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK;YACtC,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,MAAM;YACvC,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,MAAM;YACvC,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK;YAEtC,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAE5E,IACE,CAAC,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK;YACrC,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,MAAM,CAAC;YAC1C,CAAC,MAAM,CAAC,OAAO,EACf,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;QAED,KAAK,CACH,WAAW,CAAC,EAAE,EACd,IAAI,EACJ,MAAM,CAAC,aAAa,EACpB,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,UAAU,CAClB,CAAC;QAEF,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;AA/BD,oCA+BC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.d.ts new file mode 100644 index 0000000..dbb06f3 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.d.ts @@ -0,0 +1,8 @@ +import { OutPoint } from "./out-point"; +import { PrivateKey } from "./private-key"; +import { Wallet } from "./wallet"; +export type TPayment = { + OutPoint: OutPoint; + Owner: PrivateKey | Wallet; +}; +//# sourceMappingURL=payment.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.d.ts.map new file mode 100644 index 0000000..ebc1c83 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../../src/bitcoin/payment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC;CAC5B,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.js new file mode 100644 index 0000000..296d027 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=payment.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.js.map new file mode 100644 index 0000000..22ae408 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/payment.js.map @@ -0,0 +1 @@ +{"version":3,"file":"payment.js","sourceRoot":"","sources":["../../src/bitcoin/payment.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.d.ts new file mode 100644 index 0000000..a63d3b4 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.d.ts @@ -0,0 +1,16 @@ +import { Address } from "./address"; +import { Bytes } from "../bytes"; +export { verify } from "@noble/secp256k1"; +export declare class PrivateKey { + private _pk; + private _disposed; + Address: Address; + PublicKey: Bytes; + constructor(pk: Bytes); + private assertAlive; + sign: (message: Bytes) => Bytes; + verify: (signature: Bytes, message: Bytes) => boolean; + dispose: () => void; +} +export declare const verifyBitcoinSignedMessage: (message: Bytes, publicKey: Bytes, signature: Bytes) => boolean; +//# sourceMappingURL=private-key.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.d.ts.map new file mode 100644 index 0000000..1925e24 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"private-key.d.ts","sourceRoot":"","sources":["../../src/bitcoin/private-key.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,KAAK,EAAuC,MAAM,UAAU,CAAC;AAEtE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA0D1C,qBAAa,UAAU;IACrB,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,KAAK,CAAC;gBAEL,EAAE,EAAE,KAAK;IAMrB,OAAO,CAAC,WAAW,CAIjB;IAEF,IAAI,GAAI,SAAS,KAAK,WAWpB;IAEF,MAAM,GAAI,WAAW,KAAK,EAAE,SAAS,KAAK,aAUxC;IAEF,OAAO,aAGL;CACH;AAED,eAAO,MAAM,0BAA0B,GACrC,SAAS,KAAK,EACd,WAAW,KAAK,EAChB,WAAW,KAAK,YAcjB,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.js new file mode 100644 index 0000000..d217416 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.js @@ -0,0 +1,108 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyBitcoinSignedMessage = exports.PrivateKey = exports.verify = void 0; +const secp256k1_1 = require("@noble/secp256k1"); +const hmac_js_1 = require("@noble/hashes/hmac.js"); +const sha2_js_1 = require("@noble/hashes/sha2.js"); +const buffer_utils_1 = require("../buffer/buffer-utils"); +const address_1 = require("./address"); +const binary_1 = require("../binary"); +const hashes_1 = require("../hashes"); +const bytes_1 = require("../bytes"); +var secp256k1_2 = require("@noble/secp256k1"); +Object.defineProperty(exports, "verify", { enumerable: true, get: function () { return secp256k1_2.verify; } }); +secp256k1_1.hashes.hmacSha256 = (key, msg) => (0, hmac_js_1.hmac)(sha2_js_1.sha256, key, msg); +secp256k1_1.hashes.sha256 = (msg) => (0, sha2_js_1.sha256)(msg); +const bigintToBytes = (value) => { + let hex = value.toString(16); + if (hex.length % 2) + hex = `0${hex}`; + let bytes = (0, bytes_1.fromHex)(hex); + if (bytes.length > 0 && (bytes[0] & 0x80) !== 0) { + bytes = (0, bytes_1.concat)([new Uint8Array([0x00]), bytes]); + } + return bytes; +}; +const bytesToBigInt = (bytes) => { + if (bytes.length === 0) + return BigInt(0); + return BigInt(`0x${(0, bytes_1.toHex)(bytes)}`); +}; +const derEncodeSignature = (signature) => { + const r = bigintToBytes(signature.r); + const s = bigintToBytes(signature.s); + const totalLen = 2 + r.length + 2 + s.length; + return (0, bytes_1.concat)([ + new Uint8Array([0x30, totalLen, 0x02, r.length]), + r, + new Uint8Array([0x02, s.length]), + s, + ]); +}; +const derDecodeSignature = (der) => { + if (der.length < 8 || der[0] !== 0x30) { + throw new Error("Invalid DER signature"); + } + const totalLen = der[1]; + if (totalLen + 2 !== der.length) { + throw new Error("Invalid DER signature length"); + } + let offset = 2; + if (der[offset++] !== 0x02) + throw new Error("Invalid DER signature"); + const rLen = der[offset++]; + const r = der.subarray(offset, offset + rLen); + offset += rLen; + if (der[offset++] !== 0x02) + throw new Error("Invalid DER signature"); + const sLen = der[offset++]; + const s = der.subarray(offset, offset + sLen); + return new secp256k1_1.Signature(bytesToBigInt(r), bytesToBigInt(s)); +}; +class PrivateKey { + constructor(pk) { + this._disposed = false; + this.assertAlive = () => { + if (this._disposed) { + throw new Error("PrivateKey has been disposed"); + } + }; + this.sign = (message) => { + this.assertAlive(); + return derEncodeSignature(secp256k1_1.Signature.fromBytes((0, secp256k1_1.sign)(message, this._pk, { + prehash: false, + lowS: true, + extraEntropy: false, + }))); + }; + this.verify = (signature, message) => { + const sig = signature.length > 0 && signature[0] === 0x30 + ? derDecodeSignature(signature).toBytes() + : signature; + return (0, secp256k1_1.verify)(sig, message, this.PublicKey, { + prehash: false, + format: "compact", + }); + }; + this.dispose = () => { + this._pk.fill(0); + this._disposed = true; + }; + this._pk = new Uint8Array(pk); + this.PublicKey = (0, secp256k1_1.getPublicKey)(this._pk, true); + this.Address = address_1.Address.fromPublicKey(this.PublicKey); + } +} +exports.PrivateKey = PrivateKey; +const verifyBitcoinSignedMessage = (message, publicKey, signature) => { + const prefix = (0, bytes_1.utf8ToBytes)("Bitcoin Signed Message:\n"); + const writer = binary_1.ByteWriter.fromSize((0, buffer_utils_1.getChunkSize)(prefix) + (0, buffer_utils_1.getChunkSize)(message)); + writer.writeVarChunk(prefix); + writer.writeVarChunk(message); + return (0, secp256k1_1.verify)(signature, (0, hashes_1.hash256)(writer.buffer), publicKey, { + prehash: false, + format: "compact", + }); +}; +exports.verifyBitcoinSignedMessage = verifyBitcoinSignedMessage; +//# sourceMappingURL=private-key.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.js.map new file mode 100644 index 0000000..551e0e9 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/private-key.js.map @@ -0,0 +1 @@ +{"version":3,"file":"private-key.js","sourceRoot":"","sources":["../../src/bitcoin/private-key.ts"],"names":[],"mappings":";;;AAAA,gDAM0B;AAC1B,mDAA6C;AAC7C,mDAA+C;AAC/C,yDAAsD;AACtD,uCAAoC;AACpC,sCAAuC;AACvC,sCAAoC;AACpC,oCAAsE;AAEtE,8CAA0C;AAAjC,mGAAA,MAAM,OAAA;AAEf,kBAAM,CAAC,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAA,cAAI,EAAC,gBAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACzD,kBAAM,CAAC,MAAM,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,gBAAM,EAAC,GAAG,CAAC,CAAC;AAErC,MAAM,aAAa,GAAG,CAAC,KAAa,EAAE,EAAE;IACtC,IAAI,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7B,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;IACpC,IAAI,KAAK,GAAG,IAAA,eAAO,EAAC,GAAG,CAAC,CAAC;IAEzB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,GAAG,IAAA,cAAM,EAAC,CAAC,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,KAAY,EAAE,EAAE;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC,KAAK,IAAA,aAAK,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,SAAoB,EAAE,EAAE;IAClD,MAAM,CAAC,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IAE7C,OAAO,IAAA,cAAM,EAAC;QACZ,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,GAAU,EAAE,EAAE;IACxC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,QAAQ,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,MAAM,IAAI,IAAI,CAAC;IAEf,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAE9C,OAAO,IAAI,qBAAS,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC,CAAC;AAEF,MAAa,UAAU;IAOrB,YAAY,EAAS;QALb,cAAS,GAAG,KAAK,CAAC;QAWlB,gBAAW,GAAG,GAAG,EAAE;YACzB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAClD,CAAC;QACH,CAAC,CAAC;QAEF,SAAI,GAAG,CAAC,OAAc,EAAE,EAAE;YACxB,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,OAAO,kBAAkB,CACvB,qBAAS,CAAC,SAAS,CACjB,IAAA,gBAAI,EAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;gBACtB,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,IAAI;gBACV,YAAY,EAAE,KAAK;aACpB,CAAC,CACH,CACF,CAAC;QACJ,CAAC,CAAC;QAEF,WAAM,GAAG,CAAC,SAAgB,EAAE,OAAc,EAAE,EAAE;YAC5C,MAAM,GAAG,GACP,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI;gBAC3C,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;gBACzC,CAAC,CAAC,SAAS,CAAC;YAEhB,OAAO,IAAA,kBAAM,EAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE;gBAC1C,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,SAAS;aAClB,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,YAAO,GAAG,GAAG,EAAE;YACb,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC;QAvCA,IAAI,CAAC,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,IAAA,wBAAY,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,GAAG,iBAAO,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvD,CAAC;CAqCF;AAhDD,gCAgDC;AAEM,MAAM,0BAA0B,GAAG,CACxC,OAAc,EACd,SAAgB,EAChB,SAAgB,EAChB,EAAE;IACF,MAAM,MAAM,GAAG,IAAA,mBAAW,EAAC,2BAA2B,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,mBAAU,CAAC,QAAQ,CAChC,IAAA,2BAAY,EAAC,MAAM,CAAC,GAAG,IAAA,2BAAY,EAAC,OAAO,CAAC,CAC7C,CAAC;IAEF,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAE9B,OAAO,IAAA,kBAAM,EAAC,SAAS,EAAE,IAAA,gBAAO,EAAC,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE;QAC1D,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,SAAS;KAClB,CAAC,CAAC;AACL,CAAC,CAAC;AAjBW,QAAA,0BAA0B,8BAiBrC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.d.ts new file mode 100644 index 0000000..fa27bd1 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.d.ts @@ -0,0 +1,12 @@ +export declare enum ScriptType { + unknown = 0, + p2pk = 1, + p2pkh = 2, + p2sh = 3, + p2ms = 4, + nullData = 5, + p2stas = 6, + dstas = 7, + p2mpkh = 8 +} +//# sourceMappingURL=script-type.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.d.ts.map new file mode 100644 index 0000000..8a0bcab --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script-type.d.ts","sourceRoot":"","sources":["../../src/bitcoin/script-type.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU;IACpB,OAAO,IAAI;IACX,IAAI,IAAI;IACR,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,QAAQ,IAAI;IACZ,MAAM,IAAI;IACV,KAAK,IAAI;IACT,MAAM,IAAI;CACX"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.js new file mode 100644 index 0000000..2c33724 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ScriptType = void 0; +var ScriptType; +(function (ScriptType) { + ScriptType[ScriptType["unknown"] = 0] = "unknown"; + ScriptType[ScriptType["p2pk"] = 1] = "p2pk"; + ScriptType[ScriptType["p2pkh"] = 2] = "p2pkh"; + ScriptType[ScriptType["p2sh"] = 3] = "p2sh"; + ScriptType[ScriptType["p2ms"] = 4] = "p2ms"; + ScriptType[ScriptType["nullData"] = 5] = "nullData"; + ScriptType[ScriptType["p2stas"] = 6] = "p2stas"; + ScriptType[ScriptType["dstas"] = 7] = "dstas"; + ScriptType[ScriptType["p2mpkh"] = 8] = "p2mpkh"; +})(ScriptType || (exports.ScriptType = ScriptType = {})); +//# sourceMappingURL=script-type.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.js.map new file mode 100644 index 0000000..9f54ee3 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/script-type.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script-type.js","sourceRoot":"","sources":["../../src/bitcoin/script-type.ts"],"names":[],"mappings":";;;AAAA,IAAY,UAUX;AAVD,WAAY,UAAU;IACpB,iDAAW,CAAA;IACX,2CAAQ,CAAA;IACR,6CAAS,CAAA;IACT,2CAAQ,CAAA;IACR,2CAAQ,CAAA;IACR,mDAAY,CAAA;IACZ,+CAAU,CAAA;IACV,6CAAS,CAAA;IACT,+CAAU,CAAA;AACZ,CAAC,EAVW,UAAU,0BAAV,UAAU,QAUrB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.d.ts new file mode 100644 index 0000000..6e94a88 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.d.ts @@ -0,0 +1,8 @@ +export declare enum SignatureHashType { + SIGHASH_ALL = 1, + SIGHASH_NONE = 2, + SIGHASH_SINGLE = 3, + SIGHASH_FORKID = 64, + SIGHASH_ANYONECANPAY = 128 +} +//# sourceMappingURL=sig-hash-type.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.d.ts.map new file mode 100644 index 0000000..4d0f84c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sig-hash-type.d.ts","sourceRoot":"","sources":["../../src/bitcoin/sig-hash-type.ts"],"names":[],"mappings":"AAAA,oBAAY,iBAAiB;IAC3B,WAAW,IAAO;IAClB,YAAY,IAAO;IACnB,cAAc,IAAO;IACrB,cAAc,KAAO;IACrB,oBAAoB,MAAO;CAC5B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.js new file mode 100644 index 0000000..5f28627 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SignatureHashType = void 0; +var SignatureHashType; +(function (SignatureHashType) { + SignatureHashType[SignatureHashType["SIGHASH_ALL"] = 1] = "SIGHASH_ALL"; + SignatureHashType[SignatureHashType["SIGHASH_NONE"] = 2] = "SIGHASH_NONE"; + SignatureHashType[SignatureHashType["SIGHASH_SINGLE"] = 3] = "SIGHASH_SINGLE"; + SignatureHashType[SignatureHashType["SIGHASH_FORKID"] = 64] = "SIGHASH_FORKID"; + SignatureHashType[SignatureHashType["SIGHASH_ANYONECANPAY"] = 128] = "SIGHASH_ANYONECANPAY"; +})(SignatureHashType || (exports.SignatureHashType = SignatureHashType = {})); +//# sourceMappingURL=sig-hash-type.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.js.map new file mode 100644 index 0000000..5f0586e --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/sig-hash-type.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sig-hash-type.js","sourceRoot":"","sources":["../../src/bitcoin/sig-hash-type.ts"],"names":[],"mappings":";;;AAAA,IAAY,iBAMX;AAND,WAAY,iBAAiB;IAC3B,uEAAkB,CAAA;IAClB,yEAAmB,CAAA;IACnB,6EAAqB,CAAA;IACrB,8EAAqB,CAAA;IACrB,2FAA2B,CAAA;AAC7B,CAAC,EANW,iBAAiB,iCAAjB,iBAAiB,QAM5B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.d.ts new file mode 100644 index 0000000..fd2c331 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.d.ts @@ -0,0 +1,26 @@ +export type TokenAuthority = { + m: number; + publicKeys: string[]; +}; +export type TokenSchemeOptions = { + freeze?: boolean; + confiscation?: boolean; + isDivisible?: boolean; + freezeAuthority?: TokenAuthority; + confiscationAuthority?: TokenAuthority; +}; +export declare class TokenScheme { + Name: string; + TokenId: string; + Symbol: string; + SatoshisPerToken: number; + Freeze: boolean; + Confiscation: boolean; + IsDivisible: boolean; + FreezeAuthority?: TokenAuthority; + ConfiscationAuthority?: TokenAuthority; + constructor(name: string, tokenId: string, symbol: string, satoshisPerToken: number, options?: TokenSchemeOptions); + toJson: () => string; + toBytes: () => Uint8Array; +} +//# sourceMappingURL=token-scheme.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.d.ts.map new file mode 100644 index 0000000..d2d4a11 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"token-scheme.d.ts","sourceRoot":"","sources":["../../src/bitcoin/token-scheme.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,qBAAqB,CAAC,EAAE,cAAc,CAAC;CACxC,CAAC;AAEF,qBAAa,WAAW;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,qBAAqB,CAAC,EAAE,cAAc,CAAC;gBAGrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,kBAAuB;IAalC,MAAM,eAWD;IAEL,OAAO,gCAAiD;CACzD"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.js new file mode 100644 index 0000000..4f35d35 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TokenScheme = void 0; +class TokenScheme { + constructor(name, tokenId, symbol, satoshisPerToken, options = {}) { + this.toJson = () => JSON.stringify({ + name: this.Name, + tokenId: this.TokenId, + symbol: this.Symbol, + satoshisPerToken: this.SatoshisPerToken, + freeze: this.Freeze, + confiscation: this.Confiscation, + isDivisible: this.IsDivisible, + freezeAuthority: this.FreezeAuthority, + confiscationAuthority: this.ConfiscationAuthority, + }); + this.toBytes = () => new TextEncoder().encode(this.toJson()); + this.Name = name; + this.TokenId = tokenId; + this.Symbol = symbol; + this.SatoshisPerToken = satoshisPerToken; + this.Freeze = options.freeze === true; + this.Confiscation = options.confiscation === true; + this.IsDivisible = options.isDivisible === true; + this.FreezeAuthority = options.freezeAuthority; + this.ConfiscationAuthority = options.confiscationAuthority; + } +} +exports.TokenScheme = TokenScheme; +//# sourceMappingURL=token-scheme.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.js.map new file mode 100644 index 0000000..ab66fbc --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/token-scheme.js.map @@ -0,0 +1 @@ +{"version":3,"file":"token-scheme.js","sourceRoot":"","sources":["../../src/bitcoin/token-scheme.ts"],"names":[],"mappings":";;;AAaA,MAAa,WAAW;IAWtB,YACE,IAAY,EACZ,OAAe,EACf,MAAc,EACd,gBAAwB,EACxB,UAA8B,EAAE;QAalC,WAAM,GAAG,GAAG,EAAE,CACZ,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,qBAAqB,EAAE,IAAI,CAAC,qBAAqB;SAClD,CAAC,CAAC;QAEL,YAAO,GAAG,GAAG,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAxBtD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC;QACtC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,KAAK,IAAI,CAAC;QAClD,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,KAAK,IAAI,CAAC;QAChD,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;QAC/C,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAC7D,CAAC;CAgBF;AA3CD,kCA2CC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.d.ts new file mode 100644 index 0000000..884f868 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.d.ts @@ -0,0 +1,11 @@ +import { Address } from "./address"; +import { Bytes } from "../bytes"; +export declare class TransactionInput { + TxId: string; + Vout: number; + UnlockingScript: Bytes; + Sequence: number; + constructor(txId: string, vout: number, unlockingScript: Bytes, sequence: number); + tryGetAddress: () => Address | undefined; +} +//# sourceMappingURL=transaction-input.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.d.ts.map new file mode 100644 index 0000000..a52b44d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-input.d.ts","sourceRoot":"","sources":["../../src/bitcoin/transaction-input.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,qBAAa,gBAAgB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,KAAK,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;gBAGf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,KAAK,EACtB,QAAQ,EAAE,MAAM;IAQlB,aAAa,4BAYX;CACH"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.js new file mode 100644 index 0000000..bcb685c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TransactionInput = void 0; +const script_reader_1 = require("../script/read/script-reader"); +const address_1 = require("./address"); +class TransactionInput { + constructor(txId, vout, unlockingScript, sequence) { + this.tryGetAddress = () => { + const scriptTokens = script_reader_1.ScriptReader.read(this.UnlockingScript); + if (scriptTokens.length === 0) + return undefined; + const lastToken = scriptTokens[scriptTokens.length - 1]; + if (!(lastToken === null || lastToken === void 0 ? void 0 : lastToken.Data)) + return undefined; + if (lastToken.DataLength === 33 && + (lastToken.Data[0] === 2 || lastToken.Data[0] === 3)) { + return address_1.Address.fromPublicKey(lastToken.Data); + } + }; + this.TxId = txId; + this.Vout = vout; + this.UnlockingScript = unlockingScript; + this.Sequence = sequence; + } +} +exports.TransactionInput = TransactionInput; +//# sourceMappingURL=transaction-input.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.js.map new file mode 100644 index 0000000..b7fe7ee --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-input.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-input.js","sourceRoot":"","sources":["../../src/bitcoin/transaction-input.ts"],"names":[],"mappings":";;;AAAA,gEAA4D;AAC5D,uCAAoC;AAGpC,MAAa,gBAAgB;IAM3B,YACE,IAAY,EACZ,IAAY,EACZ,eAAsB,EACtB,QAAgB;QAQlB,kBAAa,GAAG,GAAG,EAAE;YACnB,MAAM,YAAY,GAAG,4BAAY,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC7D,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC;YAChD,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACxD,IAAI,CAAC,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,IAAI,CAAA;gBAAE,OAAO,SAAS,CAAC;YAEvC,IACE,SAAS,CAAC,UAAU,KAAK,EAAE;gBAC3B,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EACpD,CAAC;gBACD,OAAO,iBAAO,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC,CAAC;QAlBA,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CAeF;AA/BD,4CA+BC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.d.ts new file mode 100644 index 0000000..ed6bcef --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.d.ts @@ -0,0 +1,16 @@ +import { Bytes } from "../bytes"; +import { Address } from "./address"; +import { ScriptType } from "./script-type"; +export declare class TransactionOutput { + Satoshis: number; + private _lockingScript; + ScriptType: ScriptType; + Address?: Address; + TokenId?: string; + Symbol?: string; + data: Bytes[]; + constructor(satoshis: number, lockingScript: Bytes); + get LockingScript(): Bytes; + set LockingScript(value: Bytes); +} +//# sourceMappingURL=transaction-output.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.d.ts.map new file mode 100644 index 0000000..2c1f802 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-output.d.ts","sourceRoot":"","sources":["../../src/bitcoin/transaction-output.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAS,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,qBAAa,iBAAiB;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,cAAc,CAAQ;IAC9B,UAAU,EAAE,UAAU,CAAsB;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,KAAK,EAAE,CAAM;gBAEP,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK;IA0ClD,IAAI,aAAa,IAAI,KAAK,CAEzB;IAED,IAAI,aAAa,CAAC,KAAK,EAAE,KAAK,EAE7B;CACF"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.js new file mode 100644 index 0000000..b3e743c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.js @@ -0,0 +1,51 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TransactionOutput = void 0; +const locking_script_reader_1 = require("../script/read/locking-script-reader"); +const bytes_1 = require("../bytes"); +const script_type_1 = require("./script-type"); +class TransactionOutput { + constructor(satoshis, lockingScript) { + var _a, _b, _c, _d; + this.ScriptType = script_type_1.ScriptType.unknown; + this.data = []; + this.Satoshis = satoshis; + this._lockingScript = lockingScript; + const reader = locking_script_reader_1.LockingScriptReader.read(this._lockingScript); + this.ScriptType = reader.ScriptType; + this.Address = reader.Address; + if (reader.ScriptType === script_type_1.ScriptType.nullData) { + this.data = (_a = reader.Data) !== null && _a !== void 0 ? _a : []; + return; + } + if (reader.ScriptType === script_type_1.ScriptType.p2pkh || + reader.ScriptType === script_type_1.ScriptType.p2mpkh) { + this.data = (_b = reader.Data) !== null && _b !== void 0 ? _b : []; + return; + } + if (reader.ScriptType === script_type_1.ScriptType.p2stas) { + this.TokenId = (_c = reader.getTokenId()) !== null && _c !== void 0 ? _c : undefined; + this.Symbol = (_d = reader.getSymbol()) !== null && _d !== void 0 ? _d : undefined; + if (reader.Data && reader.Data.length > 2) { + for (let i = 2; i < reader.Data.length; i++) { + this.data.push(reader.Data[i]); + } + } + return; + } + if (reader.ScriptType === script_type_1.ScriptType.dstas && reader.Dstas) { + this.TokenId = (0, bytes_1.toHex)(reader.Dstas.Redemption); + this.data.push(reader.Dstas.Flags); + this.data.push(...reader.Dstas.ServiceFields); + this.data.push(...reader.Dstas.OptionalData); + } + } + get LockingScript() { + return this._lockingScript; + } + set LockingScript(value) { + this._lockingScript = value; + } +} +exports.TransactionOutput = TransactionOutput; +//# sourceMappingURL=transaction-output.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.js.map new file mode 100644 index 0000000..835f712 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction-output.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-output.js","sourceRoot":"","sources":["../../src/bitcoin/transaction-output.ts"],"names":[],"mappings":";;;AAAA,gFAA2E;AAC3E,oCAAwC;AAExC,+CAA2C;AAE3C,MAAa,iBAAiB;IAS5B,YAAY,QAAgB,EAAE,aAAoB;;QANlD,eAAU,GAAe,wBAAU,CAAC,OAAO,CAAC;QAI5C,SAAI,GAAY,EAAE,CAAC;QAGjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;QAEpC,MAAM,MAAM,GAAG,2CAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAE7D,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAE9B,IAAI,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,QAAQ,EAAE,CAAC;YAC9C,IAAI,CAAC,IAAI,GAAG,MAAA,MAAM,CAAC,IAAI,mCAAI,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,IACE,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK;YACtC,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,MAAM,EACvC,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,MAAA,MAAM,CAAC,IAAI,mCAAI,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,MAAM,EAAE,CAAC;YAC5C,IAAI,CAAC,OAAO,GAAG,MAAA,MAAM,CAAC,UAAU,EAAE,mCAAI,SAAS,CAAC;YAChD,IAAI,CAAC,MAAM,GAAG,MAAA,MAAM,CAAC,SAAS,EAAE,mCAAI,SAAS,CAAC;YAE9C,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC5C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC3D,IAAI,CAAC,OAAO,GAAG,IAAA,aAAK,EAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,IAAI,aAAa,CAAC,KAAY;QAC5B,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;IAC9B,CAAC;CACF;AA1DD,8CA0DC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.d.ts new file mode 100644 index 0000000..77fa1e4 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.d.ts @@ -0,0 +1,14 @@ +import { Bytes } from "../bytes"; +import { TransactionInput } from "./transaction-input"; +import { TransactionOutput } from "./transaction-output"; +export declare class Transaction { + Inputs: TransactionInput[]; + Outputs: TransactionOutput[]; + Version: number; + LockTime: number; + Raw: Bytes; + Hex: string; + Id: string; + constructor(raw: Bytes, inputs: TransactionInput[], outputs: TransactionOutput[], version: number, lockTime: number); +} +//# sourceMappingURL=transaction.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.d.ts.map new file mode 100644 index 0000000..2ed6286 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/bitcoin/transaction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAS,MAAM,UAAU,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,qBAAa,WAAW;IACtB,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,KAAK,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;gBAGT,GAAG,EAAE,KAAK,EACV,MAAM,EAAE,gBAAgB,EAAE,EAC1B,OAAO,EAAE,iBAAiB,EAAE,EAC5B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM;CAWnB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.js new file mode 100644 index 0000000..8df5152 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Transaction = void 0; +const buffer_utils_1 = require("../buffer/buffer-utils"); +const bytes_1 = require("../bytes"); +const hashes_1 = require("../hashes"); +class Transaction { + constructor(raw, inputs, outputs, version, lockTime) { + this.Inputs = inputs; + this.Outputs = outputs; + this.Version = version; + this.LockTime = lockTime; + this.Raw = raw; + this.Hex = (0, bytes_1.toHex)(raw); + this.Id = (0, bytes_1.toHex)((0, buffer_utils_1.reverseBytes)((0, hashes_1.hash256)(raw))); + } +} +exports.Transaction = Transaction; +//# sourceMappingURL=transaction.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.js.map new file mode 100644 index 0000000..d9aaa9d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/transaction.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/bitcoin/transaction.ts"],"names":[],"mappings":";;;AAAA,yDAAsD;AACtD,oCAAwC;AACxC,sCAAoC;AAIpC,MAAa,WAAW;IAStB,YACE,GAAU,EACV,MAA0B,EAC1B,OAA4B,EAC5B,OAAe,EACf,QAAgB;QAEhB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,GAAG,GAAG,IAAA,aAAK,EAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,EAAE,GAAG,IAAA,aAAK,EAAC,IAAA,2BAAY,EAAC,IAAA,gBAAO,EAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC;CACF;AAzBD,kCAyBC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.d.ts b/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.d.ts new file mode 100644 index 0000000..fe0e4d8 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.d.ts @@ -0,0 +1,22 @@ +import { HDKey, Versions } from "@scure/bip32"; +interface WalletOpt { + versions: Versions; + depth?: number; + index?: number; + parentFingerprint?: number; + chainCode: Uint8Array; + privateKey?: Uint8Array; +} +export declare class Wallet extends HDKey { + static fromMnemonic: (mnemonic: string) => Wallet; + static fromHdKey: ({ versions, depth, index, parentFingerprint, chainCode, privateKey, }: HDKey) => Wallet; + private _pk; + constructor(opt: WalletOpt); + get Address(): import("./address").Address; + get PublicKey(): import("../bytes").Bytes; + deriveWallet: (path: string) => Wallet; + sign: (message: Uint8Array) => import("../bytes").Bytes; + signMessage: (message: Uint8Array) => import("../bytes").Bytes; +} +export {}; +//# sourceMappingURL=wallet.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.d.ts.map new file mode 100644 index 0000000..09f8445 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../src/bitcoin/wallet.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG/C,UAAU,SAAS;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,qBAAa,MAAO,SAAQ,KAAK;IAC/B,MAAM,CAAC,YAAY,GAAI,UAAU,MAAM,YAQrC;IAEF,MAAM,CAAC,SAAS,GAAI,uEAOjB,KAAK,YAQH;IAEL,OAAO,CAAC,GAAG,CAAa;gBAEZ,GAAG,EAAE,SAAS;IAM1B,IAAI,OAAO,gCAEV;IAED,IAAI,SAAS,6BAEZ;IAED,YAAY,GAAI,MAAM,MAAM,KAAG,MAAM,CAEnC;IAEF,IAAI,GAAI,SAAS,UAAU,8BAA4B;IACvD,WAAW,GAAI,SAAS,UAAU,8BAA4B;CAC/D"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.js b/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.js new file mode 100644 index 0000000..711ed5e --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Wallet = void 0; +const bip39_1 = require("@scure/bip39"); +const bip32_1 = require("@scure/bip32"); +const private_key_1 = require("./private-key"); +class Wallet extends bip32_1.HDKey { + constructor(opt) { + super(opt); + this.deriveWallet = (path) => { + return Wallet.fromHdKey(super.derive(path)); + }; + this.sign = (message) => this._pk.sign(message); + this.signMessage = (message) => this._pk.sign(message); + this._pk = new private_key_1.PrivateKey(this.privateKey); + } + get Address() { + return this._pk.Address; + } + get PublicKey() { + return this._pk.PublicKey; + } +} +exports.Wallet = Wallet; +Wallet.fromMnemonic = (mnemonic) => { + let seed; + try { + seed = (0, bip39_1.mnemonicToSeedSync)(mnemonic.trim()); + } + catch (_a) { + throw new Error("Invalid mnemonic phrase"); + } + return Wallet.fromHdKey(Wallet.fromMasterSeed(seed)); +}; +Wallet.fromHdKey = ({ versions, depth, index, parentFingerprint, chainCode, privateKey, }) => new Wallet({ + versions, + depth, + index, + parentFingerprint, + chainCode: chainCode, + privateKey: privateKey, +}); +//# sourceMappingURL=wallet.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.js.map b/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.js.map new file mode 100644 index 0000000..d5e670b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bitcoin/wallet.js.map @@ -0,0 +1 @@ +{"version":3,"file":"wallet.js","sourceRoot":"","sources":["../../src/bitcoin/wallet.ts"],"names":[],"mappings":";;;AAAA,wCAAkD;AAClD,wCAA+C;AAC/C,+CAA2C;AAW3C,MAAa,MAAO,SAAQ,aAAK;IA8B/B,YAAY,GAAc;QACxB,KAAK,CAAC,GAAG,CAAC,CAAC;QAab,iBAAY,GAAG,CAAC,IAAY,EAAU,EAAE;YACtC,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC;QAEF,SAAI,GAAG,CAAC,OAAmB,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvD,gBAAW,GAAG,CAAC,OAAmB,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAhB5D,IAAI,CAAC,GAAG,GAAG,IAAI,wBAAU,CAAC,IAAI,CAAC,UAAW,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;IAC1B,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;IAC5B,CAAC;;AA1CH,wBAkDC;AAjDQ,mBAAY,GAAG,CAAC,QAAgB,EAAE,EAAE;IACzC,IAAI,IAAgB,CAAC;IACrB,IAAI,CAAC;QACH,IAAI,GAAG,IAAA,0BAAkB,EAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IAAC,WAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;AACvD,CAAC,AARkB,CAQjB;AAEK,gBAAS,GAAG,CAAC,EAClB,QAAQ,EACR,KAAK,EACL,KAAK,EACL,iBAAiB,EACjB,SAAS,EACT,UAAU,GACJ,EAAE,EAAE,CACV,IAAI,MAAM,CAAC;IACT,QAAQ;IACR,KAAK;IACL,KAAK;IACL,iBAAiB;IACjB,SAAS,EAAE,SAAU;IACrB,UAAU,EAAE,UAAW;CACxB,CAAC,AAfY,CAeX"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bsv.d.ts b/vendor/dxs-bsv-token-sdk/dist/bsv.d.ts new file mode 100644 index 0000000..ab8fde7 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bsv.d.ts @@ -0,0 +1,9 @@ +export { bs58check } from "./base"; +export type { Bytes } from "./bytes"; +export { bytesToUtf8, concat, equal, fromHex, toHex, utf8ToBytes, } from "./bytes"; +export { hash160, hash256, ripemd160, sha256 } from "./hashes"; +export { configureStrictMode, getStrictModeConfig, resetStrictMode, type StrictModeConfig, type StrictScriptEvaluationLimits, } from "./security/strict-mode"; +export { Address, Mnemonic, Networks, OutPoint, OutPointFull, PrivateKey, ScriptType, SignatureHashType, TokenScheme, Transaction, TransactionInput, TransactionOutput, Wallet, type Network, type TokenSchemeOptions, type TDestination, type TPayment, } from "./bitcoin"; +export { TransactionBuilder, TransactionBuilderError, TransactionReader, } from "./transaction"; +export * from "./script"; +//# sourceMappingURL=bsv.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bsv.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bsv.d.ts.map new file mode 100644 index 0000000..feecf1f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bsv.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"bsv.d.ts","sourceRoot":"","sources":["../src/bsv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EACL,WAAW,EACX,MAAM,EACN,KAAK,EACL,OAAO,EACP,KAAK,EACL,WAAW,GACZ,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,4BAA4B,GAClC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,MAAM,EACN,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,QAAQ,GACd,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,cAAc,UAAU,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bsv.js b/vendor/dxs-bsv-token-sdk/dist/bsv.js new file mode 100644 index 0000000..1dc6fe9 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bsv.js @@ -0,0 +1,55 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TransactionReader = exports.TransactionBuilderError = exports.TransactionBuilder = exports.Wallet = exports.TransactionOutput = exports.TransactionInput = exports.Transaction = exports.TokenScheme = exports.SignatureHashType = exports.ScriptType = exports.PrivateKey = exports.OutPointFull = exports.OutPoint = exports.Networks = exports.Mnemonic = exports.Address = exports.resetStrictMode = exports.getStrictModeConfig = exports.configureStrictMode = exports.sha256 = exports.ripemd160 = exports.hash256 = exports.hash160 = exports.utf8ToBytes = exports.toHex = exports.fromHex = exports.equal = exports.concat = exports.bytesToUtf8 = exports.bs58check = void 0; +var base_1 = require("./base"); +Object.defineProperty(exports, "bs58check", { enumerable: true, get: function () { return base_1.bs58check; } }); +var bytes_1 = require("./bytes"); +Object.defineProperty(exports, "bytesToUtf8", { enumerable: true, get: function () { return bytes_1.bytesToUtf8; } }); +Object.defineProperty(exports, "concat", { enumerable: true, get: function () { return bytes_1.concat; } }); +Object.defineProperty(exports, "equal", { enumerable: true, get: function () { return bytes_1.equal; } }); +Object.defineProperty(exports, "fromHex", { enumerable: true, get: function () { return bytes_1.fromHex; } }); +Object.defineProperty(exports, "toHex", { enumerable: true, get: function () { return bytes_1.toHex; } }); +Object.defineProperty(exports, "utf8ToBytes", { enumerable: true, get: function () { return bytes_1.utf8ToBytes; } }); +var hashes_1 = require("./hashes"); +Object.defineProperty(exports, "hash160", { enumerable: true, get: function () { return hashes_1.hash160; } }); +Object.defineProperty(exports, "hash256", { enumerable: true, get: function () { return hashes_1.hash256; } }); +Object.defineProperty(exports, "ripemd160", { enumerable: true, get: function () { return hashes_1.ripemd160; } }); +Object.defineProperty(exports, "sha256", { enumerable: true, get: function () { return hashes_1.sha256; } }); +var strict_mode_1 = require("./security/strict-mode"); +Object.defineProperty(exports, "configureStrictMode", { enumerable: true, get: function () { return strict_mode_1.configureStrictMode; } }); +Object.defineProperty(exports, "getStrictModeConfig", { enumerable: true, get: function () { return strict_mode_1.getStrictModeConfig; } }); +Object.defineProperty(exports, "resetStrictMode", { enumerable: true, get: function () { return strict_mode_1.resetStrictMode; } }); +var bitcoin_1 = require("./bitcoin"); +Object.defineProperty(exports, "Address", { enumerable: true, get: function () { return bitcoin_1.Address; } }); +Object.defineProperty(exports, "Mnemonic", { enumerable: true, get: function () { return bitcoin_1.Mnemonic; } }); +Object.defineProperty(exports, "Networks", { enumerable: true, get: function () { return bitcoin_1.Networks; } }); +Object.defineProperty(exports, "OutPoint", { enumerable: true, get: function () { return bitcoin_1.OutPoint; } }); +Object.defineProperty(exports, "OutPointFull", { enumerable: true, get: function () { return bitcoin_1.OutPointFull; } }); +Object.defineProperty(exports, "PrivateKey", { enumerable: true, get: function () { return bitcoin_1.PrivateKey; } }); +Object.defineProperty(exports, "ScriptType", { enumerable: true, get: function () { return bitcoin_1.ScriptType; } }); +Object.defineProperty(exports, "SignatureHashType", { enumerable: true, get: function () { return bitcoin_1.SignatureHashType; } }); +Object.defineProperty(exports, "TokenScheme", { enumerable: true, get: function () { return bitcoin_1.TokenScheme; } }); +Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return bitcoin_1.Transaction; } }); +Object.defineProperty(exports, "TransactionInput", { enumerable: true, get: function () { return bitcoin_1.TransactionInput; } }); +Object.defineProperty(exports, "TransactionOutput", { enumerable: true, get: function () { return bitcoin_1.TransactionOutput; } }); +Object.defineProperty(exports, "Wallet", { enumerable: true, get: function () { return bitcoin_1.Wallet; } }); +var transaction_1 = require("./transaction"); +Object.defineProperty(exports, "TransactionBuilder", { enumerable: true, get: function () { return transaction_1.TransactionBuilder; } }); +Object.defineProperty(exports, "TransactionBuilderError", { enumerable: true, get: function () { return transaction_1.TransactionBuilderError; } }); +Object.defineProperty(exports, "TransactionReader", { enumerable: true, get: function () { return transaction_1.TransactionReader; } }); +__exportStar(require("./script"), exports); +//# sourceMappingURL=bsv.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bsv.js.map b/vendor/dxs-bsv-token-sdk/dist/bsv.js.map new file mode 100644 index 0000000..f635a76 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bsv.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bsv.js","sourceRoot":"","sources":["../src/bsv.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,+BAAmC;AAA1B,iGAAA,SAAS,OAAA;AAElB,iCAOiB;AANf,oGAAA,WAAW,OAAA;AACX,+FAAA,MAAM,OAAA;AACN,8FAAA,KAAK,OAAA;AACL,gGAAA,OAAO,OAAA;AACP,8FAAA,KAAK,OAAA;AACL,oGAAA,WAAW,OAAA;AAEb,mCAA+D;AAAtD,iGAAA,OAAO,OAAA;AAAE,iGAAA,OAAO,OAAA;AAAE,mGAAA,SAAS,OAAA;AAAE,gGAAA,MAAM,OAAA;AAC5C,sDAMgC;AAL9B,kHAAA,mBAAmB,OAAA;AACnB,kHAAA,mBAAmB,OAAA;AACnB,8GAAA,eAAe,OAAA;AAKjB,qCAkBmB;AAjBjB,kGAAA,OAAO,OAAA;AACP,mGAAA,QAAQ,OAAA;AACR,mGAAA,QAAQ,OAAA;AACR,mGAAA,QAAQ,OAAA;AACR,uGAAA,YAAY,OAAA;AACZ,qGAAA,UAAU,OAAA;AACV,qGAAA,UAAU,OAAA;AACV,4GAAA,iBAAiB,OAAA;AACjB,sGAAA,WAAW,OAAA;AACX,sGAAA,WAAW,OAAA;AACX,2GAAA,gBAAgB,OAAA;AAChB,4GAAA,iBAAiB,OAAA;AACjB,iGAAA,MAAM,OAAA;AAOR,6CAIuB;AAHrB,iHAAA,kBAAkB,OAAA;AAClB,sHAAA,uBAAuB,OAAA;AACvB,gHAAA,iBAAiB,OAAA;AAGnB,2CAAyB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.d.ts b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.d.ts new file mode 100644 index 0000000..bd68045 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.d.ts @@ -0,0 +1,2 @@ +export { ByteReader } from "../binary"; +//# sourceMappingURL=buffer-reader.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.d.ts.map new file mode 100644 index 0000000..59834a8 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"buffer-reader.d.ts","sourceRoot":"","sources":["../../src/buffer/buffer-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.js b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.js new file mode 100644 index 0000000..e245f7a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ByteReader = void 0; +var binary_1 = require("../binary"); +Object.defineProperty(exports, "ByteReader", { enumerable: true, get: function () { return binary_1.ByteReader; } }); +//# sourceMappingURL=buffer-reader.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.js.map b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.js.map new file mode 100644 index 0000000..51475df --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-reader.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buffer-reader.js","sourceRoot":"","sources":["../../src/buffer/buffer-reader.ts"],"names":[],"mappings":";;;AAAA,oCAAuC;AAA9B,oGAAA,UAAU,OAAA"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.d.ts b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.d.ts new file mode 100644 index 0000000..44c45d1 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.d.ts @@ -0,0 +1,16 @@ +import { OpCode } from "../bitcoin/op-codes"; +import { Bytes } from "../bytes"; +export declare const OP_INT_BASE = OpCode.OP_RESERVED; +export declare const asMinimalOP: (buffer: Bytes) => number | undefined; +export declare const ensureUInt: (value: number, max: number) => void; +export declare const slice: (buffer: Bytes, offset: number, length: number) => Uint8Array; +export declare const reverseBytes: (buffer: Bytes) => Bytes; +export declare const cloneBytes: (source: Bytes, targetStart?: number, sourceStart?: number | undefined, sourceEnd?: number | undefined) => Uint8Array; +export declare const splitBytes: (source: Bytes, splitBy: Bytes) => Bytes[]; +export declare const getVarIntLength: (value: number) => number; +export declare const getNumberSize: (data: number) => number; +export declare const getMinimumRequiredByte: (value: number) => number; +export declare const getNumberBytes: (value: number) => Bytes; +export declare const estimateChunkSize: (bufferSize: number) => number; +export declare const getChunkSize: (buffer: Bytes) => number; +//# sourceMappingURL=buffer-utils.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.d.ts.map new file mode 100644 index 0000000..8b44202 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"buffer-utils.d.ts","sourceRoot":"","sources":["../../src/buffer/buffer-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,eAAO,MAAM,WAAW,qBAAqB,CAAC;AAE9C,eAAO,MAAM,WAAW,GAAI,QAAQ,KAAK,uBAKxC,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,SAQpD,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,QAAQ,KAAK,EAAE,QAAQ,MAAM,EAAE,QAAQ,MAAM,4BACrC,CAAC;AAE/B,eAAO,MAAM,YAAY,GAAI,QAAQ,KAAK,UAYzC,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,QAAQ,KAAK,EACb,cAAa,MAAU,EACvB,cAAc,MAAM,GAAG,SAAS,EAChC,YAAY,MAAM,GAAG,SAAS,4BAS/B,CAAC;AAiBF,eAAO,MAAM,UAAU,GAAI,QAAQ,KAAK,EAAE,SAAS,KAAK,KAAG,KAAK,EAe/D,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,MACsB,CAAC;AAEvE,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,MAIX,CAAC;AAcnC,eAAO,MAAM,sBAAsB,GAAI,OAAO,MAAM,KAAG,MAetD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,KAiB9C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,YAAY,MAAM,WACV,CAAC;AAE3C,eAAO,MAAM,YAAY,GAAI,QAAQ,KAAK,WAAqC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.js b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.js new file mode 100644 index 0000000..6956205 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.js @@ -0,0 +1,129 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getChunkSize = exports.estimateChunkSize = exports.getNumberBytes = exports.getMinimumRequiredByte = exports.getNumberSize = exports.getVarIntLength = exports.splitBytes = exports.cloneBytes = exports.reverseBytes = exports.slice = exports.ensureUInt = exports.asMinimalOP = exports.OP_INT_BASE = void 0; +const op_codes_1 = require("../bitcoin/op-codes"); +exports.OP_INT_BASE = op_codes_1.OpCode.OP_RESERVED; +const asMinimalOP = (buffer) => { + if (buffer.length === 0) + return op_codes_1.OpCode.OP_0; + if (buffer.length !== 1) + return; + if (buffer[0] >= 1 && buffer[0] <= 16) + return exports.OP_INT_BASE + buffer[0]; + if (buffer[0] === 0x81) + return op_codes_1.OpCode.OP_1NEGATE; +}; +exports.asMinimalOP = asMinimalOP; +const ensureUInt = (value, max) => { + if (value < 0) + throw new Error("specified a negative value for writing an unsigned value"); + if (value > max) + throw new Error("RangeError: value out of range"); + if (Math.floor(value) !== value) + throw new Error(`value has a fractional component: ${value}`); +}; +exports.ensureUInt = ensureUInt; +const slice = (buffer, offset, length) => buffer.slice(offset, length); +exports.slice = slice; +const reverseBytes = (buffer) => { + let j = buffer.length - 1; + let tmp = 0; + for (let i = 0; i < buffer.length / 2; i++) { + tmp = buffer[i]; + buffer[i] = buffer[j]; + buffer[j] = tmp; + j--; + } + return buffer; +}; +exports.reverseBytes = reverseBytes; +const cloneBytes = (source, targetStart = 0, sourceStart, sourceEnd) => { + sourceStart = sourceStart !== null && sourceStart !== void 0 ? sourceStart : 0; + sourceEnd = sourceEnd !== null && sourceEnd !== void 0 ? sourceEnd : source.length; + const clone = new Uint8Array(sourceEnd - sourceStart); + clone.set(source.subarray(sourceStart, sourceEnd), targetStart); + return clone; +}; +exports.cloneBytes = cloneBytes; +const indexOfSubarray = (source, needle, fromIndex = 0) => { + if (needle.length === 0) + return fromIndex; + for (let i = fromIndex; i <= source.length - needle.length; i++) { + let match = true; + for (let j = 0; j < needle.length; j++) { + if (source[i + j] !== needle[j]) { + match = false; + break; + } + } + if (match) + return i; + } + return -1; +}; +const splitBytes = (source, splitBy) => { + let search = -1; + const move = 0; + const segments = []; + while ((search = indexOfSubarray(source, splitBy)) > -1) { + const segment = (0, exports.slice)(source, 0, search + move); + if (segment.length > 0) + segments.push(segment); + source = (0, exports.slice)(source, search + splitBy.length, source.length); + } + if (source.length > 0) + segments.push(source); + return segments; +}; +exports.splitBytes = splitBytes; +const getVarIntLength = (value) => value < 0xfd ? 1 : value <= 0xffff ? 3 : value <= 0xffffffff ? 5 : 9; +exports.getVarIntLength = getVarIntLength; +const getNumberSize = (data) => data > 0 && data <= 16 + ? 1 + : (0, exports.getVarIntLength)((0, exports.getMinimumRequiredByte)(data)) + + (0, exports.getMinimumRequiredByte)(data); +exports.getNumberSize = getNumberSize; +const asSafeInteger = (value) => { + if (!Number.isInteger(value)) { + throw new Error(`value has a fractional component: ${value}`); + } + if (!Number.isSafeInteger(value)) { + throw new Error(`value exceeds Number.MAX_SAFE_INTEGER bounds: ${value}`); + } + return value; +}; +const getMinimumRequiredByte = (value) => { + const safeValue = asSafeInteger(value); + const big = BigInt(safeValue); + for (let bytes = 1; bytes <= 8; bytes++) { + const bits = BigInt(bytes * 8 - 1); + const min = -(BigInt(1) << bits); + const max = (BigInt(1) << bits) - BigInt(1); + if (big >= min && big <= max) { + return bytes; + } + } + return 8; +}; +exports.getMinimumRequiredByte = getMinimumRequiredByte; +const getNumberBytes = (value) => { + const safeValue = asSafeInteger(value); + const size = (0, exports.getMinimumRequiredByte)(safeValue); + const buffer = new Uint8Array(size); + const sizeBits = BigInt(size * 8); + let big = BigInt(safeValue); + if (safeValue < 0) { + big = (BigInt(1) << sizeBits) + big; + } + for (let i = 0; i < size; i++) { + buffer[i] = Number(big & BigInt(0xff)); + big >>= BigInt(8); + } + return buffer; +}; +exports.getNumberBytes = getNumberBytes; +const estimateChunkSize = (bufferSize) => (0, exports.getVarIntLength)(bufferSize) + bufferSize; +exports.estimateChunkSize = estimateChunkSize; +const getChunkSize = (buffer) => (0, exports.estimateChunkSize)(buffer.length); +exports.getChunkSize = getChunkSize; +//# sourceMappingURL=buffer-utils.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.js.map b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.js.map new file mode 100644 index 0000000..a254890 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buffer-utils.js","sourceRoot":"","sources":["../../src/buffer/buffer-utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.d.ts b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.d.ts new file mode 100644 index 0000000..ce2610b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.d.ts @@ -0,0 +1,2 @@ +export { ByteWriter } from "../binary"; +//# sourceMappingURL=buffer-writer.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.d.ts.map new file mode 100644 index 0000000..8feb084 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"buffer-writer.d.ts","sourceRoot":"","sources":["../../src/buffer/buffer-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.js b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.js new file mode 100644 index 0000000..bc44259 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ByteWriter = void 0; +var binary_1 = require("../binary"); +Object.defineProperty(exports, "ByteWriter", { enumerable: true, get: function () { return binary_1.ByteWriter; } }); +//# sourceMappingURL=buffer-writer.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.js.map b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.js.map new file mode 100644 index 0000000..5f2550c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/buffer-writer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buffer-writer.js","sourceRoot":"","sources":["../../src/buffer/buffer-writer.ts"],"names":[],"mappings":";;;AAAA,oCAAuC;AAA9B,oGAAA,UAAU,OAAA"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/index.d.ts b/vendor/dxs-bsv-token-sdk/dist/buffer/index.d.ts new file mode 100644 index 0000000..fc6c2bf --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/index.d.ts @@ -0,0 +1,4 @@ +export * from "./buffer-reader"; +export * from "./buffer-utils"; +export * from "./buffer-writer"; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/index.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/buffer/index.d.ts.map new file mode 100644 index 0000000..ef9cb80 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/buffer/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/index.js b/vendor/dxs-bsv-token-sdk/dist/buffer/index.js new file mode 100644 index 0000000..936253c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/index.js @@ -0,0 +1,20 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./buffer-reader"), exports); +__exportStar(require("./buffer-utils"), exports); +__exportStar(require("./buffer-writer"), exports); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/buffer/index.js.map b/vendor/dxs-bsv-token-sdk/dist/buffer/index.js.map new file mode 100644 index 0000000..fcfd1a7 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/buffer/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/buffer/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,iDAA+B;AAC/B,kDAAgC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bytes.d.ts b/vendor/dxs-bsv-token-sdk/dist/bytes.d.ts new file mode 100644 index 0000000..d2ea04c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bytes.d.ts @@ -0,0 +1,8 @@ +export type Bytes = Uint8Array; +export declare const concat: (chunks: Bytes[]) => Bytes; +export declare const equal: (a: Bytes, b: Bytes) => boolean; +export declare const utf8ToBytes: (value: string) => Bytes; +export declare const bytesToUtf8: (value: Bytes) => string; +export declare const fromHex: (value: string) => Bytes; +export declare const toHex: (value: Bytes) => string; +//# sourceMappingURL=bytes.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bytes.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/bytes.d.ts.map new file mode 100644 index 0000000..b1fc0f1 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bytes.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG,UAAU,CAAC;AAK/B,eAAO,MAAM,MAAM,GAAI,QAAQ,KAAK,EAAE,KAAG,KAWxC,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,GAAG,KAAK,EAAE,GAAG,KAAK,KAAG,OAO1C,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,KAA8B,CAAC;AAC3E,eAAO,MAAM,WAAW,GAAI,OAAO,KAAK,KAAG,MAA+B,CAAC;AAE3E,eAAO,MAAM,OAAO,GAAI,OAAO,MAAM,KAAG,KAiBvC,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,OAAO,KAAK,KAAG,MAMpC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bytes.js b/vendor/dxs-bsv-token-sdk/dist/bytes.js new file mode 100644 index 0000000..14983f2 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bytes.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toHex = exports.fromHex = exports.bytesToUtf8 = exports.utf8ToBytes = exports.equal = exports.concat = void 0; +const encoder = new TextEncoder(); +const decoder = new TextDecoder(); +const concat = (chunks) => { + const total = chunks.reduce((a, c) => a + c.length, 0); + const out = new Uint8Array(total); + let offset = 0; + for (const chunk of chunks) { + out.set(chunk, offset); + offset += chunk.length; + } + return out; +}; +exports.concat = concat; +const equal = (a, b) => { + if (a.length !== b.length) + return false; + let result = 0; + for (let i = 0; i < a.length; i++) { + result |= a[i] ^ b[i]; + } + return result === 0; +}; +exports.equal = equal; +const utf8ToBytes = (value) => encoder.encode(value); +exports.utf8ToBytes = utf8ToBytes; +const bytesToUtf8 = (value) => decoder.decode(value); +exports.bytesToUtf8 = bytesToUtf8; +const fromHex = (value) => { + if (!/^[0-9a-fA-F]*$/.test(value)) { + throw new Error("Invalid hex string"); + } + const normalized = value.length % 2 === 0 ? value : `0${value}`; + const length = normalized.length / 2; + const out = new Uint8Array(length); + for (let i = 0; i < length; i++) { + const hi = Number.parseInt(normalized[i * 2], 16); + const lo = Number.parseInt(normalized[i * 2 + 1], 16); + const byte = (hi << 4) | lo; + out[i] = byte; + } + return out; +}; +exports.fromHex = fromHex; +const toHex = (value) => { + let result = ""; + for (const byte of value) { + result += byte.toString(16).padStart(2, "0"); + } + return result; +}; +exports.toHex = toHex; +//# sourceMappingURL=bytes.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/bytes.js.map b/vendor/dxs-bsv-token-sdk/dist/bytes.js.map new file mode 100644 index 0000000..5462a08 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/bytes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bytes.js","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.d.ts b/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.d.ts new file mode 100644 index 0000000..290248d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.d.ts @@ -0,0 +1,93 @@ +import { Address, OutPoint, Transaction, Wallet } from "./bitcoin"; +import { Bytes } from "./bytes"; +import { TransactionBuilder } from "./transaction"; +import { DstasLockingParams } from "./script/build/dstas-locking-builder"; +import { TDstasAssemblyPayment } from "./dstas-tx-assembly"; +export declare const AvgFeeForDstasMerge = 500; +export type TDstasFundingUtxoRequest = { + utxoIdsToSpend: string[]; + estimatedFeeSatoshis: number; + transactionsCount: number; +}; +export type TDstasGetUtxoFunction = (satoshis?: number) => Promise; +export type TDstasGetFundingUtxoFunction = (request: TDstasFundingUtxoRequest) => Promise; +export type TDstasGetTransactionsFunction = (ids: string[]) => Promise>; +export type TDstasPayoutBundle = { + transactions?: string[]; + feeSatoshis: number; + message?: string; + devMessage?: string; +}; +export type DstasSpendType = "transfer" | "split" | "merge" | "freeze" | "unfreeze" | "confiscation" | "swap"; +export type TDstasRecipient = { + m: number; + addresses: Address[]; +}; +export type TDstasTransferOutput = { + recipient: TDstasRecipient; + satoshis: number; +}; +export type TDstasTransferRequest = { + outputs: TDstasTransferOutput[]; + spendType?: "transfer" | "freeze" | "unfreeze"; + note?: Bytes[]; +}; +export type TDstasLockingParamsBuilder = (args: { + fromOutPoint: OutPoint; + recipient: TDstasRecipient; + spendType: DstasSpendType; + isFreezeLike: boolean; + outputIndex: number; + outputCount: number; + isChange: boolean; +}) => DstasLockingParams; +export type TDstasUnlockingScriptBuilder = { + (args: { + txBuilder: TransactionBuilder; + inputIndex: number; + outPoint: OutPoint; + spendType: DstasSpendType; + isFreezeLike: boolean; + isMerge: boolean; + }): Bytes; + estimateSize?: TDstasUnlockingScriptEstimator; +}; +export type TDstasUnlockingScriptEstimator = (args: Parameters[0]) => number; +export type TDstasPayment = TDstasAssemblyPayment; +export type TDstasDestination = { + Satoshis: number; + LockingParams: DstasLockingParams; +}; +export declare class DstasBundleFactory { + private readonly stasWallet; + private readonly feeWallet; + private readonly getFundingUtxo; + private readonly getStasUtxoSet; + private readonly getTransactions; + private readonly buildLockingParams; + private readonly buildUnlockingScript; + constructor(stasWallet: Wallet, feeWallet: Wallet, getFundingUtxo: TDstasGetFundingUtxoFunction, getStasUtxoSet: TDstasGetUtxoFunction, getTransactions: TDstasGetTransactionsFunction, buildLockingParams: TDstasLockingParamsBuilder, buildUnlockingScript: TDstasUnlockingScriptBuilder); + transfer: ({ outputs, spendType, note, }: TDstasTransferRequest) => Promise; + createTransferBundle: (amountSatoshis: number, recipient: TDstasRecipient, note?: Bytes[]) => Promise; + createFreezeBundle: (amountSatoshis: number, recipient: TDstasRecipient, note?: Bytes[]) => Promise; + createUnfreezeBundle: (amountSatoshis: number, recipient: TDstasRecipient, note?: Bytes[]) => Promise; + createSwapBundle: (amountSatoshis: number, recipient: TDstasRecipient, note?: Bytes[]) => Promise; + createConfiscationBundle: (amountSatoshis: number, recipient: TDstasRecipient, note?: Bytes[]) => Promise; + createBundle: (amountSatoshis: number, recipient: TDstasRecipient, spendType: DstasSpendType, note?: Bytes[]) => Promise; + private buildBundleWithResolvedFunding; + private estimateTransactionsCount; + private estimateMergeTransactionsCount; + private estimateFinalTransferTransactionsCount; + private estimateBundleFeeUpperBound; + private isInsufficientFeeError; + private _createTransferBundle; + private buildTransferPlanTransactions; + private getStasUtxo; + private mergeStasTransactions; + private buildDstasTx; + private buildDestinations; + private outPointFromTransaction; + private getStasOutPoint; + private getFeeOutPoint; +} +//# sourceMappingURL=dstas-bundle-factory.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.d.ts.map new file mode 100644 index 0000000..c58ba0d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-bundle-factory.d.ts","sourceRoot":"","sources":["../src/dstas-bundle-factory.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.js b/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.js new file mode 100644 index 0000000..4bca955 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.js @@ -0,0 +1,436 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DstasBundleFactory = exports.AvgFeeForDstasMerge = void 0; +const bitcoin_1 = require("./bitcoin"); +const transaction_1 = require("./transaction"); +const transaction_factory_1 = require("./transaction-factory"); +const dstas_tx_assembly_1 = require("./dstas-tx-assembly"); +exports.AvgFeeForDstasMerge = 500; +class DstasBundleFactory { + constructor(stasWallet, feeWallet, getFundingUtxo, getStasUtxoSet, getTransactions, buildLockingParams, buildUnlockingScript) { + this.stasWallet = stasWallet; + this.feeWallet = feeWallet; + this.getFundingUtxo = getFundingUtxo; + this.getStasUtxoSet = getStasUtxoSet; + this.getTransactions = getTransactions; + this.buildLockingParams = buildLockingParams; + this.buildUnlockingScript = buildUnlockingScript; + this.transfer = (_a) => __awaiter(this, [_a], void 0, function* ({ outputs, spendType = "transfer", note, }) { + if (outputs.length === 0) { + throw new Error("At least one transfer output is required"); + } + for (const output of outputs) { + if (!Number.isInteger(output.satoshis) || output.satoshis <= 0) { + throw new Error(`Transfer output satoshis must be a positive integer, got ${output.satoshis}`); + } + } + const amountSatoshis = outputs.reduce((sum, x) => sum + x.satoshis, 0); + const stasUtxoSet = (yield this.getStasUtxoSet(amountSatoshis)).sort((a, b) => a.Satoshis - b.Satoshis); + const availableSatoshis = stasUtxoSet.reduce((a, x) => a + x.Satoshis, 0); + if (availableSatoshis < amountSatoshis) { + return { + message: "Insufficient STAS tokens balance", + feeSatoshis: 0, + }; + } + const stasUtxos = this.getStasUtxo(stasUtxoSet, amountSatoshis); + return this.buildBundleWithResolvedFunding(stasUtxos, amountSatoshis, outputs, spendType, note); + }); + this.createTransferBundle = (amountSatoshis, recipient, note) => __awaiter(this, void 0, void 0, function* () { + return this.transfer({ + outputs: [{ recipient, satoshis: amountSatoshis }], + spendType: "transfer", + note, + }); + }); + this.createFreezeBundle = (amountSatoshis, recipient, note) => __awaiter(this, void 0, void 0, function* () { + return this.transfer({ + outputs: [{ recipient, satoshis: amountSatoshis }], + spendType: "freeze", + note, + }); + }); + this.createUnfreezeBundle = (amountSatoshis, recipient, note) => __awaiter(this, void 0, void 0, function* () { + return this.transfer({ + outputs: [{ recipient, satoshis: amountSatoshis }], + spendType: "unfreeze", + note, + }); + }); + this.createSwapBundle = (amountSatoshis, recipient, note) => __awaiter(this, void 0, void 0, function* () { return this.createBundle(amountSatoshis, recipient, "swap", note); }); + this.createConfiscationBundle = (amountSatoshis, recipient, note) => __awaiter(this, void 0, void 0, function* () { return this.createBundle(amountSatoshis, recipient, "confiscation", note); }); + this.createBundle = (amountSatoshis, recipient, spendType, note) => __awaiter(this, void 0, void 0, function* () { + const stasUtxoSet = (yield this.getStasUtxoSet(amountSatoshis)).sort((a, b) => a.Satoshis - b.Satoshis); + const availableSatoshis = stasUtxoSet.reduce((a, x) => a + x.Satoshis, 0); + if (availableSatoshis < amountSatoshis) + return { + message: "Insufficient STAS tokens balance", + feeSatoshis: 0, + }; + const stasUtxos = this.getStasUtxo(stasUtxoSet, amountSatoshis); + return this.buildBundleWithResolvedFunding(stasUtxos, amountSatoshis, [{ recipient, satoshis: amountSatoshis }], spendType, note); + }); + this.buildBundleWithResolvedFunding = (stasUtxos, amountSatoshis, outputs, spendType, note) => __awaiter(this, void 0, void 0, function* () { + const utxoIdsToSpend = stasUtxos.map((x) => `${x.TxId}:${x.Vout}`); + const transactionsCount = this.estimateTransactionsCount(stasUtxos.length, outputs.length); + const initialEstimatedFeeSatoshis = this.estimateBundleFeeUpperBound(transactionsCount, stasUtxos.length, outputs.length); + const firstFundingUtxo = yield this.getFundingUtxo({ + utxoIdsToSpend, + estimatedFeeSatoshis: initialEstimatedFeeSatoshis, + transactionsCount, + }); + try { + return this._createTransferBundle([], stasUtxos, amountSatoshis, firstFundingUtxo, outputs, spendType, note); + } + catch (error) { + if (!this.isInsufficientFeeError(error)) + throw error; + const fallbackEstimatedFeeSatoshis = Math.ceil(initialEstimatedFeeSatoshis * 1.5) + 200; + const secondFundingUtxo = yield this.getFundingUtxo({ + utxoIdsToSpend, + estimatedFeeSatoshis: fallbackEstimatedFeeSatoshis, + transactionsCount, + }); + return this._createTransferBundle([], stasUtxos, amountSatoshis, secondFundingUtxo, outputs, spendType, note); + } + }); + this.estimateTransactionsCount = (stasInputCount, outputsCount) => this.estimateMergeTransactionsCount(stasInputCount) + + this.estimateFinalTransferTransactionsCount(outputsCount); + this.estimateMergeTransactionsCount = (stasInputCount) => { + if (stasInputCount <= 1) + return 0; + let currentLevelCount = stasInputCount; + let levelsBeforeTransfer = 0; + let transactionCount = 0; + while (currentLevelCount !== 1) { + if (levelsBeforeTransfer === 3) { + levelsBeforeTransfer = 0; + transactionCount += currentLevelCount; + } + else { + levelsBeforeTransfer++; + const merges = Math.floor(currentLevelCount / 2); + const remainder = currentLevelCount % 2; + transactionCount += merges; + currentLevelCount = merges + remainder; + } + } + return transactionCount; + }; + this.estimateFinalTransferTransactionsCount = (outputsCount) => Math.max(1, Math.ceil((outputsCount - 1) / 3)); + this.estimateBundleFeeUpperBound = (transactionsCount, stasInputCount, outputsCount) => Math.max(1200, Math.ceil((transactionsCount * 1400 + + stasInputCount * 500 + + outputsCount * 160 + + 500) * + transaction_factory_1.FeeRate * + 1.5)); + this.isInsufficientFeeError = (error) => { + var _a; + if (!(error instanceof Error)) + return false; + const message = `${error.message}${(_a = error.stack) !== null && _a !== void 0 ? _a : ""}`; + return message.includes("Insufficient satoshis to pay fee"); + }; + this._createTransferBundle = (transactions, stasUtxos, satoshisToSend, feeUtxo, outputs, spendType, note) => __awaiter(this, void 0, void 0, function* () { + const { mergeTransactions, mergeFeeUtxo, stasUtxo } = yield this.mergeStasTransactions(stasUtxos, satoshisToSend, feeUtxo); + if (mergeTransactions) { + for (const mergeTx of mergeTransactions) { + transactions.push(mergeTx); + } + } + const { transactions: transferTransactions, feeOutPoint: feeUtxoOutPoint } = this.buildTransferPlanTransactions(stasUtxo, mergeFeeUtxo, outputs, spendType, note); + for (const tx of transferTransactions) { + transactions.push(tx); + } + const paidFee = feeUtxo.Satoshis - feeUtxoOutPoint.Satoshis; + return { transactions, feeSatoshis: paidFee }; + }); + this.buildTransferPlanTransactions = (stasUtxo, feeUtxo, outputs, spendType, note) => { + let cursor = 0; + let remainingTotal = outputs.reduce((sum, x) => sum + x.satoshis, 0); + const transactions = []; + const selfRecipient = { + m: 1, + addresses: [this.stasWallet.Address], + }; + let currentStas = stasUtxo; + let currentFee = feeUtxo; + while (cursor < outputs.length) { + if (remainingTotal !== currentStas.Satoshis) { + throw new Error("Transfer planner invariant failed: remaining outputs must match current STAS input"); + } + const remainingCount = outputs.length - cursor; + const isFinal = remainingCount <= 4; + const transferOutputs = isFinal + ? outputs.slice(cursor) + : outputs.slice(cursor, cursor + 3); + const sentSatoshis = transferOutputs.reduce((sum, x) => sum + x.satoshis, 0); + const txOutputs = transferOutputs.map((x) => ({ + recipient: x.recipient, + satoshis: x.satoshis, + isChange: false, + })); + if (!isFinal) { + txOutputs.push({ + recipient: selfRecipient, + satoshis: currentStas.Satoshis - sentSatoshis, + isChange: true, + }); + } + const destinations = this.buildDestinations(currentStas, txOutputs, spendType); + const txRaw = this.buildDstasTx({ + stasPayments: [{ OutPoint: currentStas, Owner: this.stasWallet }], + feePayment: { OutPoint: currentFee, Owner: this.feeWallet }, + destinations, + note: isFinal ? note : undefined, + spendType, + isMerge: false, + }); + const tx = transaction_1.TransactionReader.readHex(txRaw); + transactions.push(txRaw); + currentFee = this.getFeeOutPoint(tx); + if (isFinal) + break; + const changeOutputIndex = txOutputs.length - 1; + const changeOutput = tx.Outputs[changeOutputIndex]; + if (!changeOutput) { + throw new Error("Transfer planner failed to locate STAS change output"); + } + currentStas = this.outPointFromTransaction(tx, changeOutputIndex); + cursor += transferOutputs.length; + remainingTotal -= sentSatoshis; + } + return { + transactions, + feeOutPoint: currentFee, + }; + }; + this.getStasUtxo = (utxos, satoshis) => { + const exactOrGreater = utxos.find((x) => x.Satoshis >= satoshis); + if (exactOrGreater && exactOrGreater.Satoshis === satoshis) { + return [exactOrGreater]; + } + const result = []; + let accumulated = 0; + for (const utxo of utxos) { + result.push(utxo); + accumulated += utxo.Satoshis; + if (accumulated >= satoshis) + return result; + } + return [exactOrGreater]; + }; + this.mergeStasTransactions = (stasUtxos, satoshis, mergeFeeUtxo) => __awaiter(this, void 0, void 0, function* () { + if (stasUtxos.length === 1) + return { mergeFeeUtxo, stasUtxo: stasUtxos[0] }; + const mergeTransactions = []; + const utxos = stasUtxos.map(({ TxId, Vout }) => ({ + TxId, + Vout, + })); + const txIds = Array.from(new Set(stasUtxos.map(({ TxId }) => TxId))); + const sourceTransactions = yield this.getTransactions(txIds); + const mergeLevels = [[]]; + for (const { TxId, Vout } of utxos) { + const tx = sourceTransactions[TxId]; + if (!tx) + throw new Error(`Transaction ${TxId} not found`); + mergeLevels[0].push(this.outPointFromTransaction(tx, Vout)); + } + const feePayment = { + OutPoint: mergeFeeUtxo, + Owner: this.feeWallet, + }; + let currentLevel = mergeLevels[0]; + let levelsBeforeTransfer = 0; + let stasUtxo = stasUtxos[0]; + while (currentLevel.length !== 1) { + const newLevel = []; + mergeLevels.push(newLevel); + if (levelsBeforeTransfer === 3) { + levelsBeforeTransfer = 0; + for (const outPoint of currentLevel) { + const stasPayment = { + OutPoint: outPoint, + Owner: this.stasWallet, + }; + const destinations = this.buildDestinations(outPoint, [ + { + recipient: { + m: 1, + addresses: [this.stasWallet.Address], + }, + satoshis: outPoint.Satoshis, + isChange: false, + }, + ], "transfer"); + const txRaw = this.buildDstasTx({ + stasPayments: [stasPayment], + feePayment, + destinations, + spendType: "transfer", + isMerge: false, + }); + const tx = transaction_1.TransactionReader.readHex(txRaw); + newLevel.push(this.getStasOutPoint(tx)); + mergeTransactions.push(txRaw); + stasUtxo = this.getStasOutPoint(tx); + feePayment.OutPoint = this.getFeeOutPoint(tx); + } + } + else { + levelsBeforeTransfer++; + const mergeCounts = Math.floor(currentLevel.length / 2); + const remainder = currentLevel.length % 2; + if (remainder !== 0) + newLevel.push(currentLevel[currentLevel.length - 1]); + let currentIdx = 0; + for (let i = 0; i < mergeCounts; i++) { + const outPoint1 = currentLevel[currentIdx++]; + const outPoint2 = currentLevel[currentIdx++]; + const lastMerge = mergeCounts === 1 && remainder === 0; + const inputSatoshis = outPoint1.Satoshis + outPoint2.Satoshis; + let outputs = [ + { + recipient: { + m: 1, + addresses: [this.stasWallet.Address], + }, + satoshis: inputSatoshis, + isChange: false, + }, + ]; + if (lastMerge && inputSatoshis !== satoshis) { + outputs = [ + { + recipient: { + m: 1, + addresses: [this.stasWallet.Address], + }, + satoshis, + isChange: false, + }, + { + recipient: { + m: 1, + addresses: [this.stasWallet.Address], + }, + satoshis: inputSatoshis - satoshis, + isChange: true, + }, + ]; + } + const destinations = this.buildDestinations(outPoint1, outputs, "merge"); + const txRaw = this.buildDstasTx({ + stasPayments: [ + { OutPoint: outPoint1, Owner: this.stasWallet }, + { OutPoint: outPoint2, Owner: this.stasWallet }, + ], + feePayment, + destinations, + spendType: "merge", + isMerge: true, + }); + const tx = transaction_1.TransactionReader.readHex(txRaw); + newLevel.push(this.getStasOutPoint(tx)); + mergeTransactions.push(txRaw); + stasUtxo = this.getStasOutPoint(tx); + feePayment.OutPoint = this.getFeeOutPoint(tx); + } + } + currentLevel = newLevel; + } + return { mergeTransactions, mergeFeeUtxo: feePayment.OutPoint, stasUtxo }; + }); + this.buildDstasTx = (params) => { + const { stasPayments, feePayment, destinations, note, feeRate, spendType, isMerge, } = params; + if (stasPayments.length === 0) + throw new Error("At least one STAS input is required"); + if (destinations.length === 0) + throw new Error("At least one destination is required"); + (0, dstas_tx_assembly_1.validateDstasAmounts)(stasPayments, destinations); + return (0, dstas_tx_assembly_1.buildSignedDstasTransaction)({ + stasPayments, + feePayment, + destinations, + note, + feeRate: feeRate !== null && feeRate !== void 0 ? feeRate : transaction_factory_1.FeeRate, + isMerge, + configureStasInput: ({ phase, txBuilder, inputIndex }) => { + const input = txBuilder.Inputs[inputIndex]; + input.AllowPresetUnlockingScript = true; + const unlockingArgs = { + txBuilder, + inputIndex, + outPoint: input.OutPoint, + spendType, + isFreezeLike: spendType === "freeze" || spendType === "unfreeze", + isMerge, + }; + if (typeof this.buildUnlockingScript.estimateSize === "function") { + if (phase === "estimate") { + input.PresetUnlockingScriptSizeHint = + this.buildUnlockingScript.estimateSize(unlockingArgs); + input.UnlockingScript = undefined; + return; + } + input.PresetUnlockingScriptSizeHint = undefined; + input.UnlockingScript = this.buildUnlockingScript(unlockingArgs); + return; + } + input.UnlockingScript = this.buildUnlockingScript(unlockingArgs); + }, + }); + }; + this.buildDestinations = (sourceOutPoint, outputs, spendType) => { + const outputCount = outputs.length; + return outputs.map((output, index) => ({ + Satoshis: output.satoshis, + LockingParams: this.buildLockingParams({ + fromOutPoint: sourceOutPoint, + recipient: output.recipient, + spendType, + isFreezeLike: spendType === "freeze" || spendType === "unfreeze", + outputIndex: index, + outputCount, + isChange: output.isChange, + }), + })); + }; + this.outPointFromTransaction = (tx, vout) => { + const output = tx.Outputs[vout]; + const outPoint = new bitcoin_1.OutPoint(tx.Id, vout, output.LockingScript, output.Satoshis, output.Address, output.ScriptType); + outPoint.Transaction = tx; + return outPoint; + }; + this.getStasOutPoint = (tx) => { + const index = tx.Outputs.findIndex((output) => output.ScriptType !== bitcoin_1.ScriptType.p2pkh && + output.ScriptType !== bitcoin_1.ScriptType.p2mpkh && + output.ScriptType !== bitcoin_1.ScriptType.nullData); + if (index === -1) + throw new Error("STAS output not found"); + return this.outPointFromTransaction(tx, index); + }; + this.getFeeOutPoint = (tx) => { + for (let i = tx.Outputs.length - 1; i >= 0; i--) { + const output = tx.Outputs[i]; + if (output.ScriptType === bitcoin_1.ScriptType.p2pkh || + output.ScriptType === bitcoin_1.ScriptType.p2mpkh) { + return new bitcoin_1.OutPoint(tx.Id, i, output.LockingScript, output.Satoshis, output.Address, output.ScriptType); + } + } + throw new Error("Fee output not found"); + }; + } +} +exports.DstasBundleFactory = DstasBundleFactory; +//# sourceMappingURL=dstas-bundle-factory.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.js.map b/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.js.map new file mode 100644 index 0000000..1005b15 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-bundle-factory.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-bundle-factory.js","sourceRoot":"","sources":["../src/dstas-bundle-factory.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-factory.d.ts b/vendor/dxs-bsv-token-sdk/dist/dstas-factory.d.ts new file mode 100644 index 0000000..f0bcf51 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-factory.d.ts @@ -0,0 +1,110 @@ +import { Address, TPayment, TokenScheme } from "./bitcoin"; +import { Bytes } from "./bytes"; +import { ActionDataInput, DstasLockingParams } from "./script/build/dstas-locking-builder"; +import { TDstasAssemblyPayment } from "./dstas-tx-assembly"; +export type TDstasPayment = TDstasAssemblyPayment; +export type TDstasDestinationByLockingParams = { + Satoshis: number; + LockingParams: DstasLockingParams; +}; +export type TDstasDestinationByScheme = { + Satoshis: number; + To?: Address; + ToOwner?: Bytes; + ToOwnerMultisig?: { + m: number; + publicKeys: string[]; + }; + ActionData?: ActionDataInput; + Frozen?: boolean; + OptionalData?: Bytes[]; +}; +export type TDstasDestination = TDstasDestinationByLockingParams | TDstasDestinationByScheme; +export type TBuildDstasBaseTxRequest = { + stasPayments: TDstasPayment[]; + feePayment: TPayment; + destinations: TDstasDestination[]; + scheme?: TokenScheme; + spendingType?: number; + note?: Bytes[]; + feeRate?: number; + omitChangeOutput?: boolean; +}; +export type TBuildDstasIssueTxsRequest = { + fundingPayment: TPayment; + scheme: TokenScheme; + destinations: TDstasDestinationByScheme[]; + feeRate?: number; +}; +export type TBuildDstasIssueTxsResult = { + contractTxHex: string; + issueTxHex: string; +}; +export declare const BuildDstasBaseTx: ({ stasPayments, feePayment, destinations, scheme, spendingType, note, feeRate, omitChangeOutput, }: TBuildDstasBaseTxRequest) => string; +export declare const BuildDstasIssueTxs: ({ fundingPayment, scheme, destinations, feeRate, }: TBuildDstasIssueTxsRequest) => TBuildDstasIssueTxsResult; +export type TBuildDstasFreezeTxRequest = TBuildDstasBaseTxRequest; +export declare const BuildDstasFreezeTx: (request: TBuildDstasFreezeTxRequest) => string; +export type TBuildDstasUnfreezeTxRequest = TBuildDstasBaseTxRequest; +export declare const BuildDstasUnfreezeTx: (request: TBuildDstasUnfreezeTxRequest) => string; +export type TBuildDstasSwapTxRequest = TBuildDstasBaseTxRequest; +export declare const BuildDstasSwapTx: (request: TBuildDstasSwapTxRequest) => string; +export type TBuildDstasConfiscateTxRequest = TBuildDstasBaseTxRequest; +export declare const BuildDstasConfiscateTx: (request: TBuildDstasConfiscateTxRequest) => string; +export type TDstasSwapDestination = { + Satoshis: number; + Owner: Bytes; + TokenIdHex: string; + Freezable: boolean; + Confiscatable?: boolean; + FreezeAuthorityServiceField?: Bytes; + ConfiscationAuthorityServiceField?: Bytes; + ActionData?: ActionDataInput; + OptionalData?: Bytes[]; +}; +export type TBuildDstasSwapFlowTxRequest = { + stasPayments: [TDstasPayment, TDstasPayment]; + feePayment: TPayment; + destinations: TDstasSwapDestination[]; + note?: Bytes[]; + feeRate?: number; + omitChangeOutput?: boolean; +}; +export type TDstasSwapMode = "auto" | "transfer-swap" | "swap-swap"; +export declare const ResolveDstasSwapMode: (stasPayments: [TDstasPayment, TDstasPayment]) => Exclude; +export declare const BuildDstasTransferSwapTx: ({ stasPayments, feePayment, destinations, note, feeRate, omitChangeOutput, }: TBuildDstasSwapFlowTxRequest) => string; +export declare const BuildDstasSwapSwapTx: ({ stasPayments, feePayment, destinations, note, feeRate, omitChangeOutput, }: TBuildDstasSwapFlowTxRequest) => string; +export type TBuildDstasSwapFlowAutoTxRequest = TBuildDstasSwapFlowTxRequest & { + mode?: TDstasSwapMode; +}; +export declare const BuildDstasSwapFlowTx: ({ mode, ...request }: TBuildDstasSwapFlowAutoTxRequest) => string; +export type TBuildDstasMultisigTxRequest = TBuildDstasBaseTxRequest; +export declare const BuildDstasMultisigTx: (request: TBuildDstasMultisigTxRequest) => string; +export type TBuildDstasTransferTxRequest = { + stasPayment: TDstasPayment; + feePayment: TPayment; + destination: TDstasDestination; + scheme?: TokenScheme; + note?: Bytes[]; + feeRate?: number; + omitChangeOutput?: boolean; +}; +export declare const BuildDstasTransferTx: ({ stasPayment, feePayment, destination, scheme, note, feeRate, omitChangeOutput, }: TBuildDstasTransferTxRequest) => string; +export type TBuildDstasSplitTxRequest = { + stasPayment: TDstasPayment; + feePayment: TPayment; + destinations: TDstasDestination[]; + scheme?: TokenScheme; + note?: Bytes[]; + feeRate?: number; +}; +export declare const BuildDstasSplitTx: ({ stasPayment, feePayment, destinations, scheme, note, feeRate, }: TBuildDstasSplitTxRequest) => string; +export type TBuildDstasMergeTxRequest = { + stasPayments: [TDstasPayment, TDstasPayment]; + feePayment: TPayment; + destinations: TDstasDestination[]; + scheme?: TokenScheme; + note?: Bytes[]; + feeRate?: number; +}; +export declare const BuildDstasMergeTx: ({ stasPayments, feePayment, destinations, scheme, note, feeRate, }: TBuildDstasMergeTxRequest) => string; +//# sourceMappingURL=dstas-factory.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-factory.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/dstas-factory.d.ts.map new file mode 100644 index 0000000..8f7142b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-factory.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-factory.d.ts","sourceRoot":"","sources":["../src/dstas-factory.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-factory.js b/vendor/dxs-bsv-token-sdk/dist/dstas-factory.js new file mode 100644 index 0000000..bca8105 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-factory.js @@ -0,0 +1,360 @@ +"use strict"; +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BuildDstasMergeTx = exports.BuildDstasSplitTx = exports.BuildDstasTransferTx = exports.BuildDstasMultisigTx = exports.BuildDstasSwapFlowTx = exports.BuildDstasSwapSwapTx = exports.BuildDstasTransferSwapTx = exports.ResolveDstasSwapMode = exports.BuildDstasConfiscateTx = exports.BuildDstasSwapTx = exports.BuildDstasUnfreezeTx = exports.BuildDstasFreezeTx = exports.BuildDstasIssueTxs = exports.BuildDstasBaseTx = void 0; +const bitcoin_1 = require("./bitcoin"); +const script_type_1 = require("./bitcoin/script-type"); +const bytes_1 = require("./bytes"); +const dstas_locking_builder_1 = require("./script/build/dstas-locking-builder"); +const transaction_builder_1 = require("./transaction/build/transaction-builder"); +const transaction_reader_1 = require("./transaction/read/transaction-reader"); +const transaction_factory_1 = require("./transaction-factory"); +const hashes_1 = require("./hashes"); +const locking_script_reader_1 = require("./script/read/locking-script-reader"); +const secp256k1_1 = require("@noble/secp256k1"); +const dstas_tx_assembly_1 = require("./dstas-tx-assembly"); +const resolveUnlockingScript = (payment) => payment.UnlockingScript; +const deriveFlagsFromScheme = (scheme) => (0, dstas_locking_builder_1.buildDstasFlags)({ + freezable: scheme.Freeze, + confiscatable: scheme.Confiscation, +}); +const isCompressedPubKey = (key) => key.length === 33 && (key[0] === 0x02 || key[0] === 0x03); +const validateMultisigPolicy = (m, n, role) => { + if (n <= 0) { + throw new Error(`${role} must define at least one public key`); + } + if (n > 5) { + throw new Error(`${role} supports at most 5 public keys, got ${n}`); + } + if (m <= 0 || m > n) { + throw new Error(`${role} has invalid threshold m=${m}, n=${n}`); + } +}; +const validateMultisigPublicKeys = (keys, role) => { + const seen = new Set(); + for (const keyHex of keys) { + const normalized = keyHex.toLowerCase(); + const key = (0, bytes_1.fromHex)(keyHex); + if (!isCompressedPubKey(key)) { + throw new Error(`${role} public key must be a compressed SEC key`); + } + try { + secp256k1_1.Point.fromHex(normalized); + } + catch (_a) { + throw new Error(`${role} public key must be a valid compressed secp256k1 point`); + } + if (seen.has(normalized)) { + throw new Error(`${role} contains duplicate public keys`); + } + seen.add(normalized); + } +}; +const buildAuthorityServiceField = (authority, role) => { + var _a, _b; + const keys = (_a = authority === null || authority === void 0 ? void 0 : authority.publicKeys) !== null && _a !== void 0 ? _a : []; + if (keys.length === 0) { + throw new Error(`${role} authority must define at least one public key for service field derivation`); + } + const m = (_b = authority === null || authority === void 0 ? void 0 : authority.m) !== null && _b !== void 0 ? _b : 1; + const n = keys.length; + validateMultisigPolicy(m, n, `${role} authority`); + validateMultisigPublicKeys(keys, `${role} authority`); + if (m === 1 && n === 1) { + return (0, hashes_1.hash160)((0, bytes_1.fromHex)(keys[0])); + } + const preimage = new Uint8Array(1 + n * (1 + 33) + 1); + let offset = 0; + preimage[offset++] = m & 0xff; + for (const keyHex of keys) { + const key = (0, bytes_1.fromHex)(keyHex); + if (key.length !== 33) { + throw new Error(`${role} authority public key must be 33 bytes`); + } + preimage[offset++] = 0x21; + preimage.set(key, offset); + offset += key.length; + } + preimage[offset] = n & 0xff; + return (0, hashes_1.hash160)(preimage); +}; +const deriveServiceFieldsFromScheme = (scheme) => { + const serviceFields = []; + if (scheme.Freeze) { + serviceFields.push(buildAuthorityServiceField(scheme.FreezeAuthority, "freeze")); + } + if (scheme.Confiscation) { + serviceFields.push(buildAuthorityServiceField(scheme.ConfiscationAuthority, "confiscation")); + } + return serviceFields; +}; +const resolveLockingParams = (dest, schemeFromRequest) => { + var _a, _b, _c, _d; + if ("LockingParams" in dest) + return dest.LockingParams; + const scheme = schemeFromRequest; + if (!scheme) { + throw new Error("scheme must be provided at request level when destination does not define LockingParams"); + } + const ownerFromMultisig = (() => { + if (!dest.ToOwnerMultisig) + return undefined; + const { m, publicKeys } = dest.ToOwnerMultisig; + if (publicKeys.length === 0) { + throw new Error("ToOwnerMultisig.publicKeys must not be empty"); + } + validateMultisigPolicy(m, publicKeys.length, "ToOwnerMultisig"); + validateMultisigPublicKeys(publicKeys, "ToOwnerMultisig"); + const preimage = new Uint8Array(1 + publicKeys.length * (1 + 33) + 1); + let off = 0; + preimage[off++] = m & 0xff; + for (const keyHex of publicKeys) { + const key = (0, bytes_1.fromHex)(keyHex); + if (key.length !== 33) { + throw new Error(`ToOwnerMultisig public key must be 33 bytes, got ${key.length}`); + } + preimage[off++] = 0x21; + preimage.set(key, off); + off += key.length; + } + preimage[off] = publicKeys.length & 0xff; + return (0, hashes_1.hash160)(preimage); + })(); + const owner = (_b = (_a = dest.ToOwner) !== null && _a !== void 0 ? _a : ownerFromMultisig) !== null && _b !== void 0 ? _b : (_c = dest.To) === null || _c === void 0 ? void 0 : _c.Hash160; + if (!owner) { + throw new Error("Destination must provide To (address) or ToOwner (raw owner field bytes)"); + } + return { + owner, + actionData: (_d = dest.ActionData) !== null && _d !== void 0 ? _d : null, + redemptionPkh: (0, bytes_1.fromHex)(scheme.TokenId), + frozen: dest.Frozen === true, + flags: deriveFlagsFromScheme(scheme), + serviceFields: deriveServiceFieldsFromScheme(scheme), + optionalData: dest.OptionalData !== undefined ? dest.OptionalData : [], + }; +}; +const validateDestinationSatoshis = (destinations) => { + for (const [idx, destination] of destinations.entries()) { + if (!Number.isInteger(destination.Satoshis) || destination.Satoshis <= 0) { + throw new Error(`Destination[${idx}] satoshis must be a positive integer, got ${destination.Satoshis}`); + } + } +}; +const validateFundingAgainstScheme = (fundingPayment, scheme) => { + const issuerTokenId = (0, bytes_1.toHex)(fundingPayment.OutPoint.Address.Hash160); + if (issuerTokenId.toLowerCase() !== scheme.TokenId.toLowerCase()) { + throw new Error(`scheme.TokenId must match issuer address hash160 (${issuerTokenId})`); + } +}; +const BuildDstasBaseTx = ({ stasPayments, feePayment, destinations, scheme, spendingType, note, feeRate = transaction_factory_1.FeeRate, omitChangeOutput = false, }) => { + if (stasPayments.length === 0) + throw new Error("At least one STAS input is required"); + if (stasPayments.length > 2) + throw new Error("At most 2 STAS inputs are supported"); + if (destinations.length === 0) + throw new Error("At least one destination is required"); + validateDestinationSatoshis(destinations); + const resolvedDestinations = destinations.map((destination) => ({ + Satoshis: destination.Satoshis, + LockingParams: resolveLockingParams(destination, scheme), + })); + return (0, dstas_tx_assembly_1.buildSignedDstasTransaction)({ + stasPayments, + feePayment, + destinations: resolvedDestinations, + note, + feeRate, + omitChangeOutput, + isMerge: stasPayments.length > 1, + configureStasInput: ({ phase, txBuilder, inputIndex, payment }) => { + txBuilder.Inputs[inputIndex].DstasSpendingType = spendingType !== null && spendingType !== void 0 ? spendingType : 1; + const unlocking = resolveUnlockingScript(payment); + if (unlocking) { + txBuilder.Inputs[inputIndex].AllowPresetUnlockingScript = true; + if (phase === "estimate") { + txBuilder.Inputs[inputIndex].PresetUnlockingScriptSizeHint = + unlocking.length; + txBuilder.Inputs[inputIndex].UnlockingScript = undefined; + } + else { + txBuilder.Inputs[inputIndex].PresetUnlockingScriptSizeHint = + undefined; + txBuilder.Inputs[inputIndex].UnlockingScript = unlocking; + } + } + }, + }); +}; +exports.BuildDstasBaseTx = BuildDstasBaseTx; +const BuildDstasIssueTxs = ({ fundingPayment, scheme, destinations, feeRate = transaction_factory_1.FeeRate, }) => { + if (destinations.length === 0) + throw new Error("At least one destination is required"); + validateDestinationSatoshis(destinations); + validateFundingAgainstScheme(fundingPayment, scheme); + const totalIssueSatoshis = destinations.reduce((sum, d) => sum + d.Satoshis, 0); + const contractChangeBudget = fundingPayment.OutPoint.Satoshis - totalIssueSatoshis; + if (contractChangeBudget <= 0) { + throw new Error("Funding output must be greater than total tokenized satoshis"); + } + const contractTxHex = transaction_builder_1.TransactionBuilder.init() + .addInput(fundingPayment.OutPoint, fundingPayment.Owner) + .addP2PkhOutput(totalIssueSatoshis, fundingPayment.OutPoint.Address, [ + scheme.toBytes(), + ]) + .addChangeOutputWithFee(fundingPayment.OutPoint.Address, contractChangeBudget, feeRate) + .sign() + .toHex(); + const contractTx = transaction_reader_1.TransactionReader.readHex(contractTxHex); + const contractOutPoint = new bitcoin_1.OutPoint(contractTx.Id, 0, contractTx.Outputs[0].LockingScript, contractTx.Outputs[0].Satoshis, fundingPayment.OutPoint.Address, script_type_1.ScriptType.p2pkh); + const contractChangeOutput = contractTx.Outputs[1]; + if (!contractChangeOutput) { + throw new Error("Contract tx does not have a change output to fund issue tx fee"); + } + const contractChangeOutPoint = new bitcoin_1.OutPoint(contractTx.Id, 1, contractChangeOutput.LockingScript, contractChangeOutput.Satoshis, fundingPayment.OutPoint.Address, script_type_1.ScriptType.p2pkh); + const issueTxHex = (0, dstas_tx_assembly_1.buildSignedDstasIssueTransaction)({ + contractOutPoint: { + OutPoint: contractOutPoint, + Owner: fundingPayment.Owner, + }, + contractChangeOutPoint: { + OutPoint: contractChangeOutPoint, + Owner: fundingPayment.Owner, + }, + contractOwner: fundingPayment.Owner, + destinations: destinations.map((dest) => ({ + Satoshis: dest.Satoshis, + LockingParams: resolveLockingParams(dest, scheme), + })), + feeRate, + }); + return { contractTxHex, issueTxHex }; +}; +exports.BuildDstasIssueTxs = BuildDstasIssueTxs; +const BuildDstasFreezeTx = (request) => (0, exports.BuildDstasBaseTx)(Object.assign(Object.assign({}, request), { spendingType: 2 })); +exports.BuildDstasFreezeTx = BuildDstasFreezeTx; +const BuildDstasUnfreezeTx = (request) => (0, exports.BuildDstasBaseTx)(Object.assign(Object.assign({}, request), { spendingType: 2 })); +exports.BuildDstasUnfreezeTx = BuildDstasUnfreezeTx; +const BuildDstasSwapTx = (request) => (0, exports.BuildDstasBaseTx)(Object.assign(Object.assign({}, request), { spendingType: 4 })); +exports.BuildDstasSwapTx = BuildDstasSwapTx; +const BuildDstasConfiscateTx = (request) => (0, exports.BuildDstasBaseTx)(Object.assign(Object.assign({}, request), { spendingType: 3 })); +exports.BuildDstasConfiscateTx = BuildDstasConfiscateTx; +const hasSwapActionData = (payment) => { + var _a, _b; + const reader = locking_script_reader_1.LockingScriptReader.read(payment.OutPoint.LockingScript); + if (reader.ScriptType !== script_type_1.ScriptType.dstas) + return false; + return ((_b = (_a = reader.Dstas) === null || _a === void 0 ? void 0 : _a.ActionDataParsed) === null || _b === void 0 ? void 0 : _b.kind) === "swap"; +}; +const ResolveDstasSwapMode = (stasPayments) => { + const [left, right] = stasPayments; + const leftIsSwap = hasSwapActionData(left); + const rightIsSwap = hasSwapActionData(right); + return leftIsSwap && rightIsSwap ? "swap-swap" : "transfer-swap"; +}; +exports.ResolveDstasSwapMode = ResolveDstasSwapMode; +const toSwapFlowDestination = (value) => { + var _a; + if (value.Freezable && !value.FreezeAuthorityServiceField) { + throw new Error("FreezeAuthorityServiceField is required when Freezable=true"); + } + if (value.Confiscatable && !value.ConfiscationAuthorityServiceField) { + throw new Error("ConfiscationAuthorityServiceField is required when Confiscatable=true"); + } + return { + Satoshis: value.Satoshis, + LockingParams: { + owner: value.Owner, + actionData: value.ActionData !== undefined ? value.ActionData : null, + redemptionPkh: (0, bytes_1.fromHex)(value.TokenIdHex), + flags: (0, dstas_locking_builder_1.buildDstasFlags)({ + freezable: value.Freezable, + confiscatable: value.Confiscatable === true, + }), + serviceFields: [ + ...(value.Freezable + ? [value.FreezeAuthorityServiceField] + : []), + ...(value.Confiscatable + ? [value.ConfiscationAuthorityServiceField] + : []), + ], + optionalData: (_a = value.OptionalData) !== null && _a !== void 0 ? _a : [], + }, + }; +}; +const BuildDstasTransferSwapTx = ({ stasPayments, feePayment, destinations, note, feeRate, omitChangeOutput, }) => (0, exports.BuildDstasBaseTx)({ + stasPayments, + feePayment, + destinations: destinations.map(toSwapFlowDestination), + note, + feeRate, + omitChangeOutput, + spendingType: 1, +}); +exports.BuildDstasTransferSwapTx = BuildDstasTransferSwapTx; +const BuildDstasSwapSwapTx = ({ stasPayments, feePayment, destinations, note, feeRate, omitChangeOutput, }) => (0, exports.BuildDstasBaseTx)({ + stasPayments, + feePayment, + destinations: destinations.map(toSwapFlowDestination), + note, + feeRate, + omitChangeOutput, + spendingType: 4, +}); +exports.BuildDstasSwapSwapTx = BuildDstasSwapSwapTx; +const BuildDstasSwapFlowTx = (_a) => { + var { mode = "auto" } = _a, request = __rest(_a, ["mode"]); + const resolvedMode = mode === "auto" ? (0, exports.ResolveDstasSwapMode)(request.stasPayments) : mode; + if (resolvedMode === "swap-swap") { + return (0, exports.BuildDstasSwapSwapTx)(request); + } + return (0, exports.BuildDstasTransferSwapTx)(request); +}; +exports.BuildDstasSwapFlowTx = BuildDstasSwapFlowTx; +const BuildDstasMultisigTx = (request) => (0, exports.BuildDstasBaseTx)(request); +exports.BuildDstasMultisigTx = BuildDstasMultisigTx; +const BuildDstasTransferTx = ({ stasPayment, feePayment, destination, scheme, note, feeRate, omitChangeOutput, }) => (0, exports.BuildDstasBaseTx)({ + stasPayments: [stasPayment], + feePayment, + destinations: [destination], + scheme, + note, + feeRate, + omitChangeOutput, +}); +exports.BuildDstasTransferTx = BuildDstasTransferTx; +const BuildDstasSplitTx = ({ stasPayment, feePayment, destinations, scheme, note, feeRate, }) => (0, exports.BuildDstasBaseTx)({ + stasPayments: [stasPayment], + feePayment, + destinations, + scheme, + note, + feeRate, +}); +exports.BuildDstasSplitTx = BuildDstasSplitTx; +const BuildDstasMergeTx = ({ stasPayments, feePayment, destinations, scheme, note, feeRate, }) => { + if (stasPayments.length !== 2) { + throw new Error("DSTAS merge requires exactly 2 STAS inputs"); + } + return (0, exports.BuildDstasBaseTx)({ + stasPayments, + feePayment, + destinations, + scheme, + note, + feeRate, + }); +}; +exports.BuildDstasMergeTx = BuildDstasMergeTx; +//# sourceMappingURL=dstas-factory.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-factory.js.map b/vendor/dxs-bsv-token-sdk/dist/dstas-factory.js.map new file mode 100644 index 0000000..4a0d491 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-factory.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-factory.js","sourceRoot":"","sources":["../src/dstas-factory.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.d.ts b/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.d.ts new file mode 100644 index 0000000..dc18e0a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.d.ts @@ -0,0 +1,43 @@ +import { TPayment } from "./bitcoin"; +import { Bytes } from "./bytes"; +import { DstasLockingParams } from "./script/build/dstas-locking-builder"; +import { ScriptBuilder } from "./script/build/script-builder"; +import { TransactionBuilder } from "./transaction/build/transaction-builder"; +export type TDstasAssemblyPayment = TPayment & { + UnlockingScript?: Bytes; +}; +export type TDstasAssemblyDestination = { + Satoshis: number; + LockingParams: DstasLockingParams; +}; +type TDstasConfigurePhase = "estimate" | "finalize"; +export declare const buildDstasLockingScriptBuilder: (params: DstasLockingParams) => ScriptBuilder; +export declare const validateDstasAmounts: (stasPayments: TDstasAssemblyPayment[], destinations: { + Satoshis: number; +}[]) => void; +export declare const buildSignedDstasTransaction: ({ stasPayments, feePayment, destinations, note, feeRate, omitChangeOutput, isMerge, configureStasInput, }: { + stasPayments: TDstasAssemblyPayment[]; + feePayment: TPayment; + destinations: TDstasAssemblyDestination[]; + note?: Bytes[]; + feeRate?: number; + omitChangeOutput?: boolean; + isMerge?: boolean; + configureStasInput?: (args: { + phase: TDstasConfigurePhase; + txBuilder: TransactionBuilder; + inputIndex: number; + payment: TDstasAssemblyPayment; + stasInputIndex: number; + isMerge: boolean; + }) => void; +}) => string; +export declare const buildSignedDstasIssueTransaction: ({ contractOutPoint, contractChangeOutPoint, contractOwner, destinations, feeRate, }: { + contractOutPoint: TPayment; + contractChangeOutPoint: TPayment; + contractOwner: TPayment["Owner"]; + destinations: TDstasAssemblyDestination[]; + feeRate?: number; +}) => string; +export {}; +//# sourceMappingURL=dstas-tx-assembly.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.d.ts.map new file mode 100644 index 0000000..a84c7e7 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-tx-assembly.d.ts","sourceRoot":"","sources":["../src/dstas-tx-assembly.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EACL,kBAAkB,EAEnB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAG7E,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG;IAC7C,eAAe,CAAC,EAAE,KAAK,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,kBAAkB,CAAC;CACnC,CAAC;AAEF,KAAK,oBAAoB,GAAG,UAAU,GAAG,UAAU,CAAC;AAEpD,eAAO,MAAM,8BAA8B,GAAI,QAAQ,kBAAkB,kBAGxE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,cAAc,qBAAqB,EAAE,EACrC,cAAc;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,SAcrC,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAI,2GASzC;IACD,YAAY,EAAE,qBAAqB,EAAE,CAAC;IACtC,UAAU,EAAE,QAAQ,CAAC;IACrB,YAAY,EAAE,yBAAyB,EAAE,CAAC;IAC1C,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC1B,KAAK,EAAE,oBAAoB,CAAC;QAC5B,SAAS,EAAE,kBAAkB,CAAC;QAC9B,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,qBAAqB,CAAC;QAC/B,cAAc,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,OAAO,CAAC;KAClB,KAAK,IAAI,CAAC;CACZ,WA0EA,CAAC;AAEF,eAAO,MAAM,gCAAgC,GAAI,qFAM9C;IACD,gBAAgB,EAAE,QAAQ,CAAC;IAC3B,sBAAsB,EAAE,QAAQ,CAAC;IACjC,aAAa,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,yBAAyB,EAAE,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,WA2BA,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.js b/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.js new file mode 100644 index 0000000..7c87912 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.js @@ -0,0 +1,97 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.buildSignedDstasIssueTransaction = exports.buildSignedDstasTransaction = exports.validateDstasAmounts = exports.buildDstasLockingScriptBuilder = void 0; +const dstas_locking_builder_1 = require("./script/build/dstas-locking-builder"); +const p2pkh_builder_1 = require("./script/build/p2pkh-builder"); +const script_builder_1 = require("./script/build/script-builder"); +const transaction_factory_1 = require("./transaction-factory"); +const script_type_1 = require("./bitcoin/script-type"); +const transaction_builder_1 = require("./transaction/build/transaction-builder"); +const output_builder_1 = require("./transaction/build/output-builder"); +const buildDstasLockingScriptBuilder = (params) => { + const tokens = (0, dstas_locking_builder_1.buildDstasLockingTokens)(params); + return script_builder_1.ScriptBuilder.fromTokens(tokens, script_type_1.ScriptType.dstas); +}; +exports.buildDstasLockingScriptBuilder = buildDstasLockingScriptBuilder; +const validateDstasAmounts = (stasPayments, destinations) => { + const inputTotal = stasPayments.reduce((sum, payment) => sum + payment.OutPoint.Satoshis, 0); + const outputTotal = destinations.reduce((sum, dest) => sum + dest.Satoshis, 0); + if (inputTotal !== outputTotal) { + throw new Error("Input satoshis must be equal output satoshis"); + } +}; +exports.validateDstasAmounts = validateDstasAmounts; +const buildSignedDstasTransaction = ({ stasPayments, feePayment, destinations, note, feeRate = transaction_factory_1.FeeRate, omitChangeOutput = false, isMerge = false, configureStasInput, }) => { + if (stasPayments.length === 0) { + throw new Error("At least one STAS input is required"); + } + if (destinations.length === 0) { + throw new Error("At least one destination is required"); + } + (0, exports.validateDstasAmounts)(stasPayments, destinations); + const txBuilder = transaction_builder_1.TransactionBuilder.init(); + const stasInputIdxs = []; + for (const payment of stasPayments) { + if (isMerge) { + txBuilder.addStasMergeInput(payment.OutPoint, payment.Owner); + } + else { + txBuilder.addInput(payment.OutPoint, payment.Owner); + } + stasInputIdxs.push(txBuilder.Inputs.length - 1); + } + txBuilder.addInput(feePayment.OutPoint, feePayment.Owner); + for (const destination of destinations) { + const lockingScript = (0, exports.buildDstasLockingScriptBuilder)(destination.LockingParams); + txBuilder.Outputs.push(new output_builder_1.OutputBuilder(lockingScript, destination.Satoshis)); + } + const feeOutputIdx = txBuilder.Outputs.length; + let changeOutput; + if (note) { + txBuilder.addNullDataOutput(note); + } + if (!omitChangeOutput) { + changeOutput = new output_builder_1.OutputBuilder(new p2pkh_builder_1.P2pkhBuilder(feePayment.OutPoint.Address), feePayment.OutPoint.Satoshis); + txBuilder.Outputs.splice(feeOutputIdx, 0, changeOutput); + } + const runConfigure = (phase) => { + stasInputIdxs.forEach((inputIndex, stasInputIndex) => { + configureStasInput === null || configureStasInput === void 0 ? void 0 : configureStasInput({ + phase, + txBuilder, + inputIndex, + payment: stasPayments[stasInputIndex], + stasInputIndex, + isMerge, + }); + }); + }; + runConfigure("estimate"); + if (!omitChangeOutput) { + const fee = txBuilder.getFee(feeRate); + if (fee >= feePayment.OutPoint.Satoshis) { + throw new Error(`Insufficient satoshis to pay fee`); + } + changeOutput.Satoshis = feePayment.OutPoint.Satoshis - fee; + } + runConfigure("finalize"); + return txBuilder.sign().toHex(); +}; +exports.buildSignedDstasTransaction = buildSignedDstasTransaction; +const buildSignedDstasIssueTransaction = ({ contractOutPoint, contractChangeOutPoint, contractOwner, destinations, feeRate = transaction_factory_1.FeeRate, }) => { + if (destinations.length === 0) { + throw new Error("At least one destination is required"); + } + const txBuilder = transaction_builder_1.TransactionBuilder.init() + .addInput(contractOutPoint.OutPoint, contractOwner) + .addInput(contractChangeOutPoint.OutPoint, contractOwner); + for (const destination of destinations) { + const lockingScript = (0, exports.buildDstasLockingScriptBuilder)(destination.LockingParams); + txBuilder.Outputs.push(new output_builder_1.OutputBuilder(lockingScript, destination.Satoshis)); + } + const feeOutputIdx = txBuilder.Outputs.length; + txBuilder.addChangeOutputWithFee(contractChangeOutPoint.OutPoint.Address, contractChangeOutPoint.OutPoint.Satoshis, feeRate, feeOutputIdx); + return txBuilder.sign().toHex(); +}; +exports.buildSignedDstasIssueTransaction = buildSignedDstasIssueTransaction; +//# sourceMappingURL=dstas-tx-assembly.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.js.map b/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.js.map new file mode 100644 index 0000000..4ae8c5a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas-tx-assembly.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-tx-assembly.js","sourceRoot":"","sources":["../src/dstas-tx-assembly.ts"],"names":[],"mappings":";;;AAEA,gFAG8C;AAC9C,gEAA4D;AAC5D,kEAA8D;AAC9D,+DAAgD;AAChD,uDAAmD;AACnD,iFAA6E;AAC7E,uEAAmE;AAa5D,MAAM,8BAA8B,GAAG,CAAC,MAA0B,EAAE,EAAE;IAC3E,MAAM,MAAM,GAAG,IAAA,+CAAuB,EAAC,MAAM,CAAC,CAAC;IAC/C,OAAO,8BAAa,CAAC,UAAU,CAAC,MAAM,EAAE,wBAAU,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC,CAAC;AAHW,QAAA,8BAA8B,kCAGzC;AAEK,MAAM,oBAAoB,GAAG,CAClC,YAAqC,EACrC,YAAoC,EACpC,EAAE;IACF,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CACpC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,EACjD,CAAC,CACF,CAAC;IACF,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CACrC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,EAClC,CAAC,CACF,CAAC;IAEF,IAAI,UAAU,KAAK,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;AACH,CAAC,CAAC;AAhBW,QAAA,oBAAoB,wBAgB/B;AAEK,MAAM,2BAA2B,GAAG,CAAC,EAC1C,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,IAAI,EACJ,OAAO,GAAG,6BAAO,EACjB,gBAAgB,GAAG,KAAK,EACxB,OAAO,GAAG,KAAK,EACf,kBAAkB,GAiBnB,EAAE,EAAE;IACH,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,IAAA,4BAAoB,EAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAEjD,MAAM,SAAS,GAAG,wCAAkB,CAAC,IAAI,EAAE,CAAC;IAC5C,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;QACnC,IAAI,OAAO,EAAE,CAAC;YACZ,SAAS,CAAC,iBAAiB,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC;QACD,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAE1D,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,aAAa,GAAG,IAAA,sCAA8B,EAClD,WAAW,CAAC,aAAa,CAC1B,CAAC;QACF,SAAS,CAAC,OAAO,CAAC,IAAI,CACpB,IAAI,8BAAa,CAAC,aAAa,EAAE,WAAW,CAAC,QAAQ,CAAC,CACvD,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;IAC9C,IAAI,YAAuC,CAAC;IAE5C,IAAI,IAAI,EAAE,CAAC;QACT,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,YAAY,GAAG,IAAI,8BAAa,CAC9B,IAAI,4BAAY,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAQ,CAAC,EAC9C,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAC7B,CAAC;QACF,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,KAA2B,EAAE,EAAE;QACnD,aAAa,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE;YACnD,kBAAkB,aAAlB,kBAAkB,uBAAlB,kBAAkB,CAAG;gBACnB,KAAK;gBACL,SAAS;gBACT,UAAU;gBACV,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC;gBACrC,cAAc;gBACd,OAAO;aACR,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,YAAY,CAAC,UAAU,CAAC,CAAC;IAEzB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QACD,YAAa,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,QAAQ,GAAG,GAAG,CAAC;IAC9D,CAAC;IAED,YAAY,CAAC,UAAU,CAAC,CAAC;IAEzB,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;AAClC,CAAC,CAAC;AAnGW,QAAA,2BAA2B,+BAmGtC;AAEK,MAAM,gCAAgC,GAAG,CAAC,EAC/C,gBAAgB,EAChB,sBAAsB,EACtB,aAAa,EACb,YAAY,EACZ,OAAO,GAAG,6BAAO,GAOlB,EAAE,EAAE;IACH,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,SAAS,GAAG,wCAAkB,CAAC,IAAI,EAAE;SACxC,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC;SAClD,QAAQ,CAAC,sBAAsB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAE5D,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,aAAa,GAAG,IAAA,sCAA8B,EAClD,WAAW,CAAC,aAAa,CAC1B,CAAC;QACF,SAAS,CAAC,OAAO,CAAC,IAAI,CACpB,IAAI,8BAAa,CAAC,aAAa,EAAE,WAAW,CAAC,QAAQ,CAAC,CACvD,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;IAC9C,SAAS,CAAC,sBAAsB,CAC9B,sBAAsB,CAAC,QAAQ,CAAC,OAAQ,EACxC,sBAAsB,CAAC,QAAQ,CAAC,QAAQ,EACxC,OAAO,EACP,YAAY,CACb,CAAC;IAEF,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;AAClC,CAAC,CAAC;AAvCW,QAAA,gCAAgC,oCAuC3C"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas.d.ts b/vendor/dxs-bsv-token-sdk/dist/dstas.d.ts new file mode 100644 index 0000000..2facf91 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas.d.ts @@ -0,0 +1,3 @@ +export * from "./dstas-factory"; +export { AvgFeeForDstasMerge, TDstasFundingUtxoRequest, TDstasGetUtxoFunction, TDstasGetFundingUtxoFunction, TDstasGetTransactionsFunction, TDstasPayoutBundle, DstasSpendType, TDstasRecipient, TDstasTransferOutput, TDstasTransferRequest, TDstasLockingParamsBuilder, TDstasUnlockingScriptBuilder, TDstasUnlockingScriptEstimator, TDstasPayment, TDstasDestination, DstasBundleFactory, } from "./dstas-bundle-factory"; +//# sourceMappingURL=dstas.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/dstas.d.ts.map new file mode 100644 index 0000000..06c7434 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas.d.ts","sourceRoot":"","sources":["../src/dstas.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,4BAA4B,EAC5B,6BAA6B,EAC7B,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,0BAA0B,EAC1B,4BAA4B,EAC5B,8BAA8B,EAC9B,aAAa,EACb,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas.js b/vendor/dxs-bsv-token-sdk/dist/dstas.js new file mode 100644 index 0000000..d6e7bc4 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas.js @@ -0,0 +1,22 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DstasBundleFactory = exports.AvgFeeForDstasMerge = void 0; +__exportStar(require("./dstas-factory"), exports); +var dstas_bundle_factory_1 = require("./dstas-bundle-factory"); +Object.defineProperty(exports, "AvgFeeForDstasMerge", { enumerable: true, get: function () { return dstas_bundle_factory_1.AvgFeeForDstasMerge; } }); +Object.defineProperty(exports, "DstasBundleFactory", { enumerable: true, get: function () { return dstas_bundle_factory_1.DstasBundleFactory; } }); +//# sourceMappingURL=dstas.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/dstas.js.map b/vendor/dxs-bsv-token-sdk/dist/dstas.js.map new file mode 100644 index 0000000..bb7d67f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/dstas.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas.js","sourceRoot":"","sources":["../src/dstas.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,+DAiBgC;AAhB9B,2HAAA,mBAAmB,OAAA;AAenB,0HAAA,kBAAkB,OAAA"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/hashes.d.ts b/vendor/dxs-bsv-token-sdk/dist/hashes.d.ts new file mode 100644 index 0000000..1a26ce6 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/hashes.d.ts @@ -0,0 +1,5 @@ +export declare const sha256: (message: Uint8Array) => Uint8Array; +export declare const ripemd160: (message: Uint8Array) => Uint8Array; +export declare const hash160: (buffer: Uint8Array) => Uint8Array; +export declare const hash256: (buffer: Uint8Array) => Uint8Array; +//# sourceMappingURL=hashes.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/hashes.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/hashes.d.ts.map new file mode 100644 index 0000000..932733a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/hashes.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"hashes.d.ts","sourceRoot":"","sources":["../src/hashes.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM,GAAI,SAAS,UAAU,KAAG,UACtB,CAAC;AAExB,eAAO,MAAM,SAAS,GAAI,SAAS,UAAU,KAAG,UACvB,CAAC;AAE1B,eAAO,MAAM,OAAO,GAAI,QAAQ,UAAU,KAAG,UAClB,CAAC;AAE5B,eAAO,MAAM,OAAO,GAAI,QAAQ,UAAU,KAAG,UACrB,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/hashes.js b/vendor/dxs-bsv-token-sdk/dist/hashes.js new file mode 100644 index 0000000..ed107ef --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/hashes.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hash256 = exports.hash160 = exports.ripemd160 = exports.sha256 = void 0; +const sha2_js_1 = require("@noble/hashes/sha2.js"); +const legacy_js_1 = require("@noble/hashes/legacy.js"); +const sha256 = (message) => (0, sha2_js_1.sha256)(message); +exports.sha256 = sha256; +const ripemd160 = (message) => (0, legacy_js_1.ripemd160)(message); +exports.ripemd160 = ripemd160; +const hash160 = (buffer) => (0, exports.ripemd160)((0, exports.sha256)(buffer)); +exports.hash160 = hash160; +const hash256 = (buffer) => (0, exports.sha256)((0, exports.sha256)(buffer)); +exports.hash256 = hash256; +//# sourceMappingURL=hashes.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/hashes.js.map b/vendor/dxs-bsv-token-sdk/dist/hashes.js.map new file mode 100644 index 0000000..1e4aaac --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/hashes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hashes.js","sourceRoot":"","sources":["../src/hashes.ts"],"names":[],"mappings":";;;AAAA,mDAA+D;AAC/D,uDAAsE;AAE/D,MAAM,MAAM,GAAG,CAAC,OAAmB,EAAc,EAAE,CACxD,IAAA,gBAAY,EAAC,OAAO,CAAC,CAAC;AADX,QAAA,MAAM,UACK;AAEjB,MAAM,SAAS,GAAG,CAAC,OAAmB,EAAc,EAAE,CAC3D,IAAA,qBAAc,EAAC,OAAO,CAAC,CAAC;AADb,QAAA,SAAS,aACI;AAEnB,MAAM,OAAO,GAAG,CAAC,MAAkB,EAAc,EAAE,CACxD,IAAA,iBAAS,EAAC,IAAA,cAAM,EAAC,MAAM,CAAC,CAAC,CAAC;AADf,QAAA,OAAO,WACQ;AAErB,MAAM,OAAO,GAAG,CAAC,MAAkB,EAAc,EAAE,CACxD,IAAA,cAAM,EAAC,IAAA,cAAM,EAAC,MAAM,CAAC,CAAC,CAAC;AADZ,QAAA,OAAO,WACK"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/index.d.ts b/vendor/dxs-bsv-token-sdk/dist/index.d.ts new file mode 100644 index 0000000..7a0e841 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/index.d.ts @@ -0,0 +1,4 @@ +export * as bsv from "./bsv"; +export * as dstas from "./dstas"; +export * as stas from "./stas"; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/index.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/index.d.ts.map new file mode 100644 index 0000000..08185ce --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/index.js b/vendor/dxs-bsv-token-sdk/dist/index.js new file mode 100644 index 0000000..f49503c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/index.js @@ -0,0 +1,40 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.stas = exports.dstas = exports.bsv = void 0; +exports.bsv = __importStar(require("./bsv")); +exports.dstas = __importStar(require("./dstas")); +exports.stas = __importStar(require("./stas")); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/index.js.map b/vendor/dxs-bsv-token-sdk/dist/index.js.map new file mode 100644 index 0000000..73dea3f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA6B;AAC7B,iDAAiC;AACjC,+CAA+B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.d.ts new file mode 100644 index 0000000..72e8d0c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.d.ts @@ -0,0 +1,4 @@ +import { ScriptToken } from "../script-token"; +export declare const asmToTokens: (asm: string) => ScriptToken[]; +export declare const asmToBytes: (asm: string) => Uint8Array; +//# sourceMappingURL=asm-template-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.d.ts.map new file mode 100644 index 0000000..bc6383c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"asm-template-builder.d.ts","sourceRoot":"","sources":["../../../src/script/build/asm-template-builder.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAc9C,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,WAAW,EA2BpD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,4BAIrC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.js b/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.js new file mode 100644 index 0000000..4660094 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.js @@ -0,0 +1,50 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.asmToBytes = exports.asmToTokens = void 0; +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_type_1 = require("../../bitcoin/script-type"); +const bytes_1 = require("../../bytes"); +const script_builder_1 = require("./script-builder"); +const script_token_1 = require("../script-token"); +const isHex = (value) => /^[0-9a-fA-F]+$/.test(value); +const toOpcode = (token) => { + if (token === "OP_FALSE") + return op_codes_1.OpCode.OP_0; + if (token === "OP_TRUE") + return op_codes_1.OpCode.OP_1; + const maybe = op_codes_1.OpCode[token]; + if (typeof maybe === "number") + return maybe; + return undefined; +}; +const asmToTokens = (asm) => { + const tokens = asm.trim().split(/\s+/).filter(Boolean); + const result = []; + for (const token of tokens) { + if (token.startsWith("<") && token.endsWith(">")) { + throw new Error(`Unresolved template placeholder: ${token}`); + } + if (token.startsWith("OP_")) { + const opcode = toOpcode(token); + if (opcode === undefined) { + throw new Error(`Unknown opcode token: ${token}`); + } + result.push(new script_token_1.ScriptToken(opcode, opcode)); + continue; + } + if (!isHex(token)) { + throw new Error(`Invalid ASM token: ${token}`); + } + const bytes = (0, bytes_1.fromHex)(token); + result.push(script_token_1.ScriptToken.fromBytes(bytes)); + } + return result; +}; +exports.asmToTokens = asmToTokens; +const asmToBytes = (asm) => { + const tokens = (0, exports.asmToTokens)(asm); + const builder = script_builder_1.ScriptBuilder.fromTokens(tokens, script_type_1.ScriptType.unknown); + return builder.toBytes(); +}; +exports.asmToBytes = asmToBytes; +//# sourceMappingURL=asm-template-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.js.map new file mode 100644 index 0000000..95cbf50 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/asm-template-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"asm-template-builder.js","sourceRoot":"","sources":["../../../src/script/build/asm-template-builder.ts"],"names":[],"mappings":";;;AAAA,qDAAgD;AAChD,2DAAuD;AACvD,uCAAsC;AACtC,qDAAiD;AACjD,kDAA8C;AAE9C,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAE9D,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAsB,EAAE;IACrD,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,iBAAM,CAAC,IAAI,CAAC;IAC7C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,iBAAM,CAAC,IAAI,CAAC;IAE5C,MAAM,KAAK,GAAI,iBAA4C,CAAC,KAAK,CAAC,CAAC;IACnE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5C,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEK,MAAM,WAAW,GAAG,CAAC,GAAW,EAAiB,EAAE;IACxD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,MAAM,GAAkB,EAAE,CAAC;IAEjC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,oCAAoC,KAAK,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,IAAI,0BAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YAC7C,SAAS;QACX,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,KAAK,GAAG,IAAA,eAAO,EAAC,KAAK,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,0BAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AA3BW,QAAA,WAAW,eA2BtB;AAEK,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE;IACxC,MAAM,MAAM,GAAG,IAAA,mBAAW,EAAC,GAAG,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,8BAAa,CAAC,UAAU,CAAC,MAAM,EAAE,wBAAU,CAAC,OAAO,CAAC,CAAC;IACrE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;AAC3B,CAAC,CAAC;AAJW,QAAA,UAAU,cAIrB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.d.ts new file mode 100644 index 0000000..6f54fdd --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.d.ts @@ -0,0 +1,23 @@ +import { Bytes } from "../../bytes"; +import { ScriptToken } from "../script-token"; +import { DstasActionData, DstasSwapActionData } from "../dstas-action-data"; +export type ActionDataInput = Bytes | number | null | DstasSwapActionData | DstasActionData; +export type DstasFlagsInput = { + freezable?: boolean; + confiscatable?: boolean; +}; +export type DstasLockingParams = { + owner?: Bytes; + ownerPkh?: Bytes; + actionData: ActionDataInput; + redemptionPkh: Bytes; + frozen?: boolean; + flags?: Bytes | DstasFlagsInput | null; + serviceFields?: Bytes[]; + optionalData?: Bytes[]; +}; +export declare const buildDstasFlags: (flags?: DstasFlagsInput) => Bytes; +export declare const buildDstasLockingTokens: (params: DstasLockingParams) => ScriptToken[]; +export declare const buildDstasLockingScript: (params: DstasLockingParams) => Bytes; +export declare const buildDstasLockingAsm: (params: DstasLockingParams) => string; +//# sourceMappingURL=dstas-locking-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.d.ts.map new file mode 100644 index 0000000..cf0ad8d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-locking-builder.d.ts","sourceRoot":"","sources":["../../../src/script/build/dstas-locking-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAKpC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EACL,eAAe,EACf,mBAAmB,EAEpB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,eAAe,GACvB,KAAK,GACL,MAAM,GACN,IAAI,GACJ,mBAAmB,GACnB,eAAe,CAAC;AACpB,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,UAAU,EAAE,eAAe,CAAC;IAC5B,aAAa,EAAE,KAAK,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,GAAG,eAAe,GAAG,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,eAAe,KAAG,KAKzD,CAAC;AA2FF,eAAO,MAAM,uBAAuB,GAClC,QAAQ,kBAAkB,KACzB,WAAW,EA6Bb,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,QAAQ,kBAAkB,KAAG,KAGpE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,kBAAkB,KAAG,MAGjE,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.js b/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.js new file mode 100644 index 0000000..56d30aa --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.js @@ -0,0 +1,114 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.buildDstasLockingAsm = exports.buildDstasLockingScript = exports.buildDstasLockingTokens = exports.buildDstasFlags = void 0; +const buffer_utils_1 = require("../../buffer/buffer-utils"); +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_type_1 = require("../../bitcoin/script-type"); +const script_builder_1 = require("./script-builder"); +const script_token_1 = require("../script-token"); +const dstas_locking_template_base_1 = require("../templates/dstas-locking-template-base"); +const dstas_action_data_1 = require("../dstas-action-data"); +const identity_field_1 = require("../identity-field"); +const buildDstasFlags = (flags) => { + const result = new Uint8Array(1); + if (flags === null || flags === void 0 ? void 0 : flags.freezable) + result[0] |= 0x01; + if (flags === null || flags === void 0 ? void 0 : flags.confiscatable) + result[0] |= 0x02; + return result; +}; +exports.buildDstasFlags = buildDstasFlags; +const parseProtocolFlags = (flags) => { + const rightmostByte = flags.length > 0 ? flags[flags.length - 1] : 0; + return { + freezable: (rightmostByte & 0x01) === 0x01, + confiscatable: (rightmostByte & 0x02) === 0x02, + }; +}; +const ensureLength = (value, expected, name) => { + if (value.length !== expected) { + throw new Error(`${name} must be ${expected} bytes, got ${value.length}`); + } +}; +const resolveOwner = (params) => { + var _a; + const owner = (_a = params.owner) !== null && _a !== void 0 ? _a : params.ownerPkh; + if (!owner || owner.length === 0) { + throw new Error("owner must be provided"); + } + (0, identity_field_1.assertSupportedIdentityField)(owner, "owner"); + return owner; +}; +const buildOwnerToken = (value) => script_token_1.ScriptToken.fromBytes(value); +const buildActionDataToken = (field, frozen) => { + if (typeof field === "object" && field && "kind" in field) { + return script_token_1.ScriptToken.fromBytes((0, dstas_action_data_1.encodeActionData)(field)); + } + if (field === null) { + return new script_token_1.ScriptToken(frozen ? op_codes_1.OpCode.OP_2 : op_codes_1.OpCode.OP_0, frozen ? op_codes_1.OpCode.OP_2 : op_codes_1.OpCode.OP_0); + } + if (typeof field !== "number" && field.length === 0) { + return new script_token_1.ScriptToken(frozen ? op_codes_1.OpCode.OP_2 : op_codes_1.OpCode.OP_0, frozen ? op_codes_1.OpCode.OP_2 : op_codes_1.OpCode.OP_0); + } + const raw = typeof field === "number" ? (0, buffer_utils_1.getNumberBytes)(field) : new Uint8Array(field); + if (!frozen) + return script_token_1.ScriptToken.fromBytes(raw); + const prefixed = new Uint8Array(raw.length + 1); + prefixed[0] = 0x02; + prefixed.set(raw, 1); + return script_token_1.ScriptToken.fromBytes(prefixed); +}; +const buildFlagsToken = (flags) => { + const fallback = new Uint8Array([0x00]); + const encoded = flags instanceof Uint8Array + ? flags.length === 0 + ? fallback + : flags + : flags + ? (0, exports.buildDstasFlags)(flags) + : fallback; + if (encoded.length > 75) { + throw new Error(`flags length must be <= 75 bytes, got ${encoded.length}`); + } + return script_token_1.ScriptToken.fromBytes(encoded); +}; +const buildDataTokens = (values) => { + if (!values || values.length === 0) + return []; + return values.map((v) => script_token_1.ScriptToken.fromBytes(v)); +}; +const buildDstasLockingTokens = (params) => { + var _a, _b; + const frozen = params.frozen === true; + ensureLength(params.redemptionPkh, 20, "redemptionPkh"); + const ownerToken = buildOwnerToken(resolveOwner(params)); + const actionDataToken = buildActionDataToken(params.actionData, frozen); + const redemptionToken = script_token_1.ScriptToken.fromBytes(params.redemptionPkh); + const flagsToken = buildFlagsToken(params.flags); + const serviceTokens = buildDataTokens(params.serviceFields); + const optionalTokens = buildDataTokens(params.optionalData); + const parsedFlags = parseProtocolFlags((_a = flagsToken.Data) !== null && _a !== void 0 ? _a : new Uint8Array(0)); + const expectedServiceFieldsCount = (parsedFlags.freezable ? 1 : 0) + (parsedFlags.confiscatable ? 1 : 0); + if (serviceTokens.length !== expectedServiceFieldsCount) { + throw new Error(`serviceFields count ${serviceTokens.length} does not match flags requirements ${expectedServiceFieldsCount}`); + } + for (const serviceField of (_b = params.serviceFields) !== null && _b !== void 0 ? _b : []) { + (0, identity_field_1.assertSupportedIdentityField)(serviceField, "service field"); + } + const baseTokens = (0, dstas_locking_template_base_1.buildDstasTemplateBaseTokens)(); + const tokens = [ownerToken, actionDataToken, ...baseTokens]; + tokens.push(redemptionToken, flagsToken, ...serviceTokens, ...optionalTokens); + return tokens; +}; +exports.buildDstasLockingTokens = buildDstasLockingTokens; +const buildDstasLockingScript = (params) => { + const tokens = (0, exports.buildDstasLockingTokens)(params); + return script_builder_1.ScriptBuilder.fromTokens(tokens, script_type_1.ScriptType.unknown).toBytes(); +}; +exports.buildDstasLockingScript = buildDstasLockingScript; +const buildDstasLockingAsm = (params) => { + const tokens = (0, exports.buildDstasLockingTokens)(params); + return script_builder_1.ScriptBuilder.fromTokens(tokens, script_type_1.ScriptType.unknown).toAsm(); +}; +exports.buildDstasLockingAsm = buildDstasLockingAsm; +//# sourceMappingURL=dstas-locking-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.js.map new file mode 100644 index 0000000..f3311b5 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/dstas-locking-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-locking-builder.js","sourceRoot":"","sources":["../../../src/script/build/dstas-locking-builder.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.d.ts new file mode 100644 index 0000000..6487644 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.d.ts @@ -0,0 +1,6 @@ +import { ScriptBuilder } from "./script-builder"; +import { Bytes } from "../../bytes"; +export declare class NullDataBuilder extends ScriptBuilder { + constructor(data: Bytes[]); +} +//# sourceMappingURL=null-data-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.d.ts.map new file mode 100644 index 0000000..2d765d1 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"null-data-builder.d.ts","sourceRoot":"","sources":["../../../src/script/build/null-data-builder.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,qBAAa,eAAgB,SAAQ,aAAa;gBACpC,IAAI,EAAE,KAAK,EAAE;CAa1B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.js b/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.js new file mode 100644 index 0000000..1de4bd9 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NullDataBuilder = void 0; +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_type_1 = require("../../bitcoin/script-type"); +const script_samples_1 = require("../script-samples"); +const script_token_1 = require("../script-token"); +const script_builder_1 = require("./script-builder"); +class NullDataBuilder extends script_builder_1.ScriptBuilder { + constructor(data) { + super(script_type_1.ScriptType.nullData); + for (const token of script_samples_1.nullDataTokens) { + this._tokens.push(script_token_1.ScriptToken.fromScriptToken(token)); + } + this.addOpCode(op_codes_1.OpCode.OP_RETURN); + for (const segment of data) { + this.addData(segment); + } + } +} +exports.NullDataBuilder = NullDataBuilder; +//# sourceMappingURL=null-data-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.js.map new file mode 100644 index 0000000..f28364b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/null-data-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"null-data-builder.js","sourceRoot":"","sources":["../../../src/script/build/null-data-builder.ts"],"names":[],"mappings":";;;AAAA,qDAAgD;AAChD,2DAAuD;AACvD,sDAAmD;AACnD,kDAA8C;AAC9C,qDAAiD;AAGjD,MAAa,eAAgB,SAAQ,8BAAa;IAChD,YAAY,IAAa;QACvB,KAAK,CAAC,wBAAU,CAAC,QAAQ,CAAC,CAAC;QAE3B,KAAK,MAAM,KAAK,IAAI,+BAAc,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,0BAAW,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,iBAAM,CAAC,SAAS,CAAC,CAAC;QAEjC,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;CACF;AAdD,0CAcC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.d.ts new file mode 100644 index 0000000..1069e6f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.d.ts @@ -0,0 +1,6 @@ +import { Address } from "../../bitcoin/address"; +import { ScriptBuilder } from "./script-builder"; +export declare class P2mpkhBuilder extends ScriptBuilder { + constructor(address: Address); +} +//# sourceMappingURL=p2mpkh-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.d.ts.map new file mode 100644 index 0000000..9f080f5 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"p2mpkh-builder.d.ts","sourceRoot":"","sources":["../../../src/script/build/p2mpkh-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAIhD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,qBAAa,aAAc,SAAQ,aAAa;gBAClC,OAAO,EAAE,OAAO;CAc7B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.js b/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.js new file mode 100644 index 0000000..f0db06f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.P2mpkhBuilder = void 0; +const script_type_1 = require("../../bitcoin/script-type"); +const script_samples_1 = require("../script-samples"); +const script_token_1 = require("../script-token"); +const script_builder_1 = require("./script-builder"); +class P2mpkhBuilder extends script_builder_1.ScriptBuilder { + constructor(address) { + super(script_type_1.ScriptType.p2mpkh, address); + for (const token of script_samples_1.p2mpkhTokens) { + if (token.IsReceiverId) { + const receiver = script_token_1.ScriptToken.fromBytes(address.Hash160); + receiver.IsReceiverId = true; + this._tokens.push(receiver); + } + else { + this._tokens.push(script_token_1.ScriptToken.fromScriptToken(token)); + } + } + } +} +exports.P2mpkhBuilder = P2mpkhBuilder; +//# sourceMappingURL=p2mpkh-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.js.map new file mode 100644 index 0000000..dc8c43d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2mpkh-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"p2mpkh-builder.js","sourceRoot":"","sources":["../../../src/script/build/p2mpkh-builder.ts"],"names":[],"mappings":";;;AACA,2DAAuD;AACvD,sDAAiD;AACjD,kDAA8C;AAC9C,qDAAiD;AAEjD,MAAa,aAAc,SAAQ,8BAAa;IAC9C,YAAY,OAAgB;QAC1B,KAAK,CAAC,wBAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAElC,KAAK,MAAM,KAAK,IAAI,6BAAY,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;gBACvB,MAAM,QAAQ,GAAG,0BAAW,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACxD,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAC;gBAE7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,0BAAW,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAfD,sCAeC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.d.ts new file mode 100644 index 0000000..0182e3a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.d.ts @@ -0,0 +1,9 @@ +import { Address } from "../../bitcoin/address"; +import { ScriptBuilder } from "./script-builder"; +import { Bytes } from "../../bytes"; +export declare class P2pkhBuilder extends ScriptBuilder { + private _isOpReturnAdded; + constructor(address: Address); + addReturnData(data: Bytes): void; +} +//# sourceMappingURL=p2pkh-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.d.ts.map new file mode 100644 index 0000000..fee8665 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"p2pkh-builder.d.ts","sourceRoot":"","sources":["../../../src/script/build/p2pkh-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAKhD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,qBAAa,YAAa,SAAQ,aAAa;IAC7C,OAAO,CAAC,gBAAgB,CAAkB;gBAE9B,OAAO,EAAE,OAAO;IAe5B,aAAa,CAAC,IAAI,EAAE,KAAK;CAQ1B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.js b/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.js new file mode 100644 index 0000000..4e5f249 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.js @@ -0,0 +1,33 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.P2pkhBuilder = void 0; +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_type_1 = require("../../bitcoin/script-type"); +const script_samples_1 = require("../script-samples"); +const script_token_1 = require("../script-token"); +const script_builder_1 = require("./script-builder"); +class P2pkhBuilder extends script_builder_1.ScriptBuilder { + constructor(address) { + super(script_type_1.ScriptType.p2pkh, address); + this._isOpReturnAdded = false; + for (const token of script_samples_1.p2phkTokens) { + if (token.IsReceiverId) { + const receiver = script_token_1.ScriptToken.fromBytes(address.Hash160); + receiver.IsReceiverId = true; + this._tokens.push(receiver); + } + else { + this._tokens.push(script_token_1.ScriptToken.fromScriptToken(token)); + } + } + } + addReturnData(data) { + if (!this._isOpReturnAdded) { + this.addOpCode(op_codes_1.OpCode.OP_RETURN); + this._isOpReturnAdded = true; + } + this.addData(data); + } +} +exports.P2pkhBuilder = P2pkhBuilder; +//# sourceMappingURL=p2pkh-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.js.map new file mode 100644 index 0000000..446dee3 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2pkh-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"p2pkh-builder.js","sourceRoot":"","sources":["../../../src/script/build/p2pkh-builder.ts"],"names":[],"mappings":";;;AACA,qDAAgD;AAChD,2DAAuD;AACvD,sDAAgD;AAChD,kDAA8C;AAC9C,qDAAiD;AAGjD,MAAa,YAAa,SAAQ,8BAAa;IAG7C,YAAY,OAAgB;QAC1B,KAAK,CAAC,wBAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAH3B,qBAAgB,GAAY,KAAK,CAAC;QAKxC,KAAK,MAAM,KAAK,IAAI,4BAAW,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;gBACvB,MAAM,QAAQ,GAAG,0BAAW,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACxD,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAC;gBAE7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,0BAAW,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC;IAED,aAAa,CAAC,IAAW;QACvB,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,IAAI,CAAC,SAAS,CAAC,iBAAM,CAAC,SAAS,CAAC,CAAC;YACjC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;CACF;AA1BD,oCA0BC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.d.ts new file mode 100644 index 0000000..a9a5eb5 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.d.ts @@ -0,0 +1,7 @@ +import { Address } from "../../bitcoin/address"; +import { ScriptBuilder } from "./script-builder"; +import { Bytes } from "../../bytes"; +export declare class P2stasBuilder extends ScriptBuilder { + constructor(address: Address, tokenId: string, symbol: string, data?: Bytes[]); +} +//# sourceMappingURL=p2stas-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.d.ts.map new file mode 100644 index 0000000..1590c8d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"p2stas-builder.d.ts","sourceRoot":"","sources":["../../../src/script/build/p2stas-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAKhD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAwB,MAAM,aAAa,CAAC;AAE1D,qBAAa,aAAc,SAAQ,aAAa;gBAE5C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,KAAK,EAAO;CAyBrB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.js b/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.js new file mode 100644 index 0000000..9a19f26 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.js @@ -0,0 +1,33 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.P2stasBuilder = void 0; +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_type_1 = require("../../bitcoin/script-type"); +const script_samples_1 = require("../script-samples"); +const script_token_1 = require("../script-token"); +const script_builder_1 = require("./script-builder"); +const bytes_1 = require("../../bytes"); +class P2stasBuilder extends script_builder_1.ScriptBuilder { + constructor(address, tokenId, symbol, data = []) { + super(script_type_1.ScriptType.p2stas, address); + const stasTokens = (0, script_samples_1.getP2stasTokens)(); + for (const token of stasTokens) { + if (token.IsReceiverId) { + const receiver = script_token_1.ScriptToken.fromBytes(address.Hash160); + receiver.IsReceiverId = true; + this._tokens.push(receiver); + } + else { + this._tokens.push(script_token_1.ScriptToken.fromScriptToken(token)); + } + } + this.addOpCode(op_codes_1.OpCode.OP_RETURN); + this.addData((0, bytes_1.fromHex)(tokenId)); + this.addData((0, bytes_1.utf8ToBytes)(symbol)); + for (const d of data) { + this.addData(d); + } + } +} +exports.P2stasBuilder = P2stasBuilder; +//# sourceMappingURL=p2stas-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.js.map new file mode 100644 index 0000000..0b83fc2 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/p2stas-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"p2stas-builder.js","sourceRoot":"","sources":["../../../src/script/build/p2stas-builder.ts"],"names":[],"mappings":";;;AACA,qDAAgD;AAChD,2DAAuD;AACvD,sDAAoD;AACpD,kDAA8C;AAC9C,qDAAiD;AACjD,uCAA0D;AAE1D,MAAa,aAAc,SAAQ,8BAAa;IAC9C,YACE,OAAgB,EAChB,OAAe,EACf,MAAc,EACd,OAAgB,EAAE;QAElB,KAAK,CAAC,wBAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAElC,MAAM,UAAU,GAAG,IAAA,gCAAe,GAAE,CAAC;QAErC,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAC/B,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;gBACvB,MAAM,QAAQ,GAAG,0BAAW,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACxD,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAC;gBAE7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,0BAAW,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,iBAAM,CAAC,SAAS,CAAC,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,IAAA,eAAO,EAAC,OAAO,CAAC,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,IAAA,mBAAW,EAAC,MAAM,CAAC,CAAC,CAAC;QAElC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;CACF;AA9BD,sCA8BC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.d.ts new file mode 100644 index 0000000..9631cbb --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.d.ts @@ -0,0 +1,24 @@ +import { Address } from "../../bitcoin/address"; +import { OpCode } from "../../bitcoin/op-codes"; +import { ScriptType } from "../../bitcoin/script-type"; +import { Bytes } from "../../bytes"; +import { ScriptToken } from "../script-token"; +export declare class ScriptBuilder { + _tokens: ScriptToken[]; + ScriptType: ScriptType; + ToAddress?: Address; + constructor(scriptType: ScriptType, toAddress?: Address); + static fromTokens: (tokens: ScriptToken[], scriptType: ScriptType) => ScriptBuilder; + private static resolveToAddress; + size: () => number; + tokenSize: (token: ScriptToken) => number; + toBytes: () => Uint8Array; + toHex: () => string; + addToken: (token: ScriptToken) => this; + addOpCode: (opCode: OpCode) => this; + addData: (data: Bytes) => this; + addDatas: (data: Bytes[]) => this; + addNumber: (data: number) => this; + toAsm: () => string; +} +//# sourceMappingURL=script-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.d.ts.map new file mode 100644 index 0000000..0da5add --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script-builder.d.ts","sourceRoot":"","sources":["../../../src/script/build/script-builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,KAAK,EAAS,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,qBAAa,aAAa;IACxB,OAAO,EAAE,WAAW,EAAE,CAAM;IAE5B,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;gBAER,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,OAAO;IAKvD,MAAM,CAAC,UAAU,GAAI,QAAQ,WAAW,EAAE,EAAE,YAAY,UAAU,mBAMhE;IAEF,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAkB7B;IAEF,IAAI,eAQF;IAEF,SAAS,GAAI,OAAO,WAAW,YAgB7B;IAEF,OAAO,gCAsBL;IAEF,KAAK,eAA+B;IAEpC,QAAQ,GAAI,OAAO,WAAW,UAI5B;IAEF,SAAS,GAAI,QAAQ,MAAM,UAIzB;IAEF,OAAO,GAAI,MAAM,KAAK,UAIpB;IAEF,QAAQ,GAAI,MAAM,KAAK,EAAE,UAIvB;IAEF,SAAS,GAAI,MAAM,MAAM,UAMvB;IAEF,KAAK,eAcH;CACH"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.js b/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.js new file mode 100644 index 0000000..b0c1d95 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.js @@ -0,0 +1,126 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ScriptBuilder = void 0; +const buffer_utils_1 = require("../../buffer/buffer-utils"); +const binary_1 = require("../../binary"); +const address_1 = require("../../bitcoin/address"); +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_type_1 = require("../../bitcoin/script-type"); +const bytes_1 = require("../../bytes"); +const script_token_1 = require("../script-token"); +class ScriptBuilder { + constructor(scriptType, toAddress) { + this._tokens = []; + this.size = () => { + let size = 0; + for (const token of this._tokens) { + size += this.tokenSize(token); + } + return size; + }; + this.tokenSize = (token) => { + const size = 1; + const opcodeNum = token.OpCodeNum; + const dataLength = token.DataLength; + const add = opcodeNum > 0 && opcodeNum < op_codes_1.OpCode.OP_PUSHDATA1 + ? dataLength + : opcodeNum === op_codes_1.OpCode.OP_PUSHDATA1 + ? dataLength + 1 + : opcodeNum === op_codes_1.OpCode.OP_PUSHDATA2 + ? dataLength + 2 + : opcodeNum === op_codes_1.OpCode.OP_PUSHDATA4 + ? dataLength + 4 + : 0; + return size + add; + }; + this.toBytes = () => { + const buffer = new Uint8Array(this.size()); + const bufferWriter = new binary_1.ByteWriter(buffer); + for (const token of this._tokens) { + bufferWriter.writeUInt8(token.OpCodeNum); + if (token.OpCodeNum > 0 && token.OpCodeNum < op_codes_1.OpCode.OP_PUSHDATA1) { + bufferWriter.writeChunk(token.Data); + } + else if (token.OpCodeNum === op_codes_1.OpCode.OP_PUSHDATA1) { + bufferWriter.writeUInt8(token.DataLength); + bufferWriter.writeChunk(token.Data); + } + else if (token.OpCodeNum === op_codes_1.OpCode.OP_PUSHDATA2) { + bufferWriter.writeUInt16(token.DataLength); + bufferWriter.writeChunk(token.Data); + } + else if (token.OpCodeNum === op_codes_1.OpCode.OP_PUSHDATA4) { + bufferWriter.writeUInt32(token.DataLength); + bufferWriter.writeChunk(token.Data); + } + } + return buffer; + }; + this.toHex = () => (0, bytes_1.toHex)(this.toBytes()); + this.addToken = (token) => { + this._tokens.push(token); + return this; + }; + this.addOpCode = (opCode) => { + this._tokens.push(new script_token_1.ScriptToken(opCode, opCode)); + return this; + }; + this.addData = (data) => { + this._tokens.push(script_token_1.ScriptToken.fromBytes(data)); + return this; + }; + this.addDatas = (data) => { + for (const chunk of data) + this._tokens.push(script_token_1.ScriptToken.fromBytes(chunk)); + return this; + }; + this.addNumber = (data) => { + if (data === 0) + this.addOpCode(op_codes_1.OpCode.OP_0); + else if (data <= 16) + this.addOpCode(0x50 + data); + else + this.addData((0, buffer_utils_1.getNumberBytes)(data)); + return this; + }; + this.toAsm = () => { + const opCodeKeys = Object.keys(op_codes_1.OpCode); + const opCodeValues = Object.values(op_codes_1.OpCode); + let result = ""; + for (const token of this._tokens) { + if (result.length > 0) + result += " "; + if (token.Data) + result += (0, bytes_1.toHex)(token.Data); + else + result += opCodeKeys[opCodeValues.indexOf(token.OpCodeNum)]; + } + return result; + }; + this.ScriptType = scriptType; + this.ToAddress = toAddress; + } +} +exports.ScriptBuilder = ScriptBuilder; +ScriptBuilder.fromTokens = (tokens, scriptType) => { + const toAddress = ScriptBuilder.resolveToAddress(tokens, scriptType); + const builder = new ScriptBuilder(scriptType, toAddress); + builder._tokens = tokens; + return builder; +}; +ScriptBuilder.resolveToAddress = (tokens, scriptType) => { + var _a, _b; + const fromToken = (token) => { + if (!(token === null || token === void 0 ? void 0 : token.Data) || token.Data.length !== 20) + return undefined; + return new address_1.Address(token.Data); + }; + if (scriptType === script_type_1.ScriptType.p2pkh || scriptType === script_type_1.ScriptType.p2mpkh) { + return fromToken((_a = tokens.find((x) => x.IsReceiverId)) !== null && _a !== void 0 ? _a : tokens[2]); + } + if (scriptType === script_type_1.ScriptType.p2stas || scriptType === script_type_1.ScriptType.dstas) { + return fromToken((_b = tokens.find((x) => x.IsReceiverId)) !== null && _b !== void 0 ? _b : tokens[0]); + } + return undefined; +}; +//# sourceMappingURL=script-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.js.map new file mode 100644 index 0000000..1614036 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/build/script-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script-builder.js","sourceRoot":"","sources":["../../../src/script/build/script-builder.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.d.ts new file mode 100644 index 0000000..3a5a656 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.d.ts @@ -0,0 +1,30 @@ +import { Bytes } from "../bytes"; +export declare const enum DstasActionKind { + swap = 1, + confiscation = 2, + freeze = 3 +} +export type DstasSwapActionData = { + kind: "swap"; + requestedScriptHash: Bytes; + requestedPkh: Bytes; + rateNumerator: number; + rateDenominator: number; + next?: DstasSwapActionData; +}; +export type DstasActionData = { + kind: "action"; + action: DstasActionKind.confiscation | DstasActionKind.freeze; + payload?: Bytes; +}; +export type ParsedActionData = { + kind: "empty"; +} | DstasSwapActionData | DstasActionData | { + kind: "unknown"; + action: number; + payload: Bytes; +}; +export declare const encodeActionData: (value: DstasSwapActionData | DstasActionData) => Bytes; +export declare const decodeActionData: (bytes: Bytes) => ParsedActionData; +export declare const buildSwapActionData: (value: Omit) => Bytes; +//# sourceMappingURL=dstas-action-data.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.d.ts.map new file mode 100644 index 0000000..a6eeeaf --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-action-data.d.ts","sourceRoot":"","sources":["../../src/script/dstas-action-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,0BAAkB,eAAe;IAC/B,IAAI,IAAO;IACX,YAAY,IAAO;IACnB,MAAM,IAAO;CACd;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,EAAE,KAAK,CAAC;IAC3B,YAAY,EAAE,KAAK,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,eAAe,CAAC,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC;IAC9D,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB,mBAAmB,GACnB,eAAe,GACf;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC;AAoHxD,eAAO,MAAM,gBAAgB,GAC3B,OAAO,mBAAmB,GAAG,eAAe,KAC3C,KAQF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,KAAK,KAAG,gBA4B/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,OAAO,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC,KACvC,KAIC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.js b/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.js new file mode 100644 index 0000000..d0b727f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.js @@ -0,0 +1,132 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.buildSwapActionData = exports.decodeActionData = exports.encodeActionData = void 0; +const ensureLength = (value, expected, name) => { + if (value.length !== expected) { + throw new Error(`${name} must be ${expected} bytes, got ${value.length}`); + } +}; +const ensureU32 = (value, name) => { + if (!Number.isInteger(value) || value < 0 || value > 0xffffffff) { + throw new Error(`${name} must be uint32, got ${value}`); + } +}; +const writeU32Le = (value, out, offset) => { + out[offset] = value & 0xff; + out[offset + 1] = (value >>> 8) & 0xff; + out[offset + 2] = (value >>> 16) & 0xff; + out[offset + 3] = (value >>> 24) & 0xff; +}; +const readU32Le = (bytes, offset) => (bytes[offset] | + (bytes[offset + 1] << 8) | + (bytes[offset + 2] << 16) | + (bytes[offset + 3] << 24)) >>> + 0; +const SWAP_LEG_SIZE = 1 + 32 + 20 + 8; +const encodeSwapCore = (spec) => { + const legs = []; + const seen = new Set(); + let current = spec; + while (current) { + if (seen.has(current)) { + throw new Error("swap action data has cyclic next reference"); + } + seen.add(current); + ensureLength(current.requestedScriptHash, 32, "requestedScriptHash"); + ensureLength(current.requestedPkh, 20, "requestedPkh"); + ensureU32(current.rateNumerator, "rateNumerator"); + ensureU32(current.rateDenominator, "rateDenominator"); + if (current.rateDenominator === 0 && current.rateNumerator !== 0) { + throw new Error("rateDenominator must be > 0 when rateNumerator is non-zero"); + } + legs.push(current); + current = current.next; + } + const out = new Uint8Array(legs.length * SWAP_LEG_SIZE); + let offset = 0; + for (const leg of legs) { + out[offset++] = 1; + out.set(leg.requestedScriptHash, offset); + offset += 32; + out.set(leg.requestedPkh, offset); + offset += 20; + writeU32Le(leg.rateNumerator, out, offset); + offset += 4; + writeU32Le(leg.rateDenominator, out, offset); + offset += 4; + } + return out; +}; +const decodeSwapCore = (bytes, offset) => { + let nextOffset = offset; + let first; + let tail; + while (nextOffset < bytes.length) { + if (nextOffset + SWAP_LEG_SIZE > bytes.length) { + throw new Error("swap action data is truncated"); + } + if (bytes[nextOffset] !== 1) { + throw new Error("swap action data must start with action=0x01"); + } + const parsed = { + kind: "swap", + requestedScriptHash: bytes.subarray(nextOffset + 1, nextOffset + 33), + requestedPkh: bytes.subarray(nextOffset + 33, nextOffset + 53), + rateNumerator: readU32Le(bytes, nextOffset + 53), + rateDenominator: readU32Le(bytes, nextOffset + 57), + }; + if (!first) { + first = parsed; + tail = parsed; + } + else { + tail.next = parsed; + tail = parsed; + } + nextOffset += SWAP_LEG_SIZE; + } + if (!first) { + throw new Error("swap action data is truncated"); + } + return { parsed: first, nextOffset }; +}; +const encodeActionData = (value) => { + var _a; + if (value.kind === "swap") + return encodeSwapCore(value); + const payload = (_a = value.payload) !== null && _a !== void 0 ? _a : new Uint8Array(0); + const out = new Uint8Array(1 + payload.length); + out[0] = value.action; + out.set(payload, 1); + return out; +}; +exports.encodeActionData = encodeActionData; +const decodeActionData = (bytes) => { + if (bytes.length === 0) + return { kind: "empty" }; + const action = bytes[0]; + if (action === 1) { + const decoded = decodeSwapCore(bytes, 0); + if (decoded.nextOffset !== bytes.length) { + throw new Error("swap action data has trailing bytes"); + } + return decoded.parsed; + } + if (action === 2 || + action === 3) { + return { + kind: "action", + action, + payload: bytes.subarray(1), + }; + } + return { + kind: "unknown", + action, + payload: bytes.subarray(1), + }; +}; +exports.decodeActionData = decodeActionData; +const buildSwapActionData = (value) => (0, exports.encodeActionData)(Object.assign({ kind: "swap" }, value)); +exports.buildSwapActionData = buildSwapActionData; +//# sourceMappingURL=dstas-action-data.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.js.map b/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.js.map new file mode 100644 index 0000000..48f6c50 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-action-data.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-action-data.js","sourceRoot":"","sources":["../../src/script/dstas-action-data.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.d.ts new file mode 100644 index 0000000..66a8705 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.d.ts @@ -0,0 +1,13 @@ +import { Bytes } from "../bytes"; +import { ScriptBuilder } from "./build/script-builder"; +export declare const buildDstasLockingScriptForOwnerField: ({ ownerField, tokenIdHex, freezable, confiscatable, authorityServiceField, confiscationAuthorityServiceField, frozen, }: { + ownerField: Bytes; + tokenIdHex: string; + freezable: boolean; + confiscatable?: boolean; + authorityServiceField: Bytes; + confiscationAuthorityServiceField?: Bytes; + frozen?: boolean; +}) => ScriptBuilder; +export declare const computeDstasRequestedScriptHash: (lockingScript: Bytes | ScriptBuilder) => Uint8Array; +//# sourceMappingURL=dstas-requested-script-hash.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.d.ts.map new file mode 100644 index 0000000..f9b7bbf --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-requested-script-hash.d.ts","sourceRoot":"","sources":["../../src/script/dstas-requested-script-hash.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAW,MAAM,UAAU,CAAC;AAO1C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,eAAO,MAAM,oCAAoC,GAAI,yHAQlD;IACD,UAAU,EAAE,KAAK,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB,EAAE,KAAK,CAAC;IAC7B,iCAAiC,CAAC,EAAE,KAAK,CAAC;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,kBAkBA,CAAC;AAEF,eAAO,MAAM,+BAA+B,GAC1C,eAAe,KAAK,GAAG,aAAa,KACnC,UAAmE,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.js b/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.js new file mode 100644 index 0000000..76de4f5 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.computeDstasRequestedScriptHash = exports.buildDstasLockingScriptForOwnerField = void 0; +const script_type_1 = require("../bitcoin/script-type"); +const bytes_1 = require("../bytes"); +const hashes_1 = require("../hashes"); +const dstas_locking_builder_1 = require("./build/dstas-locking-builder"); +const script_builder_1 = require("./build/script-builder"); +const dstas_swap_script_1 = require("./dstas-swap-script"); +const buildDstasLockingScriptForOwnerField = ({ ownerField, tokenIdHex, freezable, confiscatable = false, authorityServiceField, confiscationAuthorityServiceField, frozen = false, }) => { + const flags = { freezable, confiscatable }; + const tokens = (0, dstas_locking_builder_1.buildDstasLockingTokens)({ + owner: ownerField, + actionData: null, + redemptionPkh: (0, bytes_1.fromHex)(tokenIdHex), + frozen, + flags: (0, dstas_locking_builder_1.buildDstasFlags)(flags), + serviceFields: [ + ...(freezable ? [authorityServiceField] : []), + ...(confiscatable + ? [confiscationAuthorityServiceField !== null && confiscationAuthorityServiceField !== void 0 ? confiscationAuthorityServiceField : authorityServiceField] + : []), + ], + optionalData: [], + }); + return script_builder_1.ScriptBuilder.fromTokens(tokens, script_type_1.ScriptType.dstas); +}; +exports.buildDstasLockingScriptForOwnerField = buildDstasLockingScriptForOwnerField; +const computeDstasRequestedScriptHash = (lockingScript) => (0, hashes_1.sha256)((0, dstas_swap_script_1.extractDstasCounterpartyScript)(lockingScript)); +exports.computeDstasRequestedScriptHash = computeDstasRequestedScriptHash; +//# sourceMappingURL=dstas-requested-script-hash.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.js.map b/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.js.map new file mode 100644 index 0000000..8db3e90 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-requested-script-hash.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-requested-script-hash.js","sourceRoot":"","sources":["../../src/script/dstas-requested-script-hash.ts"],"names":[],"mappings":";;;AAAA,wDAAoD;AACpD,oCAA0C;AAC1C,sCAAmC;AACnC,yEAIuC;AACvC,2DAAuD;AACvD,2DAAqE;AAE9D,MAAM,oCAAoC,GAAG,CAAC,EACnD,UAAU,EACV,UAAU,EACV,SAAS,EACT,aAAa,GAAG,KAAK,EACrB,qBAAqB,EACrB,iCAAiC,EACjC,MAAM,GAAG,KAAK,GASf,EAAE,EAAE;IACH,MAAM,KAAK,GAAoB,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAA,+CAAuB,EAAC;QACrC,KAAK,EAAE,UAAU;QACjB,UAAU,EAAE,IAAI;QAChB,aAAa,EAAE,IAAA,eAAO,EAAC,UAAU,CAAC;QAClC,MAAM;QACN,KAAK,EAAE,IAAA,uCAAe,EAAC,KAAK,CAAC;QAC7B,aAAa,EAAE;YACb,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7C,GAAG,CAAC,aAAa;gBACf,CAAC,CAAC,CAAC,iCAAiC,aAAjC,iCAAiC,cAAjC,iCAAiC,GAAI,qBAAqB,CAAC;gBAC9D,CAAC,CAAC,EAAE,CAAC;SACR;QACD,YAAY,EAAE,EAAE;KACjB,CAAC,CAAC;IAEH,OAAO,8BAAa,CAAC,UAAU,CAAC,MAAM,EAAE,wBAAU,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC,CAAC;AAlCW,QAAA,oCAAoC,wCAkC/C;AAEK,MAAM,+BAA+B,GAAG,CAC7C,aAAoC,EACxB,EAAE,CAAC,IAAA,eAAM,EAAC,IAAA,kDAA8B,EAAC,aAAa,CAAC,CAAC,CAAC;AAF1D,QAAA,+BAA+B,mCAE2B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.d.ts new file mode 100644 index 0000000..cf58a7d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.d.ts @@ -0,0 +1,5 @@ +import { ScriptBuilder } from "./build/script-builder"; +import { Bytes } from "../bytes"; +export declare const extractDstasCounterpartyScript: (lockingScript: Bytes | ScriptBuilder) => Bytes; +export declare const splitDstasPreviousTransactionByCounterpartyScript: (previousTransaction: Bytes, counterpartyScript: Bytes) => Bytes[]; +//# sourceMappingURL=dstas-swap-script.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.d.ts.map new file mode 100644 index 0000000..2d662a2 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-swap-script.d.ts","sourceRoot":"","sources":["../../src/script/dstas-swap-script.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AA4DjC,eAAO,MAAM,8BAA8B,GACzC,eAAe,KAAK,GAAG,aAAa,KACnC,KAcF,CAAC;AA0BF,eAAO,MAAM,iDAAiD,GAC5D,qBAAqB,KAAK,EAC1B,oBAAoB,KAAK,KACxB,KAAK,EAwBP,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.js b/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.js new file mode 100644 index 0000000..5947598 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.js @@ -0,0 +1,103 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.splitDstasPreviousTransactionByCounterpartyScript = exports.extractDstasCounterpartyScript = void 0; +const script_builder_1 = require("./build/script-builder"); +const op_codes_1 = require("../bitcoin/op-codes"); +const readRawChunk = (script, offset) => { + if (offset >= script.length) + return undefined; + const opcode = script[offset]; + if (opcode > op_codes_1.OpCode.OP_0 && opcode < op_codes_1.OpCode.OP_PUSHDATA1) { + const size = opcode; + const start = offset + 1; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA1) { + if (offset + 2 > script.length) + return undefined; + const size = script[offset + 1]; + const start = offset + 2; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA2) { + if (offset + 3 > script.length) + return undefined; + const size = script[offset + 1] | (script[offset + 2] << 8); + const start = offset + 3; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA4) { + if (offset + 5 > script.length) + return undefined; + const size = (script[offset + 1] | + (script[offset + 2] << 8) | + (script[offset + 3] << 16) | + (script[offset + 4] << 24)) >>> + 0; + const start = offset + 5; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + return { opcode, start: offset, end: offset + 1 }; +}; +const asBytes = (value) => value instanceof script_builder_1.ScriptBuilder ? value.toBytes() : value; +const extractDstasCounterpartyScript = (lockingScript) => { + const scriptBytes = asBytes(lockingScript); + const owner = readRawChunk(scriptBytes, 0); + if (!owner || !owner.data || owner.data.length === 0) { + throw new Error("DSTAS locking script must start with owner field"); + } + const second = readRawChunk(scriptBytes, owner.end); + if (!second) { + throw new Error("DSTAS locking script must include action data"); + } + return scriptBytes.subarray(second.end); +}; +exports.extractDstasCounterpartyScript = extractDstasCounterpartyScript; +const findNextOccurrence = (source, needle, from) => { + if (needle.length === 0) { + throw new Error("counterpartyScript must not be empty"); + } + for (let i = from; i <= source.length - needle.length; i++) { + let matched = true; + for (let j = 0; j < needle.length; j++) { + if (source[i + j] !== needle[j]) { + matched = false; + break; + } + } + if (matched) + return i; + } + return -1; +}; +const splitDstasPreviousTransactionByCounterpartyScript = (previousTransaction, counterpartyScript) => { + const pieces = []; + if (counterpartyScript.length === 0) { + throw new Error("counterpartyScript must not be empty"); + } + let cursor = 0; + while (cursor <= previousTransaction.length) { + const match = findNextOccurrence(previousTransaction, counterpartyScript, cursor); + if (match < 0) { + pieces.push(previousTransaction.subarray(cursor)); + break; + } + pieces.push(previousTransaction.subarray(cursor, match)); + cursor = match + counterpartyScript.length; + } + return pieces; +}; +exports.splitDstasPreviousTransactionByCounterpartyScript = splitDstasPreviousTransactionByCounterpartyScript; +//# sourceMappingURL=dstas-swap-script.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.js.map b/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.js.map new file mode 100644 index 0000000..480416a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/dstas-swap-script.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-swap-script.js","sourceRoot":"","sources":["../../src/script/dstas-swap-script.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.d.ts new file mode 100644 index 0000000..127fdee --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.d.ts @@ -0,0 +1,66 @@ +import { Transaction } from "../../bitcoin/transaction"; +import { Bytes } from "../../bytes"; +export type PrevOutput = { + lockingScript: Bytes; + satoshis: number; +}; +export type ScriptEvalContext = { + tx: Transaction; + inputIndex: number; + prevOutputs: PrevOutput[]; +}; +export type ScriptEvalResult = { + success: boolean; + error?: string; + stack: Bytes[]; + altStack: Bytes[]; + trace?: ScriptTraceStep[]; + equalityTrace?: ScriptEqualityStep[]; +}; +export type ScriptEvalOptions = { + allowOpReturn?: boolean; + scriptFlags?: number; + trace?: boolean; + traceLimit?: number; + strict?: boolean; + requireDerSignatures?: boolean; + maxScriptSizeBytes?: number; + maxOps?: number; + maxStackDepth?: number; + maxElementSizeBytes?: number; +}; +export type ScriptTraceStep = { + phase: "unlocking" | "locking"; + pc: number; + opcode: number; + stackDepth: number; + stackTopHex?: string; + altStackDepth: number; +}; +export type ScriptEqualityStep = { + phase: "unlocking" | "locking"; + pc: number; + opcode: number; + leftHex: string; + rightHex: string; + result: boolean; +}; +export declare const SCRIPT_ENABLE_SIGHASH_FORKID: number; +export declare const SCRIPT_ENABLE_MAGNETIC_OPCODES: number; +export declare const SCRIPT_ENABLE_MONOLITH_OPCODES: number; +export type ResolvePrevOutput = (txId: string, vout: number) => PrevOutput | undefined; +export type TransactionInputEvalResult = { + inputIndex: number; + success: boolean; + error?: string; +}; +export type TransactionEvalResult = { + txId: string; + success: boolean; + inputs: TransactionInputEvalResult[]; + errors: string[]; +}; +export declare const evaluateScripts: (unlockingScript: Bytes, lockingScript: Bytes, ctx: ScriptEvalContext, options?: ScriptEvalOptions) => ScriptEvalResult; +export declare const evaluateTransactionHex: (txHex: string, resolvePrevOutput: ResolvePrevOutput, options?: ScriptEvalOptions) => TransactionEvalResult; +export declare const createPrevOutputResolverFromTransactions: (txMap: Map) => ResolvePrevOutput; +//# sourceMappingURL=script-evaluator.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.d.ts.map new file mode 100644 index 0000000..660e673 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script-evaluator.d.ts","sourceRoot":"","sources":["../../../src/script/eval/script-evaluator.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.js b/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.js new file mode 100644 index 0000000..270a921 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.js @@ -0,0 +1,1083 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createPrevOutputResolverFromTransactions = exports.evaluateTransactionHex = exports.evaluateScripts = exports.SCRIPT_ENABLE_MONOLITH_OPCODES = exports.SCRIPT_ENABLE_MAGNETIC_OPCODES = exports.SCRIPT_ENABLE_SIGHASH_FORKID = void 0; +const secp256k1_1 = require("@noble/secp256k1"); +const binary_1 = require("../../binary"); +const buffer_utils_1 = require("../../buffer/buffer-utils"); +const sig_hash_type_1 = require("../../bitcoin/sig-hash-type"); +const op_codes_1 = require("../../bitcoin/op-codes"); +const bytes_1 = require("../../bytes"); +const hashes_1 = require("../../hashes"); +const transaction_reader_1 = require("../../transaction/read/transaction-reader"); +const strict_mode_1 = require("../../security/strict-mode"); +exports.SCRIPT_ENABLE_SIGHASH_FORKID = 1 << 16; +exports.SCRIPT_ENABLE_MAGNETIC_OPCODES = 1 << 17; +exports.SCRIPT_ENABLE_MONOLITH_OPCODES = 1 << 18; +const DEFAULT_SCRIPT_FLAGS = exports.SCRIPT_ENABLE_SIGHASH_FORKID | + exports.SCRIPT_ENABLE_MAGNETIC_OPCODES | + exports.SCRIPT_ENABLE_MONOLITH_OPCODES; +class ScriptEvalError extends Error { + constructor(message) { + super(message); + } +} +const isTruthy = (value) => { + for (let i = 0; i < value.length; i++) { + if (value[i] !== 0) { + if (i === value.length - 1 && value[i] === 0x80) + return false; + return true; + } + } + return false; +}; +const decodeScriptNum = (value) => { + if (value.length === 0) + return BigInt(0); + let result = BigInt(0); + for (let i = 0; i < value.length; i++) { + result |= BigInt(value[i]) << BigInt(8 * i); + } + const signBit = BigInt(1) << BigInt(8 * value.length - 1); + const isNegative = (result & signBit) !== BigInt(0); + if (isNegative) { + result &= signBit - BigInt(1); + return -result; + } + return result; +}; +const encodeScriptNum = (value) => { + if (value === BigInt(0)) + return new Uint8Array(); + const neg = value < BigInt(0); + let absValue = neg ? -value : value; + const result = []; + while (absValue > BigInt(0)) { + result.push(Number(absValue & BigInt(0xff))); + absValue >>= BigInt(8); + } + if ((result[result.length - 1] & 0x80) !== 0) { + result.push(neg ? 0x80 : 0x00); + } + else if (neg) { + result[result.length - 1] |= 0x80; + } + return new Uint8Array(result); +}; +const fromBigInt = (value) => encodeScriptNum(value); +const pushBool = (stack, value) => { + stack.push(value ? new Uint8Array([1]) : new Uint8Array()); +}; +const decodePushData = (script, offset) => { + const opcode = script[offset]; + if (opcode >= 1 && opcode <= 75) { + const size = opcode; + const start = offset + 1; + const end = start + size; + if (end > script.length) + throw new ScriptEvalError("Push out of bounds"); + return { opcode, data: script.subarray(start, end), next: end }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA1) { + if (offset + 2 > script.length) + throw new ScriptEvalError("Pushdata1 out of bounds"); + const size = script[offset + 1]; + const start = offset + 2; + const end = start + size; + if (end > script.length) + throw new ScriptEvalError("Push out of bounds"); + return { opcode, data: script.subarray(start, end), next: end }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA2) { + if (offset + 3 > script.length) + throw new ScriptEvalError("Pushdata2 out of bounds"); + const size = script[offset + 1] | (script[offset + 2] << 8); + const start = offset + 3; + const end = start + size; + if (end > script.length) + throw new ScriptEvalError("Push out of bounds"); + return { opcode, data: script.subarray(start, end), next: end }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA4) { + if (offset + 5 > script.length) + throw new ScriptEvalError("Pushdata4 out of bounds"); + const size = (script[offset + 1] | + (script[offset + 2] << 8) | + (script[offset + 3] << 16) | + (script[offset + 4] << 24)) >>> + 0; + const start = offset + 5; + const end = start + size; + if (end > script.length) + throw new ScriptEvalError("Push out of bounds"); + return { opcode, data: script.subarray(start, end), next: end }; + } + return { opcode, data: undefined, next: offset + 1 }; +}; +const stripCodeSeparators = (script) => { + const parts = []; + let i = 0; + while (i < script.length) { + const { opcode, data, next } = decodePushData(script, i); + if (data !== undefined) { + parts.push(script.subarray(i, next)); + } + else if (opcode !== op_codes_1.OpCode.OP_CODESEPARATOR) { + parts.push(script.subarray(i, next)); + } + i = next; + } + return (0, bytes_1.concat)(parts); +}; +const derDecodeSignature = (der) => { + if (der.length < 8 || der[0] !== 0x30) { + throw new ScriptEvalError("Invalid DER signature"); + } + const totalLen = der[1]; + if (totalLen + 2 !== der.length) { + throw new ScriptEvalError("Invalid DER signature length"); + } + let offset = 2; + if (der[offset++] !== 0x02) + throw new ScriptEvalError("Invalid DER signature"); + const rLen = der[offset++]; + const r = der.subarray(offset, offset + rLen); + offset += rLen; + if (der[offset++] !== 0x02) + throw new ScriptEvalError("Invalid DER signature"); + const sLen = der[offset++]; + const s = der.subarray(offset, offset + sLen); + const bytesToBigInt = (bytes) => { + let result = BigInt(0); + for (const byte of bytes) { + result = (result << BigInt(8)) + BigInt(byte); + } + return result; + }; + return new secp256k1_1.Signature(bytesToBigInt(r), bytesToBigInt(s)); +}; +const parseSignature = (sigWithHashType, requireDerSignatures = false) => { + if (sigWithHashType.length === 0) { + return { signature: new Uint8Array(), sighashType: 0 }; + } + const sighashType = sigWithHashType[sigWithHashType.length - 1]; + const signature = sigWithHashType.subarray(0, sigWithHashType.length - 1); + if (signature.length === 0) { + return { signature: new Uint8Array(), sighashType }; + } + if (requireDerSignatures && signature[0] !== 0x30) { + throw new ScriptEvalError("Non-DER signature is rejected in strict mode"); + } + const sigBytes = signature[0] === 0x30 ? derDecodeSignature(signature).toBytes() : signature; + return { signature: sigBytes, sighashType }; +}; +const writeOutputTo = (writer, output) => { + writer.writeUInt64(output.Satoshis); + writer.writeVarChunk(output.LockingScript); +}; +const outputSize = (output) => 8 + (0, buffer_utils_1.estimateChunkSize)(output.LockingScript.length); +const buildSighashPreimage = (ctx, scriptCode, sighashType) => { + const tx = ctx.tx; + const inputIdx = ctx.inputIndex; + const baseType = sighashType & 0x1f; + const anyoneCanPay = (sighashType & sig_hash_type_1.SignatureHashType.SIGHASH_ANYONECANPAY) !== 0; + const prevoutHash = anyoneCanPay + ? new Uint8Array(32) + : (0, hashes_1.hash256)((0, bytes_1.concat)(tx.Inputs.map((input) => (0, bytes_1.concat)([ + (0, buffer_utils_1.reverseBytes)((0, bytes_1.fromHex)(input.TxId)), + new Uint8Array([ + input.Vout & 0xff, + (input.Vout >> 8) & 0xff, + (input.Vout >> 16) & 0xff, + (input.Vout >> 24) & 0xff, + ]), + ])))); + const sequenceHash = anyoneCanPay || + baseType === sig_hash_type_1.SignatureHashType.SIGHASH_NONE || + baseType === sig_hash_type_1.SignatureHashType.SIGHASH_SINGLE + ? new Uint8Array(32) + : (0, hashes_1.hash256)((0, bytes_1.concat)(tx.Inputs.map((input) => new Uint8Array([ + input.Sequence & 0xff, + (input.Sequence >> 8) & 0xff, + (input.Sequence >> 16) & 0xff, + (input.Sequence >> 24) & 0xff, + ])))); + let outputsHash = new Uint8Array(32); + if (baseType === sig_hash_type_1.SignatureHashType.SIGHASH_ALL) { + const outputsSize = tx.Outputs.reduce((sum, out) => sum + outputSize(out), 0); + const outputsBuffer = new Uint8Array(outputsSize); + const outputsWriter = new binary_1.ByteWriter(outputsBuffer); + for (const output of tx.Outputs) + writeOutputTo(outputsWriter, output); + outputsHash = (0, hashes_1.hash256)(outputsBuffer); + } + else if (baseType === sig_hash_type_1.SignatureHashType.SIGHASH_SINGLE) { + if (inputIdx < tx.Outputs.length) { + const output = tx.Outputs[inputIdx]; + const singleBuffer = new Uint8Array(outputSize(output)); + const singleWriter = new binary_1.ByteWriter(singleBuffer); + writeOutputTo(singleWriter, output); + outputsHash = (0, hashes_1.hash256)(singleBuffer); + } + } + const prevOutput = ctx.prevOutputs[inputIdx]; + if (!prevOutput) + throw new ScriptEvalError("Missing prev output for input"); + const scriptChunk = stripCodeSeparators(scriptCode); + const preimageSize = 4 + 32 + 32 + 32 + 4 + (0, buffer_utils_1.getChunkSize)(scriptChunk) + 8 + 4 + 32 + 4 + 4; + const preimageBuffer = new Uint8Array(preimageSize); + const preimageWriter = new binary_1.ByteWriter(preimageBuffer); + preimageWriter.writeUInt32(tx.Version); + preimageWriter.writeChunk(prevoutHash); + preimageWriter.writeChunk(sequenceHash); + preimageWriter.writeChunk((0, buffer_utils_1.reverseBytes)((0, bytes_1.fromHex)(tx.Inputs[inputIdx].TxId))); + preimageWriter.writeUInt32(tx.Inputs[inputIdx].Vout); + preimageWriter.writeVarChunk(scriptChunk); + preimageWriter.writeUInt64(prevOutput.satoshis); + preimageWriter.writeUInt32(tx.Inputs[inputIdx].Sequence); + preimageWriter.writeChunk(outputsHash); + preimageWriter.writeUInt32(tx.LockTime); + preimageWriter.writeUInt32(sighashType >>> 0); + return preimageBuffer; +}; +class ScriptInterpreter { + constructor(ctx, options) { + var _a, _b, _c, _d, _e, _f, _g, _h; + this.stack = []; + this.altStack = []; + this.execStack = []; + this.script = new Uint8Array(); + this.codeSeparator = -1; + this.tracePhase = "unlocking"; + this.trace = []; + this.equalityTrace = []; + this.opCount = 0; + this.getStack = () => this.stack; + this.getAltStack = () => this.altStack; + this.getTrace = () => this.trace; + this.getEqualityTrace = () => this.equalityTrace; + this.setTracePhase = (phase) => { + this.tracePhase = phase; + }; + this.isExecuting = () => this.execStack.every((v) => v); + this.pop = () => { + if (this.stack.length === 0) + throw new ScriptEvalError("Stack underflow"); + return this.stack.pop(); + }; + this.popNum = () => decodeScriptNum(this.pop()); + this.popBool = () => isTruthy(this.pop()); + this.ensureElementSize = (value) => { + if (this.strictMode && value.length > this.maxElementSizeBytes) { + throw new ScriptEvalError(`Script element exceeds strict limit: ${value.length} > ${this.maxElementSizeBytes}`); + } + }; + this.ensureStackDepth = () => { + if (this.strictMode && + this.stack.length + this.altStack.length > this.maxStackDepth) { + throw new ScriptEvalError(`Stack depth exceeds strict limit: ${this.stack.length + this.altStack.length} > ${this.maxStackDepth}`); + } + }; + this.push = (value) => { + this.ensureElementSize(value); + this.stack.push(value); + this.ensureStackDepth(); + }; + this.top = () => { + if (this.stack.length === 0) + throw new ScriptEvalError("Stack underflow"); + return this.stack[this.stack.length - 1]; + }; + this.getScriptCode = () => { + const start = this.codeSeparator + 1; + return this.script.subarray(start); + }; + this.hasFlag = (flag) => (this.scriptFlags & flag) !== 0; + this.requireMonolithOpcodes = () => { + if (!this.hasFlag(exports.SCRIPT_ENABLE_MONOLITH_OPCODES)) { + throw new ScriptEvalError("Monolith opcodes disabled"); + } + }; + this.requireMagneticOpcodes = () => { + if (!this.hasFlag(exports.SCRIPT_ENABLE_MAGNETIC_OPCODES)) { + throw new ScriptEvalError("Magnetic opcodes disabled"); + } + }; + this.execute = (script) => { + if (this.strictMode && script.length > this.maxScriptSizeBytes) { + throw new ScriptEvalError(`Script exceeds strict size limit: ${script.length} > ${this.maxScriptSizeBytes}`); + } + this.script = script; + this.codeSeparator = -1; + let pc = 0; + while (pc < script.length) { + const { opcode, data, next } = decodePushData(script, pc); + const executing = this.isExecuting(); + if (data !== undefined) { + if (executing) + this.push(data); + pc = next; + continue; + } + this.opCount++; + if (this.strictMode && this.opCount > this.maxOps) { + throw new ScriptEvalError(`Opcode count exceeds strict limit: ${this.opCount} > ${this.maxOps}`); + } + if (!executing) { + if (opcode === op_codes_1.OpCode.OP_IF || + opcode === op_codes_1.OpCode.OP_NOTIF || + opcode === op_codes_1.OpCode.OP_ELSE || + opcode === op_codes_1.OpCode.OP_ENDIF) { + this.execControl(opcode); + } + pc = next; + continue; + } + const halt = this.execOp(opcode, pc); + if (this.traceEnabled) { + const top = this.stack.length > 0 ? this.stack[this.stack.length - 1] : undefined; + this.trace.push({ + phase: this.tracePhase, + pc, + opcode, + stackDepth: this.stack.length, + stackTopHex: top ? (0, bytes_1.toHex)(top) : undefined, + altStackDepth: this.altStack.length, + }); + if (this.trace.length > this.traceLimit) + this.trace.shift(); + } + if (halt) + break; + pc = next; + } + if (this.execStack.length !== 0) + throw new ScriptEvalError("Unbalanced conditional"); + }; + this.execControl = (opcode) => { + if (opcode === op_codes_1.OpCode.OP_IF || opcode === op_codes_1.OpCode.OP_NOTIF) { + if (this.isExecuting()) { + const cond = this.popBool(); + this.execStack.push(opcode === op_codes_1.OpCode.OP_IF ? cond : !cond); + } + else { + this.execStack.push(false); + } + return; + } + if (opcode === op_codes_1.OpCode.OP_ELSE) { + if (this.execStack.length === 0) + throw new ScriptEvalError("OP_ELSE without OP_IF"); + const parentExec = this.execStack + .slice(0, this.execStack.length - 1) + .every((v) => v); + if (parentExec) { + this.execStack[this.execStack.length - 1] = + !this.execStack[this.execStack.length - 1]; + } + return; + } + if (opcode === op_codes_1.OpCode.OP_ENDIF) { + if (this.execStack.length === 0) + throw new ScriptEvalError("OP_ENDIF without OP_IF"); + this.execStack.pop(); + } + }; + this.execOp = (opcode, pc) => { + switch (opcode) { + case op_codes_1.OpCode.OP_0: + this.push(new Uint8Array()); + return; + case op_codes_1.OpCode.OP_1NEGATE: + this.push(fromBigInt(BigInt(-1))); + return; + case op_codes_1.OpCode.OP_1: + case op_codes_1.OpCode.OP_2: + case op_codes_1.OpCode.OP_3: + case op_codes_1.OpCode.OP_4: + case op_codes_1.OpCode.OP_5: + case op_codes_1.OpCode.OP_6: + case op_codes_1.OpCode.OP_7: + case op_codes_1.OpCode.OP_8: + case op_codes_1.OpCode.OP_9: + case op_codes_1.OpCode.OP_10: + case op_codes_1.OpCode.OP_11: + case op_codes_1.OpCode.OP_12: + case op_codes_1.OpCode.OP_13: + case op_codes_1.OpCode.OP_14: + case op_codes_1.OpCode.OP_15: + case op_codes_1.OpCode.OP_16: + this.push(fromBigInt(BigInt(opcode - op_codes_1.OpCode.OP_1 + 1))); + return; + case op_codes_1.OpCode.OP_NOP: + case op_codes_1.OpCode.OP_NOP1: + case op_codes_1.OpCode.OP_NOP4: + case op_codes_1.OpCode.OP_NOP5: + case op_codes_1.OpCode.OP_NOP6: + case op_codes_1.OpCode.OP_NOP7: + case op_codes_1.OpCode.OP_NOP8: + case op_codes_1.OpCode.OP_NOP9: + case op_codes_1.OpCode.OP_NOP10: + return; + case op_codes_1.OpCode.OP_VERIFY: { + const ok = this.popBool(); + if (!ok) + throw new ScriptEvalError("OP_VERIFY failed"); + return; + } + case op_codes_1.OpCode.OP_RETURN: + if (this.allowOpReturn) + return true; + throw new ScriptEvalError("OP_RETURN"); + case op_codes_1.OpCode.OP_IF: + case op_codes_1.OpCode.OP_NOTIF: + case op_codes_1.OpCode.OP_ELSE: + case op_codes_1.OpCode.OP_ENDIF: + return this.execControl(opcode); + case op_codes_1.OpCode.OP_TOALTSTACK: + this.altStack.push(this.pop()); + this.ensureStackDepth(); + return; + case op_codes_1.OpCode.OP_FROMALTSTACK: + if (this.altStack.length === 0) + throw new ScriptEvalError("Alt stack underflow"); + this.push(this.altStack.pop()); + return; + case op_codes_1.OpCode.OP_2DROP: + this.pop(); + this.pop(); + return; + case op_codes_1.OpCode.OP_2DUP: { + const a = this.pop(); + const b = this.pop(); + this.push(b); + this.push(a); + this.push((0, buffer_utils_1.cloneBytes)(b)); + this.push((0, buffer_utils_1.cloneBytes)(a)); + return; + } + case op_codes_1.OpCode.OP_3DUP: { + const a = this.pop(); + const b = this.pop(); + const c = this.pop(); + this.push(c); + this.push(b); + this.push(a); + this.push((0, buffer_utils_1.cloneBytes)(c)); + this.push((0, buffer_utils_1.cloneBytes)(b)); + this.push((0, buffer_utils_1.cloneBytes)(a)); + return; + } + case op_codes_1.OpCode.OP_2OVER: { + if (this.stack.length < 4) + throw new ScriptEvalError("Stack underflow"); + this.push((0, buffer_utils_1.cloneBytes)(this.stack[this.stack.length - 4])); + this.push((0, buffer_utils_1.cloneBytes)(this.stack[this.stack.length - 3])); + return; + } + case op_codes_1.OpCode.OP_2ROT: { + if (this.stack.length < 6) + throw new ScriptEvalError("Stack underflow"); + const a = this.stack.splice(this.stack.length - 6, 2); + this.stack.push(a[0], a[1]); + return; + } + case op_codes_1.OpCode.OP_2SWAP: { + if (this.stack.length < 4) + throw new ScriptEvalError("Stack underflow"); + const a = this.stack.splice(this.stack.length - 4, 2); + this.stack.push(a[0], a[1]); + return; + } + case op_codes_1.OpCode.OP_IFDUP: { + if (this.stack.length === 0) + throw new ScriptEvalError("Stack underflow"); + if (isTruthy(this.top())) + this.push((0, buffer_utils_1.cloneBytes)(this.top())); + return; + } + case op_codes_1.OpCode.OP_DEPTH: + this.push(fromBigInt(BigInt(this.stack.length))); + return; + case op_codes_1.OpCode.OP_DROP: + this.pop(); + return; + case op_codes_1.OpCode.OP_DUP: + this.push((0, buffer_utils_1.cloneBytes)(this.top())); + return; + case op_codes_1.OpCode.OP_NIP: { + const a = this.pop(); + this.pop(); + this.push(a); + return; + } + case op_codes_1.OpCode.OP_OVER: { + if (this.stack.length < 2) + throw new ScriptEvalError("Stack underflow"); + this.push((0, buffer_utils_1.cloneBytes)(this.stack[this.stack.length - 2])); + return; + } + case op_codes_1.OpCode.OP_PICK: { + const n = Number(this.popNum()); + if (n < 0 || n >= this.stack.length) + throw new ScriptEvalError("OP_PICK out of range"); + this.push((0, buffer_utils_1.cloneBytes)(this.stack[this.stack.length - 1 - n])); + return; + } + case op_codes_1.OpCode.OP_ROLL: { + const n = Number(this.popNum()); + if (n < 0 || n >= this.stack.length) + throw new ScriptEvalError("OP_ROLL out of range"); + const idx = this.stack.length - 1 - n; + const [val] = this.stack.splice(idx, 1); + this.push(val); + return; + } + case op_codes_1.OpCode.OP_ROT: { + if (this.stack.length < 3) + throw new ScriptEvalError("Stack underflow"); + const a = this.stack.splice(this.stack.length - 3, 1)[0]; + this.stack.push(a); + return; + } + case op_codes_1.OpCode.OP_SWAP: { + if (this.stack.length < 2) + throw new ScriptEvalError("Stack underflow"); + const a = this.pop(); + const b = this.pop(); + this.push(a); + this.push(b); + return; + } + case op_codes_1.OpCode.OP_TUCK: { + if (this.stack.length < 2) + throw new ScriptEvalError("Stack underflow"); + const a = this.pop(); + const b = this.pop(); + this.push((0, buffer_utils_1.cloneBytes)(a)); + this.push(b); + this.push(a); + return; + } + case op_codes_1.OpCode.OP_CAT: { + this.requireMonolithOpcodes(); + const b = this.pop(); + const a = this.pop(); + this.push((0, bytes_1.concat)([a, b])); + return; + } + case op_codes_1.OpCode.OP_SPLIT: { + this.requireMonolithOpcodes(); + const pos = Number(this.popNum()); + const data = this.pop(); + if (pos < 0 || pos > data.length) + throw new ScriptEvalError("OP_SPLIT out of range"); + this.push(data.subarray(0, pos)); + this.push(data.subarray(pos)); + return; + } + case op_codes_1.OpCode.OP_NUM2BIN: { + this.requireMonolithOpcodes(); + const size = Number(this.popNum()); + const num = this.popNum(); + if (size < 0) + throw new ScriptEvalError("OP_NUM2BIN size < 0"); + if (size === 0) { + if (num !== BigInt(0)) + throw new ScriptEvalError("OP_NUM2BIN overflow"); + this.push(new Uint8Array()); + return; + } + const minimal = fromBigInt(num); + if (minimal.length > size) + throw new ScriptEvalError("OP_NUM2BIN overflow"); + if (minimal.length === size) { + this.push(minimal); + return; + } + const out = new Uint8Array(size); + out.set(minimal); + if (num < BigInt(0)) { + if (minimal.length > 0) { + out[minimal.length - 1] &= 0x7f; + } + out[size - 1] |= 0x80; + } + this.push(out); + return; + } + case op_codes_1.OpCode.OP_BIN2NUM: { + this.requireMonolithOpcodes(); + const num = this.popNum(); + this.push(fromBigInt(num)); + return; + } + case op_codes_1.OpCode.OP_SIZE: { + this.push(fromBigInt(BigInt(this.top().length))); + return; + } + case op_codes_1.OpCode.OP_INVERT: { + this.requireMonolithOpcodes(); + const data = this.pop(); + const out = new Uint8Array(data.length); + for (let i = 0; i < data.length; i++) + out[i] = data[i] ^ 0xff; + this.push(out); + return; + } + case op_codes_1.OpCode.OP_AND: + case op_codes_1.OpCode.OP_OR: + case op_codes_1.OpCode.OP_XOR: { + this.requireMonolithOpcodes(); + const b = this.pop(); + const a = this.pop(); + if (a.length !== b.length) + throw new ScriptEvalError("Bitwise length mismatch"); + const out = new Uint8Array(a.length); + for (let i = 0; i < a.length; i++) { + if (opcode === op_codes_1.OpCode.OP_AND) + out[i] = a[i] & b[i]; + else if (opcode === op_codes_1.OpCode.OP_OR) + out[i] = a[i] | b[i]; + else + out[i] = a[i] ^ b[i]; + } + this.push(out); + return; + } + case op_codes_1.OpCode.OP_EQUAL: { + const b = this.pop(); + const a = this.pop(); + const ok = (0, bytes_1.equal)(a, b); + if (this.traceEnabled) { + this.equalityTrace.push({ + phase: this.tracePhase, + pc, + opcode, + leftHex: (0, bytes_1.toHex)(a), + rightHex: (0, bytes_1.toHex)(b), + result: ok, + }); + if (this.equalityTrace.length > this.traceLimit) + this.equalityTrace.shift(); + } + pushBool(this.stack, ok); + return; + } + case op_codes_1.OpCode.OP_EQUALVERIFY: { + const b = this.pop(); + const a = this.pop(); + const ok = (0, bytes_1.equal)(a, b); + if (this.traceEnabled) { + this.equalityTrace.push({ + phase: this.tracePhase, + pc, + opcode, + leftHex: (0, bytes_1.toHex)(a), + rightHex: (0, bytes_1.toHex)(b), + result: ok, + }); + if (this.equalityTrace.length > this.traceLimit) + this.equalityTrace.shift(); + } + if (!ok) + throw new ScriptEvalError("OP_EQUALVERIFY failed"); + return; + } + case op_codes_1.OpCode.OP_1ADD: + this.push(fromBigInt(this.popNum() + BigInt(1))); + return; + case op_codes_1.OpCode.OP_1SUB: + this.push(fromBigInt(this.popNum() - BigInt(1))); + return; + case op_codes_1.OpCode.OP_2MUL: + this.push(fromBigInt(this.popNum() * BigInt(2))); + return; + case op_codes_1.OpCode.OP_2DIV: + this.push(fromBigInt(this.popNum() / BigInt(2))); + return; + case op_codes_1.OpCode.OP_NEGATE: + this.push(fromBigInt(-this.popNum())); + return; + case op_codes_1.OpCode.OP_ABS: { + const n = this.popNum(); + this.push(fromBigInt(n < BigInt(0) ? -n : n)); + return; + } + case op_codes_1.OpCode.OP_NOT: + pushBool(this.stack, this.popNum() === BigInt(0)); + return; + case op_codes_1.OpCode.OP_0NOTEQUAL: + pushBool(this.stack, this.popNum() !== BigInt(0)); + return; + case op_codes_1.OpCode.OP_ADD: { + const b = this.popNum(); + const a = this.popNum(); + this.push(fromBigInt(a + b)); + return; + } + case op_codes_1.OpCode.OP_SUB: { + const b = this.popNum(); + const a = this.popNum(); + this.push(fromBigInt(a - b)); + return; + } + case op_codes_1.OpCode.OP_MUL: { + this.requireMagneticOpcodes(); + const b = this.popNum(); + const a = this.popNum(); + this.push(fromBigInt(a * b)); + return; + } + case op_codes_1.OpCode.OP_DIV: { + this.requireMagneticOpcodes(); + const b = this.popNum(); + if (b === BigInt(0)) + throw new ScriptEvalError("OP_DIV by zero"); + const a = this.popNum(); + this.push(fromBigInt(a / b)); + return; + } + case op_codes_1.OpCode.OP_MOD: { + this.requireMagneticOpcodes(); + const b = this.popNum(); + if (b === BigInt(0)) + throw new ScriptEvalError("OP_MOD by zero"); + const a = this.popNum(); + this.push(fromBigInt(a % b)); + return; + } + case op_codes_1.OpCode.OP_LSHIFT: { + this.requireMagneticOpcodes(); + const b = this.popNum(); + const a = this.popNum(); + this.push(fromBigInt(a << b)); + return; + } + case op_codes_1.OpCode.OP_RSHIFT: { + this.requireMagneticOpcodes(); + const b = this.popNum(); + const a = this.popNum(); + this.push(fromBigInt(a >> b)); + return; + } + case op_codes_1.OpCode.OP_BOOLAND: { + const b = this.popNum(); + const a = this.popNum(); + pushBool(this.stack, a !== BigInt(0) && b !== BigInt(0)); + return; + } + case op_codes_1.OpCode.OP_BOOLOR: { + const b = this.popNum(); + const a = this.popNum(); + pushBool(this.stack, a !== BigInt(0) || b !== BigInt(0)); + return; + } + case op_codes_1.OpCode.OP_NUMEQUAL: { + const b = this.popNum(); + const a = this.popNum(); + pushBool(this.stack, a === b); + return; + } + case op_codes_1.OpCode.OP_NUMEQUALVERIFY: { + const b = this.popNum(); + const a = this.popNum(); + if (a !== b) + throw new ScriptEvalError("OP_NUMEQUALVERIFY failed"); + return; + } + case op_codes_1.OpCode.OP_NUMNOTEQUAL: { + const b = this.popNum(); + const a = this.popNum(); + pushBool(this.stack, a !== b); + return; + } + case op_codes_1.OpCode.OP_LESSTHAN: { + const b = this.popNum(); + const a = this.popNum(); + pushBool(this.stack, a < b); + return; + } + case op_codes_1.OpCode.OP_GREATERTHAN: { + const b = this.popNum(); + const a = this.popNum(); + pushBool(this.stack, a > b); + return; + } + case op_codes_1.OpCode.OP_LESSTHANOREQUAL: { + const b = this.popNum(); + const a = this.popNum(); + pushBool(this.stack, a <= b); + return; + } + case op_codes_1.OpCode.OP_GREATERTHANOREQUAL: { + const b = this.popNum(); + const a = this.popNum(); + pushBool(this.stack, a >= b); + return; + } + case op_codes_1.OpCode.OP_MIN: { + const b = this.popNum(); + const a = this.popNum(); + this.push(fromBigInt(a < b ? a : b)); + return; + } + case op_codes_1.OpCode.OP_MAX: { + const b = this.popNum(); + const a = this.popNum(); + this.push(fromBigInt(a > b ? a : b)); + return; + } + case op_codes_1.OpCode.OP_WITHIN: { + const max = this.popNum(); + const min = this.popNum(); + const x = this.popNum(); + pushBool(this.stack, x >= min && x < max); + return; + } + case op_codes_1.OpCode.OP_RIPEMD160: { + const data = this.pop(); + this.push((0, hashes_1.ripemd160)(data)); + return; + } + case op_codes_1.OpCode.OP_SHA1: + throw new ScriptEvalError("OP_SHA1 not supported"); + case op_codes_1.OpCode.OP_SHA256: { + const data = this.pop(); + this.push((0, hashes_1.sha256)(data)); + return; + } + case op_codes_1.OpCode.OP_HASH160: { + const data = this.pop(); + this.push((0, hashes_1.hash160)(data)); + return; + } + case op_codes_1.OpCode.OP_HASH256: { + const data = this.pop(); + this.push((0, hashes_1.hash256)(data)); + return; + } + case op_codes_1.OpCode.OP_CODESEPARATOR: + this.codeSeparator = pc; + return; + case op_codes_1.OpCode.OP_CHECKSIG: + case op_codes_1.OpCode.OP_CHECKSIGVERIFY: { + const pubKey = this.pop(); + const sigWithType = this.pop(); + const { signature, sighashType } = parseSignature(sigWithType, this.requireDerSignatures); + const requireForkId = this.hasFlag(exports.SCRIPT_ENABLE_SIGHASH_FORKID); + const hasForkId = (sighashType & sig_hash_type_1.SignatureHashType.SIGHASH_FORKID) === + sig_hash_type_1.SignatureHashType.SIGHASH_FORKID; + if (requireForkId && !hasForkId) { + if (opcode === op_codes_1.OpCode.OP_CHECKSIGVERIFY) { + throw new ScriptEvalError("OP_CHECKSIGVERIFY missing FORKID"); + } + pushBool(this.stack, false); + return; + } + const scriptCode = this.getScriptCode(); + const preimage = buildSighashPreimage(this.ctx, scriptCode, sighashType); + const msg = (0, hashes_1.hash256)(preimage); + const ok = (() => { + try { + return (signature.length > 0 && + (0, secp256k1_1.verify)(signature, msg, pubKey, { + prehash: false, + format: "compact", + })); + } + catch (_a) { + return false; + } + })(); + if (opcode === op_codes_1.OpCode.OP_CHECKSIGVERIFY) { + if (!ok) + throw new ScriptEvalError("OP_CHECKSIGVERIFY failed"); + return; + } + pushBool(this.stack, ok); + return; + } + case op_codes_1.OpCode.OP_CHECKMULTISIG: + case op_codes_1.OpCode.OP_CHECKMULTISIGVERIFY: { + const n = Number(this.popNum()); + if (n < 0 || n > this.stack.length) + throw new ScriptEvalError("OP_CHECKMULTISIG invalid pubkey count"); + const pubKeys = this.stack.splice(this.stack.length - n, n); + const m = Number(this.popNum()); + if (m < 0 || m > this.stack.length) + throw new ScriptEvalError("OP_CHECKMULTISIG invalid sig count"); + const sigs = this.stack.splice(this.stack.length - m, m); + this.pop(); + let sigIdx = 0; + let keyIdx = 0; + let ok = false; + try { + while (sigIdx < m && keyIdx < n) { + const { signature, sighashType } = parseSignature(sigs[sigIdx], this.requireDerSignatures); + const requireForkId = this.hasFlag(exports.SCRIPT_ENABLE_SIGHASH_FORKID); + const hasForkId = (sighashType & sig_hash_type_1.SignatureHashType.SIGHASH_FORKID) === + sig_hash_type_1.SignatureHashType.SIGHASH_FORKID; + if (requireForkId && !hasForkId) { + keyIdx++; + continue; + } + const scriptCode = this.getScriptCode(); + const preimage = buildSighashPreimage(this.ctx, scriptCode, sighashType); + const msg = (0, hashes_1.hash256)(preimage); + const matched = signature.length > 0 && + (0, secp256k1_1.verify)(signature, msg, pubKeys[keyIdx], { + prehash: false, + format: "compact", + }); + if (matched) + sigIdx++; + keyIdx++; + } + ok = sigIdx === m; + } + catch (_a) { + ok = false; + } + const success = ok; + if (opcode === op_codes_1.OpCode.OP_CHECKMULTISIGVERIFY) { + if (!success) + throw new ScriptEvalError("OP_CHECKMULTISIGVERIFY failed"); + return; + } + pushBool(this.stack, success); + return; + } + case op_codes_1.OpCode.OP_CHECKLOCKTIMEVERIFY: { + const locktime = Number(decodeScriptNum(this.top())); + if (locktime < 0) + throw new ScriptEvalError("CLTV negative"); + const txLock = this.ctx.tx.LockTime; + const txInput = this.ctx.tx.Inputs[this.ctx.inputIndex]; + if (txInput.Sequence === 0xffffffff) + throw new ScriptEvalError("CLTV disabled by sequence"); + if ((locktime < 500000000 && txLock >= 500000000) || + (locktime >= 500000000 && txLock < 500000000)) + throw new ScriptEvalError("CLTV locktime type mismatch"); + if (txLock < locktime) + throw new ScriptEvalError("CLTV not yet reached"); + return; + } + case op_codes_1.OpCode.OP_CHECKSEQUENCEVERIFY: + throw new ScriptEvalError("OP_CHECKSEQUENCEVERIFY not supported"); + case op_codes_1.OpCode.OP_RESERVED: + case op_codes_1.OpCode.OP_VER: + case op_codes_1.OpCode.OP_VERIF: + case op_codes_1.OpCode.OP_VERNOTIF: + case op_codes_1.OpCode.OP_RESERVED1: + case op_codes_1.OpCode.OP_RESERVED2: + throw new ScriptEvalError("Disabled opcode"); + default: + throw new ScriptEvalError(`Unsupported opcode: 0x${opcode.toString(16)}`); + } + }; + const strictConfig = (0, strict_mode_1.getStrictModeConfig)(); + const strict = (_a = options === null || options === void 0 ? void 0 : options.strict) !== null && _a !== void 0 ? _a : strictConfig.strictScriptEvaluation; + this.ctx = ctx; + this.allowOpReturn = (options === null || options === void 0 ? void 0 : options.allowOpReturn) === true; + this.scriptFlags = (_b = options === null || options === void 0 ? void 0 : options.scriptFlags) !== null && _b !== void 0 ? _b : DEFAULT_SCRIPT_FLAGS; + this.traceEnabled = (options === null || options === void 0 ? void 0 : options.trace) === true; + this.traceLimit = (_c = options === null || options === void 0 ? void 0 : options.traceLimit) !== null && _c !== void 0 ? _c : 400; + this.strictMode = strict; + this.requireDerSignatures = (_d = options === null || options === void 0 ? void 0 : options.requireDerSignatures) !== null && _d !== void 0 ? _d : strict; + this.maxScriptSizeBytes = + (_e = options === null || options === void 0 ? void 0 : options.maxScriptSizeBytes) !== null && _e !== void 0 ? _e : strictConfig.scriptEvaluationLimits.maxScriptSizeBytes; + this.maxOps = (_f = options === null || options === void 0 ? void 0 : options.maxOps) !== null && _f !== void 0 ? _f : strictConfig.scriptEvaluationLimits.maxOps; + this.maxStackDepth = + (_g = options === null || options === void 0 ? void 0 : options.maxStackDepth) !== null && _g !== void 0 ? _g : strictConfig.scriptEvaluationLimits.maxStackDepth; + this.maxElementSizeBytes = + (_h = options === null || options === void 0 ? void 0 : options.maxElementSizeBytes) !== null && _h !== void 0 ? _h : strictConfig.scriptEvaluationLimits.maxElementSizeBytes; + } +} +const evaluateScripts = (unlockingScript, lockingScript, ctx, options) => { + const interpreter = new ScriptInterpreter(ctx, options); + try { + interpreter.setTracePhase("unlocking"); + interpreter.execute(unlockingScript); + interpreter.setTracePhase("locking"); + interpreter.execute(lockingScript); + const stack = interpreter.getStack(); + const success = stack.length > 0 && isTruthy(stack[stack.length - 1]); + return { + success, + stack, + altStack: interpreter.getAltStack(), + trace: interpreter.getTrace(), + equalityTrace: interpreter.getEqualityTrace(), + error: success ? undefined : "Script evaluated to false", + }; + } + catch (err) { + return { + success: false, + stack: interpreter.getStack(), + altStack: interpreter.getAltStack(), + trace: interpreter.getTrace(), + equalityTrace: interpreter.getEqualityTrace(), + error: err instanceof Error ? err.message : "Script error", + }; + } +}; +exports.evaluateScripts = evaluateScripts; +const evaluateTransactionHex = (txHex, resolvePrevOutput, options) => { + const tx = transaction_reader_1.TransactionReader.readHex(txHex); + const inputResults = []; + const errors = []; + const prevOutputs = []; + for (let i = 0; i < tx.Inputs.length; i++) { + const input = tx.Inputs[i]; + const prev = resolvePrevOutput(input.TxId, input.Vout); + if (!prev) { + const error = `Missing prev output for input ${i}: ${input.TxId}:${input.Vout}`; + inputResults.push({ inputIndex: i, success: false, error }); + errors.push(error); + prevOutputs.push({ lockingScript: new Uint8Array(), satoshis: 0 }); + continue; + } + prevOutputs.push(prev); + } + for (let i = 0; i < tx.Inputs.length; i++) { + if (inputResults.some((r) => r.inputIndex === i && !r.success)) + continue; + const result = (0, exports.evaluateScripts)(tx.Inputs[i].UnlockingScript, prevOutputs[i].lockingScript, { tx, inputIndex: i, prevOutputs }, options); + if (!result.success) { + inputResults.push({ + inputIndex: i, + success: false, + error: result.error, + }); + errors.push(`Input ${i} failed: ${result.error}`); + } + else { + inputResults.push({ inputIndex: i, success: true }); + } + } + return { + txId: tx.Id, + success: inputResults.every((r) => r.success), + inputs: inputResults.sort((a, b) => a.inputIndex - b.inputIndex), + errors, + }; +}; +exports.evaluateTransactionHex = evaluateTransactionHex; +const createPrevOutputResolverFromTransactions = (txMap) => { + return (txId, vout) => { + const tx = txMap.get(txId); + if (!tx) + return undefined; + const output = tx.Outputs[vout]; + if (!output) + return undefined; + return { + lockingScript: output.LockingScript, + satoshis: output.Satoshis, + }; + }; +}; +exports.createPrevOutputResolverFromTransactions = createPrevOutputResolverFromTransactions; +//# sourceMappingURL=script-evaluator.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.js.map b/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.js.map new file mode 100644 index 0000000..ec8e51b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/eval/script-evaluator.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script-evaluator.js","sourceRoot":"","sources":["../../../src/script/eval/script-evaluator.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/identity-field.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/identity-field.d.ts new file mode 100644 index 0000000..9c0d5e4 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/identity-field.d.ts @@ -0,0 +1,13 @@ +import { Bytes } from "../bytes"; +export declare const isCanonicalMpkhField: (value: Bytes) => boolean; +export declare const isSupportedIdentityField: (value: Bytes) => boolean; +export declare const assertSupportedIdentityField: (value: Bytes, name: string) => void; +export declare const sameBytesOrShape: (expected: { + OpCodeNum: number; + DataLength: number; + Data?: Bytes; +}, actual: { + OpCodeNum: number; + Data: Bytes; +}) => boolean; +//# sourceMappingURL=identity-field.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/identity-field.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/identity-field.d.ts.map new file mode 100644 index 0000000..1c17d72 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/identity-field.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"identity-field.d.ts","sourceRoot":"","sources":["../../src/script/identity-field.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAgB,MAAM,UAAU,CAAC;AAK/C,eAAO,MAAM,oBAAoB,GAAI,OAAO,KAAK,KAAG,OA+BnD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,OAAO,KAAK,KAAG,OACJ,CAAC;AAErD,eAAO,MAAM,4BAA4B,GACvC,OAAO,KAAK,EACZ,MAAM,MAAM,KACX,IAMF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,UAAU;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CAAE,EACjE,QAAQ;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,KACzC,OAIF,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/identity-field.js b/vendor/dxs-bsv-token-sdk/dist/script/identity-field.js new file mode 100644 index 0000000..bef1275 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/identity-field.js @@ -0,0 +1,59 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sameBytesOrShape = exports.assertSupportedIdentityField = exports.isSupportedIdentityField = exports.isCanonicalMpkhField = void 0; +const secp256k1_1 = require("@noble/secp256k1"); +const bytes_1 = require("../bytes"); +const isCompressedPubKey = (key) => key.length === 33 && (key[0] === 0x02 || key[0] === 0x03); +const isCanonicalMpkhField = (value) => { + if (value.length < 36) + return false; + const m = value[0]; + const n = value[value.length - 1]; + if (n <= 0 || n > 5) + return false; + if (m <= 0 || m > n) + return false; + if (value.length !== 1 + n * 34 + 1) + return false; + const seen = new Set(); + let offset = 1; + for (let i = 0; i < n; i++) { + if (value[offset] !== 0x21) + return false; + const key = value.subarray(offset + 1, offset + 34); + if (!isCompressedPubKey(key)) + return false; + try { + secp256k1_1.Point.fromHex((0, bytes_1.toHex)(key)); + } + catch (_a) { + return false; + } + const keyHex = (0, bytes_1.toHex)(key); + if (seen.has(keyHex)) + return false; + seen.add(keyHex); + offset += 34; + } + return offset === value.length - 1; +}; +exports.isCanonicalMpkhField = isCanonicalMpkhField; +const isSupportedIdentityField = (value) => value.length === 20 || (0, exports.isCanonicalMpkhField)(value); +exports.isSupportedIdentityField = isSupportedIdentityField; +const assertSupportedIdentityField = (value, name) => { + if (value.length === 20) + return; + if ((0, exports.isCanonicalMpkhField)(value)) + return; + throw new Error(`${name} must be either 20-byte PKH or canonical MPKH preimage`); +}; +exports.assertSupportedIdentityField = assertSupportedIdentityField; +const sameBytesOrShape = (expected, actual) => { + if (expected.OpCodeNum !== actual.OpCodeNum) + return false; + if (expected.Data !== undefined) + return (0, bytes_1.equal)(expected.Data, actual.Data); + return expected.DataLength === actual.Data.length; +}; +exports.sameBytesOrShape = sameBytesOrShape; +//# sourceMappingURL=identity-field.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/identity-field.js.map b/vendor/dxs-bsv-token-sdk/dist/script/identity-field.js.map new file mode 100644 index 0000000..42f160f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/identity-field.js.map @@ -0,0 +1 @@ +{"version":3,"file":"identity-field.js","sourceRoot":"","sources":["../../src/script/identity-field.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/index.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/index.d.ts new file mode 100644 index 0000000..29d69ae --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/index.d.ts @@ -0,0 +1,23 @@ +export * from "./build/null-data-builder"; +export * from "./build/p2pkh-builder"; +export * from "./build/p2mpkh-builder"; +export * from "./build/p2stas-builder"; +export * from "./build/asm-template-builder"; +export * from "./build/dstas-locking-builder"; +export * from "./build/script-builder"; +export * from "./read/script-reader"; +export * from "./read/script-read-token"; +export * from "./read/base-script-reader"; +export * from "./read/locking-script-reader"; +export * from "./read/script-reader-extensions"; +export * from "./read/dstas-locking-script-decomposer"; +export * from "./read/dstas-unlocking-script-decomposer"; +export * from "./script-samples"; +export * from "./script-token"; +export * from "./script-utils"; +export * from "./dstas-action-data"; +export * from "./dstas-swap-script"; +export * from "./dstas-requested-script-hash"; +export * from "./templates/dstas-locking-template"; +export * from "./eval/script-evaluator"; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/index.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/index.d.ts.map new file mode 100644 index 0000000..c456d0f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/script/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AAEvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,wCAAwC,CAAC;AACvD,cAAc,0CAA0C,CAAC;AAEzD,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,yBAAyB,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/index.js b/vendor/dxs-bsv-token-sdk/dist/script/index.js new file mode 100644 index 0000000..92c4d25 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/index.js @@ -0,0 +1,39 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./build/null-data-builder"), exports); +__exportStar(require("./build/p2pkh-builder"), exports); +__exportStar(require("./build/p2mpkh-builder"), exports); +__exportStar(require("./build/p2stas-builder"), exports); +__exportStar(require("./build/asm-template-builder"), exports); +__exportStar(require("./build/dstas-locking-builder"), exports); +__exportStar(require("./build/script-builder"), exports); +__exportStar(require("./read/script-reader"), exports); +__exportStar(require("./read/script-read-token"), exports); +__exportStar(require("./read/base-script-reader"), exports); +__exportStar(require("./read/locking-script-reader"), exports); +__exportStar(require("./read/script-reader-extensions"), exports); +__exportStar(require("./read/dstas-locking-script-decomposer"), exports); +__exportStar(require("./read/dstas-unlocking-script-decomposer"), exports); +__exportStar(require("./script-samples"), exports); +__exportStar(require("./script-token"), exports); +__exportStar(require("./script-utils"), exports); +__exportStar(require("./dstas-action-data"), exports); +__exportStar(require("./dstas-swap-script"), exports); +__exportStar(require("./dstas-requested-script-hash"), exports); +__exportStar(require("./templates/dstas-locking-template"), exports); +__exportStar(require("./eval/script-evaluator"), exports); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/index.js.map b/vendor/dxs-bsv-token-sdk/dist/script/index.js.map new file mode 100644 index 0000000..a15f6af --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/script/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4DAA0C;AAC1C,wDAAsC;AACtC,yDAAuC;AACvC,yDAAuC;AACvC,+DAA6C;AAC7C,gEAA8C;AAC9C,yDAAuC;AAEvC,uDAAqC;AACrC,2DAAyC;AACzC,4DAA0C;AAC1C,+DAA6C;AAC7C,kEAAgD;AAChD,yEAAuD;AACvD,2EAAyD;AAEzD,mDAAiC;AACjC,iDAA+B;AAC/B,iDAA+B;AAC/B,sDAAoC;AACpC,sDAAoC;AACpC,gEAA8C;AAC9C,qEAAmD;AACnD,0DAAwC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.d.ts new file mode 100644 index 0000000..67edd56 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.d.ts @@ -0,0 +1,19 @@ +import { Bytes } from "../../bytes"; +import { ScriptReadToken } from "./script-read-token"; +export declare abstract class BaseScriptReader { + protected Source: Bytes; + protected ExpectedLength: number; + protected ReadBytes: number; + constructor(source: Bytes, expectedLength?: number); + protected abstract handleToken(token: ScriptReadToken, tokenIdx: number, isLastToken: boolean): boolean; + protected readInternal(): number; + private handleTokenInternal; + private handleBytes; + private handleRest; + private readUInt8; + private readUInt16Le; + private readUInt32Le; + private readNBytes; + private varIntLength; +} +//# sourceMappingURL=base-script-reader.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.d.ts.map new file mode 100644 index 0000000..4883d3b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"base-script-reader.d.ts","sourceRoot":"","sources":["../../../src/script/read/base-script-reader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,8BAAsB,gBAAgB;IACpC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC;IACxB,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IACjC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAK;gBAEpB,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,EAAE,MAAM;IAKlD,SAAS,CAAC,QAAQ,CAAC,WAAW,CAC5B,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,OAAO,GACnB,OAAO;IAEV,SAAS,CAAC,YAAY,IAAI,MAAM;IAyEhC,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,WAAW;IAsCnB,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,YAAY;CAMrB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.js b/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.js new file mode 100644 index 0000000..17b5fe3 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.js @@ -0,0 +1,143 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BaseScriptReader = void 0; +const binary_1 = require("../../binary"); +const op_codes_1 = require("../../bitcoin/op-codes"); +const strict_mode_1 = require("../../security/strict-mode"); +const script_read_token_1 = require("./script-read-token"); +class BaseScriptReader { + constructor(source, expectedLength) { + this.ReadBytes = 0; + this.Source = source; + this.ExpectedLength = expectedLength !== null && expectedLength !== void 0 ? expectedLength : source.length; + } + readInternal() { + let tokenIdx = 0; + while (this.ReadBytes < this.ExpectedLength) { + const opCodeNum = this.readUInt8(); + this.ReadBytes++; + switch (opCodeNum) { + case op_codes_1.OpCode.OP_PUSHDATA1: { + if (this.ReadBytes === this.ExpectedLength) { + if (!this.handleRest(opCodeNum, tokenIdx)) + return -1; + break; + } + const count = this.readUInt8(); + this.ReadBytes++; + if (!this.handleBytes(opCodeNum, count, tokenIdx, count)) + return -1; + break; + } + case op_codes_1.OpCode.OP_PUSHDATA2: { + if (this.ReadBytes + 2 >= this.ExpectedLength) { + if (!this.handleRest(opCodeNum, tokenIdx)) + return -1; + break; + } + const count = this.readUInt16Le(); + this.ReadBytes += 2; + if (!this.handleBytes(opCodeNum, count, tokenIdx, count)) + return -1; + break; + } + case op_codes_1.OpCode.OP_PUSHDATA4: { + if (this.ReadBytes + 4 >= this.ExpectedLength) { + if (!this.handleRest(opCodeNum, tokenIdx)) + return -1; + break; + } + const count = this.readUInt32Le(); + this.ReadBytes += 4; + if (!this.handleBytes(opCodeNum, count, tokenIdx, count)) + return -1; + break; + } + default: { + if (opCodeNum > 0 && opCodeNum < op_codes_1.OpCode.OP_PUSHDATA1) { + const count = opCodeNum; + if (!this.handleBytes(opCodeNum, count, tokenIdx, count)) + return -1; + } + else { + if (!this.handleTokenInternal(new script_read_token_1.ScriptReadToken(opCodeNum), tokenIdx, this.ReadBytes === this.ExpectedLength)) { + return -1; + } + } + break; + } + } + tokenIdx++; + } + return tokenIdx; + } + handleTokenInternal(token, tokenIdx, isLastToken) { + return this.handleToken(token, tokenIdx, isLastToken); + } + handleBytes(opCodeNum, count, tokenIdx, varInt) { + if (count + this.ReadBytes > this.ExpectedLength) { + if ((0, strict_mode_1.getStrictModeConfig)().strictScriptReader) { + throw new Error("Malformed pushdata in script"); + } + const rest = this.ExpectedLength - this.ReadBytes; + const writer = binary_1.ByteWriter.fromSize(1 + this.varIntLength(varInt) + rest); + writer.writeUInt8(opCodeNum); + writer.writeVarInt(varInt); + if (rest > 0) + writer.writeChunk(this.readNBytes(rest)); + this.ReadBytes += rest; + return this.handleTokenInternal(new script_read_token_1.ScriptReadToken(opCodeNum, writer.buffer), tokenIdx, this.ReadBytes === this.ExpectedLength); + } + const bytes = this.readNBytes(count); + this.ReadBytes += count; + return this.handleTokenInternal(new script_read_token_1.ScriptReadToken(opCodeNum, bytes), tokenIdx, this.ReadBytes === this.ExpectedLength); + } + handleRest(opCodeNum, tokenIdx) { + if ((0, strict_mode_1.getStrictModeConfig)().strictScriptReader) { + throw new Error("Malformed pushdata in script"); + } + const count = this.ExpectedLength - this.ReadBytes; + const bytes = count > 0 ? this.readNBytes(count) : undefined; + this.ReadBytes = this.ExpectedLength; + return this.handleTokenInternal(new script_read_token_1.ScriptReadToken(opCodeNum, bytes), tokenIdx, true); + } + readUInt8() { + if (this.ReadBytes >= this.Source.length) { + throw new Error("Read more bytes than expected"); + } + return this.Source[this.ReadBytes]; + } + readUInt16Le() { + if (this.ReadBytes + 1 >= this.Source.length) { + throw new Error("Read more bytes than expected"); + } + return this.Source[this.ReadBytes] | (this.Source[this.ReadBytes + 1] << 8); + } + readUInt32Le() { + if (this.ReadBytes + 3 >= this.Source.length) { + throw new Error("Read more bytes than expected"); + } + return ((this.Source[this.ReadBytes] | + (this.Source[this.ReadBytes + 1] << 8) | + (this.Source[this.ReadBytes + 2] << 16) | + (this.Source[this.ReadBytes + 3] << 24)) >>> + 0); + } + readNBytes(count) { + if (count < 0 || this.ReadBytes + count > this.Source.length) { + throw new Error("Read more bytes than expected"); + } + return this.Source.subarray(this.ReadBytes, this.ReadBytes + count); + } + varIntLength(value) { + if (value < 0xfd) + return 1; + if (value <= 0xffff) + return 3; + if (value <= 0xffffffff) + return 5; + return 9; + } +} +exports.BaseScriptReader = BaseScriptReader; +//# sourceMappingURL=base-script-reader.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.js.map b/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.js.map new file mode 100644 index 0000000..243c91e --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/base-script-reader.js.map @@ -0,0 +1 @@ +{"version":3,"file":"base-script-reader.js","sourceRoot":"","sources":["../../../src/script/read/base-script-reader.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.d.ts new file mode 100644 index 0000000..8f8212e --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.d.ts @@ -0,0 +1,24 @@ +import { Bytes } from "../../bytes"; +export type DstasActionDataField = { + kind: "opcode"; + opcode: number; +} | { + kind: "data"; + hex: string; +}; +export type DstasLockingScriptDecomposition = { + ownerHex?: string; + ownerPkhHex?: string; + actionData?: DstasActionDataField; + baseMatched: boolean; + redemptionPkhHex?: string; + flagsHex?: string; + freezeEnabled?: boolean; + confiscationEnabled?: boolean; + serviceFieldHexes: string[]; + optionalDataHexes: string[]; + trailingOpcodes: number[]; + errors: string[]; +}; +export declare const decomposeDstasLockingScript: (script: Bytes) => DstasLockingScriptDecomposition; +//# sourceMappingURL=dstas-locking-script-decomposer.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.d.ts.map new file mode 100644 index 0000000..83cf493 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-locking-script-decomposer.d.ts","sourceRoot":"","sources":["../../../src/script/read/dstas-locking-script-decomposer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAgB,MAAM,aAAa,CAAC;AAWlD,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,MAAM,MAAM,+BAA+B,GAAG;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAsDF,eAAO,MAAM,2BAA2B,GACtC,QAAQ,KAAK,KACZ,+BA6FF,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.js b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.js new file mode 100644 index 0000000..70458e3 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.js @@ -0,0 +1,143 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.decomposeDstasLockingScript = void 0; +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_type_1 = require("../../bitcoin/script-type"); +const bytes_1 = require("../../bytes"); +const script_builder_1 = require("../build/script-builder"); +const dstas_locking_template_base_1 = require("../templates/dstas-locking-template-base"); +const DSTAS_TEMPLATE_BASE_SCRIPT = script_builder_1.ScriptBuilder.fromTokens((0, dstas_locking_template_base_1.buildDstasTemplateBaseTokens)(), script_type_1.ScriptType.unknown).toBytes(); +const readRawChunk = (script, offset) => { + if (offset >= script.length) + return undefined; + const opcode = script[offset]; + if (opcode > op_codes_1.OpCode.OP_0 && opcode < op_codes_1.OpCode.OP_PUSHDATA1) { + const size = opcode; + const start = offset + 1; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA1) { + if (offset + 2 > script.length) + return undefined; + const size = script[offset + 1]; + const start = offset + 2; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA2) { + if (offset + 3 > script.length) + return undefined; + const size = script[offset + 1] | (script[offset + 2] << 8); + const start = offset + 3; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA4) { + if (offset + 5 > script.length) + return undefined; + const size = (script[offset + 1] | + (script[offset + 2] << 8) | + (script[offset + 3] << 16) | + (script[offset + 4] << 24)) >>> + 0; + const start = offset + 5; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + return { opcode, start: offset, end: offset + 1 }; +}; +const decomposeDstasLockingScript = (script) => { + const result = { + baseMatched: false, + serviceFieldHexes: [], + optionalDataHexes: [], + trailingOpcodes: [], + errors: [], + }; + const owner = readRawChunk(script, 0); + if (!owner || !owner.data || owner.data.length === 0) { + result.errors.push("owner field pushdata was not found at script start"); + return result; + } + result.ownerHex = (0, bytes_1.toHex)(owner.data); + if (owner.data.length === 20) { + result.ownerPkhHex = result.ownerHex; + } + const second = readRawChunk(script, owner.end); + if (!second) { + result.errors.push("action data was not found"); + return result; + } + result.actionData = second.data + ? { kind: "data", hex: (0, bytes_1.toHex)(second.data) } + : { kind: "opcode", opcode: second.opcode }; + const baseStart = second.end; + const baseEnd = baseStart + DSTAS_TEMPLATE_BASE_SCRIPT.length; + if (baseEnd > script.length) { + result.errors.push("script is shorter than DSTAS template base"); + return result; + } + result.baseMatched = (0, bytes_1.equal)(script.subarray(baseStart, baseEnd), DSTAS_TEMPLATE_BASE_SCRIPT); + if (!result.baseMatched) { + result.errors.push("script middle does not match DSTAS template base"); + return result; + } + const redemption = readRawChunk(script, baseEnd); + if (!redemption || !redemption.data || redemption.data.length !== 20) { + result.errors.push("redemption PKH pushdata(20) was not found"); + return result; + } + result.redemptionPkhHex = (0, bytes_1.toHex)(redemption.data); + let cursor = redemption.end; + const flags = readRawChunk(script, cursor); + if (!flags) + return result; + if (flags.data) { + result.flagsHex = (0, bytes_1.toHex)(flags.data); + const rightmostByte = flags.data.length > 0 ? flags.data[flags.data.length - 1] : 0; + result.freezeEnabled = (rightmostByte & 0x01) === 0x01; + result.confiscationEnabled = (rightmostByte & 0x02) === 0x02; + } + else if (flags.opcode === op_codes_1.OpCode.OP_0) { + result.flagsHex = ""; + result.freezeEnabled = false; + result.confiscationEnabled = false; + } + else { + result.errors.push("flags field is not pushdata/OP_0"); + result.trailingOpcodes.push(flags.opcode); + } + cursor = flags.end; + const expectedServiceFieldsCount = (result.freezeEnabled ? 1 : 0) + (result.confiscationEnabled ? 1 : 0); + while (cursor < script.length) { + const chunk = readRawChunk(script, cursor); + if (!chunk) { + result.errors.push("failed to parse tail chunk"); + break; + } + if (chunk.data) { + if (result.serviceFieldHexes.length < expectedServiceFieldsCount) { + result.serviceFieldHexes.push((0, bytes_1.toHex)(chunk.data)); + } + else { + result.optionalDataHexes.push((0, bytes_1.toHex)(chunk.data)); + } + } + else { + result.trailingOpcodes.push(chunk.opcode); + } + cursor = chunk.end; + } + return result; +}; +exports.decomposeDstasLockingScript = decomposeDstasLockingScript; +//# sourceMappingURL=dstas-locking-script-decomposer.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.js.map b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.js.map new file mode 100644 index 0000000..fdf3418 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-locking-script-decomposer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-locking-script-decomposer.js","sourceRoot":"","sources":["../../../src/script/read/dstas-locking-script-decomposer.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.d.ts new file mode 100644 index 0000000..ac9d00c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.d.ts @@ -0,0 +1,22 @@ +import { Bytes } from "../../bytes"; +export type DstasUnlockingScriptDecomposition = { + parsed: boolean; + errors: string[]; + firstOutputSatoshis?: number; + firstOutputReceiverPkhHex?: string; + noteHexes: string[]; + hasExplicitEmptyNote: boolean; + authPlaceholderOpcodes: number[]; + fundingVout?: number; + fundingTxIdLeHex?: string; + mergeMode: "none" | "present" | "unknown"; + counterpartyPiecesCount?: number; + counterpartyPiecesHexes: string[]; + counterpartyScriptHex?: string; + preimageHex?: string; + spendingType?: number; + signatureHex?: string; + publicKeyHex?: string; +}; +export declare const decomposeDstasUnlockingScript: (script: Bytes) => DstasUnlockingScriptDecomposition; +//# sourceMappingURL=dstas-unlocking-script-decomposer.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.d.ts.map new file mode 100644 index 0000000..b1b5c8d --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-unlocking-script-decomposer.d.ts","sourceRoot":"","sources":["../../../src/script/read/dstas-unlocking-script-decomposer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAS,MAAM,aAAa,CAAC;AAgB3C,MAAM,MAAM,iCAAiC,GAAG;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAuGF,eAAO,MAAM,6BAA6B,GACxC,QAAQ,KAAK,KACZ,iCAoKF,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.js b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.js new file mode 100644 index 0000000..bf66f8b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.js @@ -0,0 +1,261 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.decomposeDstasUnlockingScript = void 0; +const op_codes_1 = require("../../bitcoin/op-codes"); +const bytes_1 = require("../../bytes"); +const readRawChunk = (script, offset) => { + if (offset >= script.length) + return undefined; + const opcode = script[offset]; + if (opcode > op_codes_1.OpCode.OP_0 && opcode < op_codes_1.OpCode.OP_PUSHDATA1) { + const size = opcode; + const start = offset + 1; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA1) { + if (offset + 2 > script.length) + return undefined; + const size = script[offset + 1]; + const start = offset + 2; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA2) { + if (offset + 3 > script.length) + return undefined; + const size = script[offset + 1] | (script[offset + 2] << 8); + const start = offset + 3; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + if (opcode === op_codes_1.OpCode.OP_PUSHDATA4) { + if (offset + 5 > script.length) + return undefined; + const size = (script[offset + 1] | + (script[offset + 2] << 8) | + (script[offset + 3] << 16) | + (script[offset + 4] << 24)) >>> + 0; + const start = offset + 5; + const end = start + size; + if (end > script.length) + return undefined; + return { opcode, start: offset, end, data: script.subarray(start, end) }; + } + return { opcode, start: offset, end: offset + 1 }; +}; +const parseScriptNum = (value) => { + if (value.length === 0) + return 0; + if (value.length > 4) + return undefined; + let result = 0; + for (let i = 0; i < value.length; i++) { + result |= value[i] << (8 * i); + } + const last = value[value.length - 1]; + const negative = (last & 0x80) !== 0; + if (negative) { + result &= ~(0x80 << (8 * (value.length - 1))); + result = -result; + } + return result; +}; +const parseNumberChunk = (chunk) => { + if (chunk.data) + return parseScriptNum(chunk.data); + if (chunk.opcode === op_codes_1.OpCode.OP_0) + return 0; + if (chunk.opcode === op_codes_1.OpCode.OP_1NEGATE) + return -1; + if (chunk.opcode >= op_codes_1.OpCode.OP_1 && chunk.opcode <= op_codes_1.OpCode.OP_16) { + return chunk.opcode - op_codes_1.OpCode.OP_1 + 1; + } + return undefined; +}; +const tryParseSwapSection = (chunks) => { + if (chunks.length < 3) + return undefined; + const scriptChunk = chunks[chunks.length - 1]; + if (!scriptChunk.data || scriptChunk.data.length === 0) + return undefined; + const piecesCountChunk = chunks[chunks.length - 2]; + const piecesCount = parseNumberChunk(piecesCountChunk); + if (piecesCount === undefined || piecesCount < 0) + return undefined; + const piecesStart = chunks.length - 2 - piecesCount; + if (piecesStart < 0) + return undefined; + const pieces = chunks.slice(piecesStart, chunks.length - 2); + if (pieces.length !== piecesCount) + return undefined; + if (pieces.some((piece) => !piece.data)) + return undefined; + return { + start: piecesStart, + counterpartyPiecesCount: piecesCount, + counterpartyPiecesHexes: pieces.map((piece) => (0, bytes_1.toHex)(piece.data)), + counterpartyScriptHex: (0, bytes_1.toHex)(scriptChunk.data), + }; +}; +const decomposeDstasUnlockingScript = (script) => { + var _a, _b, _c; + const result = { + parsed: false, + errors: [], + noteHexes: [], + hasExplicitEmptyNote: false, + authPlaceholderOpcodes: [], + mergeMode: "unknown", + counterpartyPiecesHexes: [], + }; + const chunks = []; + let cursor = 0; + while (cursor < script.length) { + const chunk = readRawChunk(script, cursor); + if (!chunk) { + result.errors.push("failed to decode chunk"); + return result; + } + chunks.push(chunk); + cursor = chunk.end; + } + if (chunks.length < 9) { + result.errors.push("too few chunks for DSTAS unlocking layout"); + return result; + } + const pubChunk = chunks[chunks.length - 1]; + const sigChunk = chunks[chunks.length - 2]; + const spendingTypeChunk = chunks[chunks.length - 3]; + const preimageChunk = chunks[chunks.length - 4]; + if (!pubChunk.data || pubChunk.data.length !== 33) { + result.errors.push("public key chunk not found at script end"); + } + else { + result.publicKeyHex = (0, bytes_1.toHex)(pubChunk.data); + } + if (!sigChunk.data || sigChunk.data.length < 9) { + result.errors.push("signature chunk not found"); + } + else { + result.signatureHex = (0, bytes_1.toHex)(sigChunk.data); + } + if (!preimageChunk.data || preimageChunk.data.length < 120) { + result.errors.push("preimage chunk not found"); + } + else { + result.preimageHex = (0, bytes_1.toHex)(preimageChunk.data); + } + const spendingType = parseNumberChunk(spendingTypeChunk); + if (spendingType === undefined) { + result.errors.push("spending type chunk is not a script number"); + } + else { + result.spendingType = spendingType; + } + const prefix = chunks.slice(0, chunks.length - 4); + const swapSection = tryParseSwapSection(prefix); + if (swapSection) { + if (result.spendingType !== undefined && result.spendingType !== 1) { + result.errors.push("swap section requires spending type 1"); + } + result.counterpartyPiecesCount = swapSection.counterpartyPiecesCount; + result.counterpartyPiecesHexes = swapSection.counterpartyPiecesHexes; + result.counterpartyScriptHex = swapSection.counterpartyScriptHex; + } + const working = swapSection ? prefix.slice(0, swapSection.start) : prefix; + if (working.length < 3) { + result.errors.push("missing funding fields"); + return result; + } + const fundingVoutChunk = working[working.length - 3]; + const fundingTxIdChunk = working[working.length - 2]; + const mergeMarkerChunk = working[working.length - 1]; + if (!fundingTxIdChunk.data || fundingTxIdChunk.data.length !== 32) { + result.errors.push("funding txid(LE) chunk not found"); + } + else { + result.fundingTxIdLeHex = (0, bytes_1.toHex)(fundingTxIdChunk.data); + } + const fundingVout = parseNumberChunk(fundingVoutChunk); + if (fundingVout === undefined) { + result.errors.push("funding vout chunk is not a script number"); + } + else { + result.fundingVout = fundingVout; + } + result.mergeMode = + mergeMarkerChunk.opcode === op_codes_1.OpCode.OP_0 && !mergeMarkerChunk.data + ? "none" + : "present"; + const head = working.slice(0, working.length - 3); + if (head.length < 3) { + result.errors.push("missing first token-output chunks"); + return result; + } + const satChunk = head[0]; + const pkhChunk = head[1]; + const sat = parseNumberChunk(satChunk); + if (sat === undefined) { + result.errors.push("first output satoshis is not a script number"); + } + else { + result.firstOutputSatoshis = sat; + } + if (!pkhChunk.data || pkhChunk.data.length !== 20) { + result.errors.push("first output receiver pkh(20) not found"); + } + else { + result.firstOutputReceiverPkhHex = (0, bytes_1.toHex)(pkhChunk.data); + } + let noteStartIdx = 3; + const tailHead = head.slice(3); + const auth1 = tailHead[0]; + const auth2 = tailHead[1]; + const auth3 = tailHead[2]; + result.authPlaceholderOpcodes = [ + (_a = auth1 === null || auth1 === void 0 ? void 0 : auth1.opcode) !== null && _a !== void 0 ? _a : -1, + (_b = auth2 === null || auth2 === void 0 ? void 0 : auth2.opcode) !== null && _b !== void 0 ? _b : -1, + (_c = auth3 === null || auth3 === void 0 ? void 0 : auth3.opcode) !== null && _c !== void 0 ? _c : -1, + ]; + const hasChangePair = !!auth1 && + !!auth2 && + parseNumberChunk(auth1) !== undefined && + !!auth2.data && + auth2.data.length === 20; + const hasNoChangePlaceholders = !!auth1 && + !!auth2 && + auth1.opcode === op_codes_1.OpCode.OP_0 && + !auth1.data && + auth2.opcode === op_codes_1.OpCode.OP_0 && + !auth2.data; + if (hasChangePair || hasNoChangePlaceholders) { + noteStartIdx = 5; + } + else if (tailHead.length > 0) { + result.errors.push("unexpected post-output layout before funding fields"); + } + for (let i = noteStartIdx; i < head.length; i++) { + const chunk = head[i]; + if (chunk.opcode === op_codes_1.OpCode.OP_0 && !chunk.data) { + result.hasExplicitEmptyNote = true; + } + else if (chunk.data) { + result.noteHexes.push((0, bytes_1.toHex)(chunk.data)); + } + else { + result.errors.push(`unexpected opcode in note area: ${chunk.opcode}`); + } + } + result.parsed = result.errors.length === 0; + return result; +}; +exports.decomposeDstasUnlockingScript = decomposeDstasUnlockingScript; +//# sourceMappingURL=dstas-unlocking-script-decomposer.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.js.map b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.js.map new file mode 100644 index 0000000..bf27512 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/dstas-unlocking-script-decomposer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-unlocking-script-decomposer.js","sourceRoot":"","sources":["../../../src/script/read/dstas-unlocking-script-decomposer.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.d.ts new file mode 100644 index 0000000..51c86af --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.d.ts @@ -0,0 +1,41 @@ +import { Address } from "../../bitcoin/address"; +import { ScriptType } from "../../bitcoin/script-type"; +import { Bytes } from "../../bytes"; +import { BaseScriptReader } from "./base-script-reader"; +import { ScriptReadToken } from "./script-read-token"; +import { ParsedActionData } from "../dstas-action-data"; +export declare class LockingScriptReader extends BaseScriptReader { + private samples; + private dstasBaseTokens; + private dstasCtx; + Address?: Address; + Data?: Bytes[]; + Dstas?: { + Owner: Bytes; + ActionDataRaw?: Bytes; + ActionDataOpCode?: number; + ActionDataParsed?: ParsedActionData; + Redemption: Bytes; + Flags: Bytes; + FreezeEnabled: boolean; + ConfiscationEnabled: boolean; + ServiceFields: Bytes[]; + OptionalData: Bytes[]; + }; + get ScriptType(): ScriptType; + private constructor(); + private read; + protected handleToken(token: ScriptReadToken, tokenIdx: number): boolean; + private sameToken; + private addData; + private handleDstasToken; + private finalizeDstas; + private isPushData; + getTokenId(): string | null; + getSymbol(): string | null; + getData(): Bytes; + static readHex(hex: string): LockingScriptReader; + static read(bytes: Bytes, expectedLength?: number): LockingScriptReader; + private ScriptTypeOverride?; +} +//# sourceMappingURL=locking-script-reader.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.d.ts.map new file mode 100644 index 0000000..8e33964 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"locking-script-reader.d.ts","sourceRoot":"","sources":["../../../src/script/read/locking-script-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,KAAK,EAA+B,MAAM,aAAa,CAAC;AASjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAoB,MAAM,sBAAsB,CAAC;AAgC1E,qBAAa,mBAAoB,SAAQ,gBAAgB;IACvD,OAAO,CAAC,OAAO,CAqBb;IAEF,OAAO,CAAC,eAAe,CAAkC;IAEzD,OAAO,CAAC,QAAQ,CASd;IAEF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;IACf,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,KAAK,CAAC;QACb,aAAa,CAAC,EAAE,KAAK,CAAC;QACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;QACpC,UAAU,EAAE,KAAK,CAAC;QAClB,KAAK,EAAE,KAAK,CAAC;QACb,aAAa,EAAE,OAAO,CAAC;QACvB,mBAAmB,EAAE,OAAO,CAAC;QAC7B,aAAa,EAAE,KAAK,EAAE,CAAC;QACvB,YAAY,EAAE,KAAK,EAAE,CAAC;KACvB,CAAC;IAEF,IAAI,UAAU,IAAI,UAAU,CAQ3B;IAED,OAAO;IAIP,OAAO,CAAC,IAAI;IAcZ,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAkCxE,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,gBAAgB;IAsFxB,OAAO,CAAC,aAAa;IAmDrB,OAAO,CAAC,UAAU;IAUlB,UAAU,IAAI,MAAM,GAAG,IAAI;IAM3B,SAAS,IAAI,MAAM,GAAG,IAAI;IAM1B,OAAO,IAAI,KAAK;IAMhB,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB;IAIhD,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,mBAAmB;IAMvE,OAAO,CAAC,kBAAkB,CAAC,CAAa;CACzC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.js b/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.js new file mode 100644 index 0000000..1f6ea5b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.js @@ -0,0 +1,278 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LockingScriptReader = void 0; +const address_1 = require("../../bitcoin/address"); +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_type_1 = require("../../bitcoin/script-type"); +const bytes_1 = require("../../bytes"); +const dstas_locking_template_base_1 = require("../templates/dstas-locking-template-base"); +const script_samples_1 = require("../script-samples"); +const base_script_reader_1 = require("./base-script-reader"); +const dstas_action_data_1 = require("../dstas-action-data"); +const identity_field_1 = require("../identity-field"); +class LockingScriptReader extends base_script_reader_1.BaseScriptReader { + get ScriptType() { + if (this.ScriptTypeOverride !== undefined) + return this.ScriptTypeOverride; + for (const sample of this.samples) { + if (sample.ctx.Result) + return sample.type; + } + return script_type_1.ScriptType.unknown; + } + constructor(bytes, expectedLength) { + super(bytes, expectedLength); + this.samples = [ + { + type: script_type_1.ScriptType.p2pkh, + tokens: script_samples_1.p2phkTokens, + ctx: { Result: true, OpReturnReached: false }, + }, + { + type: script_type_1.ScriptType.p2mpkh, + tokens: script_samples_1.p2mpkhTokens, + ctx: { Result: true, OpReturnReached: false }, + }, + { + type: script_type_1.ScriptType.p2stas, + tokens: (0, script_samples_1.getP2stasTokens)(), + ctx: { Result: true, OpReturnReached: false }, + }, + { + type: script_type_1.ScriptType.nullData, + tokens: script_samples_1.nullDataTokens, + ctx: { Result: true, OpReturnReached: false }, + }, + ]; + this.dstasBaseTokens = (0, dstas_locking_template_base_1.buildDstasTemplateBaseTokens)(); + this.dstasCtx = { + Result: true, + Stage: "owner", + BaseIdx: 0, + FreezeEnabled: false, + ConfiscationEnabled: false, + ExpectedServiceFieldsCount: 0, + ServiceFields: [], + OptionalData: [], + }; + } + read() { + const count = this.readInternal(); + if (count === -1) + return; + for (const sample of this.samples) { + if (!sample.ctx.Result) + continue; + sample.ctx.Result = + sample.ctx.OpReturnReached || sample.tokens.length === count; + } + this.finalizeDstas(); + } + handleToken(token, tokenIdx) { + let activeDetectors = 0; + for (const sample of this.samples) { + if (!sample.ctx.Result) + continue; + activeDetectors++; + if (!sample.ctx.OpReturnReached) { + if (sample.tokens.length === tokenIdx) { + if (token.OpCode === op_codes_1.OpCode.OP_RETURN) { + sample.ctx.OpReturnReached = true; + } + } + else { + const expected = sample.tokens[tokenIdx]; + const nextResult = expected ? this.sameToken(expected, token) : false; + sample.ctx.Result = nextResult; + if (nextResult) { + if (expected.IsReceiverId && token.Data.length > 0) { + this.Address = new address_1.Address(token.Data); + } + } + } + } + else { + this.addData(token.Data); + } + } + this.handleDstasToken(token); + if (this.dstasCtx.Result) + activeDetectors++; + return activeDetectors > 0; + } + sameToken(expected, actual) { + return (0, identity_field_1.sameBytesOrShape)(expected, actual); + } + addData(data) { + if (!this.Data) + this.Data = []; + this.Data.push(data); + } + handleDstasToken(token) { + if (!this.dstasCtx.Result) + return; + switch (this.dstasCtx.Stage) { + case "owner": { + if (!this.isPushData(token) || !(0, identity_field_1.isSupportedIdentityField)(token.Data)) { + this.dstasCtx.Result = false; + return; + } + this.dstasCtx.Owner = token.Data; + this.dstasCtx.Stage = "second"; + return; + } + case "second": { + if (this.isPushData(token)) { + this.dstasCtx.ActionDataRaw = token.Data; + } + else { + this.dstasCtx.ActionDataOpCode = token.OpCodeNum; + } + this.dstasCtx.Stage = "base"; + return; + } + case "base": { + const expected = this.dstasBaseTokens[this.dstasCtx.BaseIdx]; + if (!expected || !this.sameToken(expected, token)) { + this.dstasCtx.Result = false; + return; + } + this.dstasCtx.BaseIdx++; + if (this.dstasCtx.BaseIdx === this.dstasBaseTokens.length) { + this.dstasCtx.Stage = "redemption"; + } + return; + } + case "redemption": { + if (!this.isPushData(token) || token.Data.length !== 20) { + this.dstasCtx.Result = false; + return; + } + this.dstasCtx.Redemption = token.Data; + this.dstasCtx.Stage = "flags"; + return; + } + case "flags": { + if (!this.isPushData(token)) { + this.dstasCtx.Result = false; + return; + } + this.dstasCtx.Flags = token.Data; + const rightmostByte = token.Data.length > 0 ? token.Data[token.Data.length - 1] : 0; + this.dstasCtx.FreezeEnabled = (rightmostByte & 0x01) === 0x01; + this.dstasCtx.ConfiscationEnabled = (rightmostByte & 0x02) === 0x02; + this.dstasCtx.ExpectedServiceFieldsCount = + (this.dstasCtx.FreezeEnabled ? 1 : 0) + + (this.dstasCtx.ConfiscationEnabled ? 1 : 0); + this.dstasCtx.Stage = "tail"; + return; + } + case "tail": { + if (!this.isPushData(token)) { + this.dstasCtx.Result = false; + return; + } + if (this.dstasCtx.ServiceFields.length < + this.dstasCtx.ExpectedServiceFieldsCount) { + if (!(0, identity_field_1.isSupportedIdentityField)(token.Data)) { + this.dstasCtx.Result = false; + return; + } + this.dstasCtx.ServiceFields.push(token.Data); + } + else { + this.dstasCtx.OptionalData.push(token.Data); + } + return; + } + } + } + finalizeDstas() { + if (!this.dstasCtx.Result) + return; + if (this.dstasCtx.Stage === "owner") + return; + if (this.dstasCtx.Stage === "second") + return; + if (this.dstasCtx.Stage === "base") + return; + if (this.dstasCtx.Stage === "redemption") + return; + if (this.dstasCtx.Stage === "flags") + return; + if (!this.dstasCtx.Owner || + !this.dstasCtx.Redemption || + !this.dstasCtx.Flags) + return; + if (this.dstasCtx.ServiceFields.length < + this.dstasCtx.ExpectedServiceFieldsCount) + return; + let actionDataParsed; + if (this.dstasCtx.ActionDataRaw) { + try { + actionDataParsed = (0, dstas_action_data_1.decodeActionData)(this.dstasCtx.ActionDataRaw); + } + catch (_a) { + this.dstasCtx.Result = false; + return; + } + } + this.ScriptTypeOverride = script_type_1.ScriptType.dstas; + if (this.dstasCtx.Owner.length === 20) { + this.Address = new address_1.Address(this.dstasCtx.Owner); + } + this.Dstas = { + Owner: this.dstasCtx.Owner, + ActionDataRaw: this.dstasCtx.ActionDataRaw, + ActionDataOpCode: this.dstasCtx.ActionDataOpCode, + ActionDataParsed: actionDataParsed, + Redemption: this.dstasCtx.Redemption, + Flags: this.dstasCtx.Flags, + FreezeEnabled: this.dstasCtx.FreezeEnabled, + ConfiscationEnabled: this.dstasCtx.ConfiscationEnabled, + ServiceFields: this.dstasCtx.ServiceFields, + OptionalData: this.dstasCtx.OptionalData, + }; + if (this.dstasCtx.Owner.length === 20) { + this.Address = new address_1.Address(this.dstasCtx.Owner); + } + } + isPushData(token) { + return (token.OpCodeNum > 0 && + (token.OpCodeNum < op_codes_1.OpCode.OP_PUSHDATA1 || + token.OpCodeNum === op_codes_1.OpCode.OP_PUSHDATA1 || + token.OpCodeNum === op_codes_1.OpCode.OP_PUSHDATA2 || + token.OpCodeNum === op_codes_1.OpCode.OP_PUSHDATA4)); + } + getTokenId() { + if (this.ScriptType !== script_type_1.ScriptType.p2stas) + return null; + if (!this.Data || this.Data.length === 0) + return null; + return (0, bytes_1.toHex)(this.Data[0]); + } + getSymbol() { + if (this.ScriptType !== script_type_1.ScriptType.p2stas) + return null; + if (!this.Data || this.Data.length < 2) + return null; + return (0, bytes_1.bytesToUtf8)(this.Data[1]); + } + getData() { + if (this.ScriptType !== script_type_1.ScriptType.p2stas) + return new Uint8Array(0); + if (!this.Data || this.Data.length <= 2) + return new Uint8Array(0); + return this.Data[2]; + } + static readHex(hex) { + return LockingScriptReader.read((0, bytes_1.fromHex)(hex)); + } + static read(bytes, expectedLength) { + const reader = new LockingScriptReader(bytes, expectedLength); + reader.read(); + return reader; + } +} +exports.LockingScriptReader = LockingScriptReader; +//# sourceMappingURL=locking-script-reader.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.js.map b/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.js.map new file mode 100644 index 0000000..17599ae --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/locking-script-reader.js.map @@ -0,0 +1 @@ +{"version":3,"file":"locking-script-reader.js","sourceRoot":"","sources":["../../../src/script/read/locking-script-reader.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.d.ts new file mode 100644 index 0000000..679b931 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.d.ts @@ -0,0 +1,9 @@ +import { OpCode } from "../../bitcoin/op-codes"; +import { Bytes } from "../../bytes"; +export declare class ScriptReadToken { + OpCodeNum: number; + Data: Bytes; + OpCode?: OpCode; + constructor(opCodeNum: number, data?: Bytes); +} +//# sourceMappingURL=script-read-token.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.d.ts.map new file mode 100644 index 0000000..a30ab52 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script-read-token.d.ts","sourceRoot":"","sources":["../../../src/script/read/script-read-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,qBAAa,eAAe;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,KAAK,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEJ,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK;CAO5C"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.js b/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.js new file mode 100644 index 0000000..d062b91 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ScriptReadToken = void 0; +const script_utils_1 = require("../script-utils"); +class ScriptReadToken { + constructor(opCodeNum, data) { + this.OpCodeNum = opCodeNum; + this.Data = data !== null && data !== void 0 ? data : new Uint8Array(0); + const { valid } = (0, script_utils_1.isOpCode)(opCodeNum); + if (valid) + this.OpCode = opCodeNum; + } +} +exports.ScriptReadToken = ScriptReadToken; +//# sourceMappingURL=script-read-token.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.js.map b/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.js.map new file mode 100644 index 0000000..07cdbe9 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-read-token.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script-read-token.js","sourceRoot":"","sources":["../../../src/script/read/script-read-token.ts"],"names":[],"mappings":";;;AAEA,kDAA2C;AAE3C,MAAa,eAAe;IAK1B,YAAY,SAAiB,EAAE,IAAY;QACzC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;QAEtC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAA,uBAAQ,EAAC,SAAS,CAAC,CAAC;QACtC,IAAI,KAAK;YAAE,IAAI,CAAC,MAAM,GAAG,SAAmB,CAAC;IAC/C,CAAC;CACF;AAZD,0CAYC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.d.ts new file mode 100644 index 0000000..9648d66 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.d.ts @@ -0,0 +1,7 @@ +import { Bytes } from "../../bytes"; +import { LockingScriptReader } from "./locking-script-reader"; +export declare const getTokenId: (reader: LockingScriptReader) => string | null; +export declare const getSymbol: (reader: LockingScriptReader) => string | null; +export declare const getData: (reader: LockingScriptReader) => Bytes; +export declare const isSplittable: (reader: LockingScriptReader) => boolean; +//# sourceMappingURL=script-reader-extensions.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.d.ts.map new file mode 100644 index 0000000..dfe8c42 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script-reader-extensions.d.ts","sourceRoot":"","sources":["../../../src/script/read/script-reader-extensions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,eAAO,MAAM,UAAU,GAAI,QAAQ,mBAAmB,KAAG,MAAM,GAAG,IAC7C,CAAC;AAEtB,eAAO,MAAM,SAAS,GAAI,QAAQ,mBAAmB,KAAG,MAAM,GAAG,IAC7C,CAAC;AAErB,eAAO,MAAM,OAAO,GAAI,QAAQ,mBAAmB,KAAG,KAAyB,CAAC;AAEhF,eAAO,MAAM,YAAY,GAAI,QAAQ,mBAAmB,KAAG,OAQ1D,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.js b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.js new file mode 100644 index 0000000..41e3fff --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isSplittable = exports.getData = exports.getSymbol = exports.getTokenId = void 0; +const script_type_1 = require("../../bitcoin/script-type"); +const getTokenId = (reader) => reader.getTokenId(); +exports.getTokenId = getTokenId; +const getSymbol = (reader) => reader.getSymbol(); +exports.getSymbol = getSymbol; +const getData = (reader) => reader.getData(); +exports.getData = getData; +const isSplittable = (reader) => { + if (reader.ScriptType !== script_type_1.ScriptType.p2stas) + return true; + if (!reader.Data || reader.Data.length < 2) + return true; + const marker = reader.Data[1]; + if (!marker || marker.length !== 1) + return true; + return marker[0] === 0x0; +}; +exports.isSplittable = isSplittable; +//# sourceMappingURL=script-reader-extensions.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.js.map b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.js.map new file mode 100644 index 0000000..e4196c1 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader-extensions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script-reader-extensions.js","sourceRoot":"","sources":["../../../src/script/read/script-reader-extensions.ts"],"names":[],"mappings":";;;AACA,2DAAuD;AAGhD,MAAM,UAAU,GAAG,CAAC,MAA2B,EAAiB,EAAE,CACvE,MAAM,CAAC,UAAU,EAAE,CAAC;AADT,QAAA,UAAU,cACD;AAEf,MAAM,SAAS,GAAG,CAAC,MAA2B,EAAiB,EAAE,CACtE,MAAM,CAAC,SAAS,EAAE,CAAC;AADR,QAAA,SAAS,aACD;AAEd,MAAM,OAAO,GAAG,CAAC,MAA2B,EAAS,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;AAAnE,QAAA,OAAO,WAA4D;AAEzE,MAAM,YAAY,GAAG,CAAC,MAA2B,EAAW,EAAE;IACnE,IAAI,MAAM,CAAC,UAAU,KAAK,wBAAU,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAExD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEhD,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;AAC3B,CAAC,CAAC;AARW,QAAA,YAAY,gBAQvB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.d.ts new file mode 100644 index 0000000..230ecb7 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.d.ts @@ -0,0 +1,11 @@ +import { Bytes } from "../../bytes"; +import { ScriptToken } from "../script-token"; +export declare class ScriptReader { + static read: (source: Bytes) => ScriptToken[]; + static decode: (buffer: Bytes, offset: number) => { + opcode: number; + number: number; + size: number; + } | null; +} +//# sourceMappingURL=script-reader.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.d.ts.map new file mode 100644 index 0000000..02232b1 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script-reader.d.ts","sourceRoot":"","sources":["../../../src/script/read/script-reader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,qBAAa,YAAY;IACvB,MAAM,CAAC,IAAI,GAAI,QAAQ,KAAK,mBAkD1B;IAEF,MAAM,CAAC,MAAM,GAAI,QAAQ,KAAK,EAAE,QAAQ,MAAM;;;;aAmC5C;CACH"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.js b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.js new file mode 100644 index 0000000..1908370 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.js @@ -0,0 +1,87 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ScriptReader = void 0; +const buffer_utils_1 = require("../../buffer/buffer-utils"); +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_token_1 = require("../script-token"); +const strict_mode_1 = require("../../security/strict-mode"); +class ScriptReader { +} +exports.ScriptReader = ScriptReader; +ScriptReader.read = (source) => { + const result = []; + let i = 0; + while (i < source.length) { + const byte = source[i]; + if (byte > op_codes_1.OpCode.OP_0 && byte <= op_codes_1.OpCode.OP_PUSHDATA4) { + const d = ScriptReader.decode(source, i); + if (d === null) { + if ((0, strict_mode_1.getStrictModeConfig)().strictScriptReader) { + throw new Error(`Malformed pushdata at offset ${i}`); + } + return []; + } + i += d.size; + if (i + d.number > source.length) { + if ((0, strict_mode_1.getStrictModeConfig)().strictScriptReader) { + throw new Error(`Pushdata exceeds script length at offset ${i}`); + } + return []; + } + const data = (0, buffer_utils_1.slice)(source, i, i + d.number); + i += d.number; + const op = (0, buffer_utils_1.asMinimalOP)(data); + if (op !== undefined) { + result.push(new script_token_1.ScriptToken(op, op)); + } + else { + result.push(script_token_1.ScriptToken.fromBytes(data)); + } + } + else { + result.push(new script_token_1.ScriptToken(byte, byte)); + i += 1; + } + } + return result; +}; +ScriptReader.decode = (buffer, offset) => { + const opcode = buffer[offset]; + let num; + let size; + if (opcode < op_codes_1.OpCode.OP_PUSHDATA1) { + num = opcode; + size = 1; + } + else if (opcode === op_codes_1.OpCode.OP_PUSHDATA1) { + if (offset + 2 > buffer.length) + return null; + num = buffer[offset + 1]; + size = 2; + } + else if (opcode === op_codes_1.OpCode.OP_PUSHDATA2) { + if (offset + 3 > buffer.length) + return null; + num = buffer[offset + 1] | (buffer[offset + 2] << 8); + size = 3; + } + else { + if (offset + 5 > buffer.length) + return null; + if (opcode !== op_codes_1.OpCode.OP_PUSHDATA4) + throw new Error("Unexpected opcode"); + num = + (buffer[offset + 1] | + (buffer[offset + 2] << 8) | + (buffer[offset + 3] << 16) | + (buffer[offset + 4] << 24)) >>> + 0; + size = 5; + } + return { + opcode, + number: num, + size, + }; +}; +//# sourceMappingURL=script-reader.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.js.map b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.js.map new file mode 100644 index 0000000..cb2a56e --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/read/script-reader.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script-reader.js","sourceRoot":"","sources":["../../../src/script/read/script-reader.ts"],"names":[],"mappings":";;;AAAA,4DAA+D;AAC/D,qDAAgD;AAEhD,kDAA8C;AAC9C,4DAAiE;AAEjE,MAAa,YAAY;;AAAzB,oCAyFC;AAxFQ,iBAAI,GAAG,CAAC,MAAa,EAAE,EAAE;IAC9B,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAGvB,IAAI,IAAI,GAAG,iBAAM,CAAC,IAAI,IAAI,IAAI,IAAI,iBAAM,CAAC,YAAY,EAAE,CAAC;YACtD,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAGzC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACf,IAAI,IAAA,iCAAmB,GAAE,CAAC,kBAAkB,EAAE,CAAC;oBAC7C,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,EAAE,CAAC,CAAC;gBACvD,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;YAGZ,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;gBACjC,IAAI,IAAA,iCAAmB,GAAE,CAAC,kBAAkB,EAAE,CAAC;oBAC7C,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,EAAE,CAAC,CAAC;gBACnE,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,MAAM,IAAI,GAAG,IAAA,oBAAK,EAAC,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;YAC5C,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YAGd,MAAM,EAAE,GAAG,IAAA,0BAAW,EAAC,IAAI,CAAC,CAAC;YAE7B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;gBACrB,MAAM,CAAC,IAAI,CAAC,IAAI,0BAAW,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,0BAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3C,CAAC;QAEH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,IAAI,0BAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YAEzC,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEK,mBAAM,GAAG,CAAC,MAAa,EAAE,MAAc,EAAE,EAAE;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,IAAI,GAAG,CAAC;IACR,IAAI,IAAI,CAAC;IAET,IAAI,MAAM,GAAG,iBAAM,CAAC,YAAY,EAAE,CAAC;QACjC,GAAG,GAAG,MAAM,CAAC;QACb,IAAI,GAAG,CAAC,CAAC;IAEX,CAAC;SAAM,IAAI,MAAM,KAAK,iBAAM,CAAC,YAAY,EAAE,CAAC;QAC1C,IAAI,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC5C,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,GAAG,CAAC,CAAC;IAEX,CAAC;SAAM,IAAI,MAAM,KAAK,iBAAM,CAAC,YAAY,EAAE,CAAC;QAC1C,IAAI,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC5C,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACrD,IAAI,GAAG,CAAC,CAAC;IAEX,CAAC;SAAM,CAAC;QACN,IAAI,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC5C,IAAI,MAAM,KAAK,iBAAM,CAAC,YAAY;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACzE,GAAG;YACD,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;gBACjB,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC1B,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC7B,CAAC,CAAC;QACJ,IAAI,GAAG,CAAC,CAAC;IACX,CAAC;IACD,OAAO;QACL,MAAM;QACN,MAAM,EAAE,GAAG;QACX,IAAI;KACL,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-samples.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/script-samples.d.ts new file mode 100644 index 0000000..af12274 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-samples.d.ts @@ -0,0 +1,8 @@ +import { ScriptToken } from "./script-token"; +export declare const nullDataTokens: ScriptToken[]; +export declare const p2phkTokens: ScriptToken[]; +export declare const p2mpkhTokens: ScriptToken[]; +export declare const p2stasSampleHex = "76a914001122334455667788990011223344556677889988ac6976aa607f5f7f7c5e7f7c5d7f7c5c7f7c5b7f7c5a7f7c597f7c587f7c577f7c567f7c557f7c547f7c537f7c527f7c517f7c7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7c5f7f7c5e7f7c5d7f7c5c7f7c5b7f7c5a7f7c597f7c587f7c577f7c567f7c557f7c547f7c537f7c527f7c517f7c7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e011f7f7d7e01007e8111414136d08c5ed2bf3ba048afe6dcaebafe01005f80837e01007e7652967b537a7601ff877c0100879b7d648b6752799368537a7d9776547aa06394677768263044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802207c607f5f7f7c5e7f7c5d7f7c5c7f7c5b7f7c5a7f7c597f7c587f7c577f7c567f7c557f7c547f7c537f7c527f7c517f7c7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7c5f7f7c5e7f7c5d7f7c5c7f7c5b7f7c5a7f7c597f7c587f7c577f7c567f7c557f7c547f7c537f7c527f7c517f7c7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e01417e7c6421038ff83d8cf12121491609c4939dc11c4aa35503508fe432dc5a5c1905608b92186721023635954789a02e39fb7e54440b6f528d53efd65635ddad7f3c4085f97fdbdc4868ad547f7701207f01207f7701247f517f7801007e02fd00a063546752687f7801007e817f727e7b537f7701147f76020c057f7701147f757b876b7b557a766471567a577a786354807e7e676d68aa880067765158a569765187645294567a5379587a7e7e78637c8c7c53797e577a7e6878637c8c7c53797e577a7e6878637c8c7c53797e577a7e6878637c8c7c53797e577a7e6878637c8c7c53797e577a7e6867567a6876aa587a7d54807e577a597a5a7a786354807e6f7e7eaa727c7e676d6e7eaa7c687b7eaa587a7d877663516752687c72879b69537a6491687c7b547f77517f7853a0916901247f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e816854937f77788c6301247f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e816854937f777852946301247f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e816854937f77686877517f7c52797d8b9f7c53a09b91697c76638c7c587f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e81687f777c6876638c7c587f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e81687f777c6863587f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e81687f7768587f517f7801007e817602fc00a06302fd00a063546752687f7801007e81727e7b7b687f75537f7c0376a9148801147f775379645579887567726881687863547a677b68587f7c815379635379528763547a6b547a6b7b6b67567a6b567a6b6b7c68677b93687c547f7701207f75748c7a7669765880041976a9147858790376a9147e7e748c7a7d7e5879727e0288ac727e547a00587a64745da0637c748c7a76697d937b7b58807e59790376a9147e748c7a7e59797e7e68676c766976748c7a9d58807e6c0376a9147e748c7a7e6c7e7e68745da0637c748c7a76697d937b7b58807e59790376a9147e748c7a7e59797e7e68745da0637c748c7a76697d937b7b58807e59790376a9147e748c7a7e59797e7e687c577a9d7d7e5979635a795880041976a9145b797e0288ac7e7e6700687d7e597a766302006a7c7e827602fc00a06301fd7c7e536751687f757c7e0058807c7e687d7eaa6b7e7e7e7e7eaa78877c6c877c6c9a9b726d7777"; +export declare const getP2stasTokens: () => ScriptToken[]; +export declare const getDstasTokens: () => ScriptToken[]; +//# sourceMappingURL=script-samples.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-samples.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/script-samples.d.ts.map new file mode 100644 index 0000000..41b1b41 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-samples.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script-samples.d.ts","sourceRoot":"","sources":["../../src/script/script-samples.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,eAAO,MAAM,cAAc,eAAuC,CAAC;AAEnE,eAAO,MAAM,WAAW,eAMvB,CAAC;AAEF,eAAO,MAAM,YAAY,eAkDxB,CAAC;AAEF,eAAO,MAAM,eAAe,ukFAC0iF,CAAC;AAKvkF,eAAO,MAAM,eAAe,qBAO3B,CAAC;AAEF,eAAO,MAAM,cAAc,qBAmD1B,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-samples.js b/vendor/dxs-bsv-token-sdk/dist/script/script-samples.js new file mode 100644 index 0000000..0e1bb8a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-samples.js @@ -0,0 +1,127 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getDstasTokens = exports.getP2stasTokens = exports.p2stasSampleHex = exports.p2mpkhTokens = exports.p2phkTokens = exports.nullDataTokens = void 0; +const op_codes_1 = require("../bitcoin/op-codes"); +const bytes_1 = require("../bytes"); +const script_reader_1 = require("./read/script-reader"); +const script_token_1 = require("./script-token"); +const dstas_locking_builder_1 = require("./build/dstas-locking-builder"); +exports.nullDataTokens = [script_token_1.ScriptToken.forSample(op_codes_1.OpCode.OP_0)]; +exports.p2phkTokens = [ + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_DUP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_HASH160), + script_token_1.ScriptToken.forSample(20, 20, true), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_EQUALVERIFY), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_CHECKSIG), +]; +exports.p2mpkhTokens = [ + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_DUP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_HASH160), + script_token_1.ScriptToken.forSample(20, 20, true), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_EQUALVERIFY), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SIZE), + script_token_1.ScriptToken.fromBytes(new Uint8Array([0x21])), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_EQUAL), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_CHECKSIG), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_ELSE), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_1), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_1), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IFDUP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SWAP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_ENDIF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_1), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IFDUP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SWAP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_ENDIF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_1), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IFDUP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SWAP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_ENDIF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_1), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IFDUP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SWAP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_ENDIF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_1), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IFDUP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_IF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SWAP), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_SPLIT), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_ENDIF), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_CHECKMULTISIG), + new script_token_1.ScriptToken(op_codes_1.OpCode.OP_ENDIF), +]; +exports.p2stasSampleHex = "76a914001122334455667788990011223344556677889988ac6976aa607f5f7f7c5e7f7c5d7f7c5c7f7c5b7f7c5a7f7c597f7c587f7c577f7c567f7c557f7c547f7c537f7c527f7c517f7c7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7c5f7f7c5e7f7c5d7f7c5c7f7c5b7f7c5a7f7c597f7c587f7c577f7c567f7c557f7c547f7c537f7c527f7c517f7c7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e011f7f7d7e01007e8111414136d08c5ed2bf3ba048afe6dcaebafe01005f80837e01007e7652967b537a7601ff877c0100879b7d648b6752799368537a7d9776547aa06394677768263044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802207c607f5f7f7c5e7f7c5d7f7c5c7f7c5b7f7c5a7f7c597f7c587f7c577f7c567f7c557f7c547f7c537f7c527f7c517f7c7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7c5f7f7c5e7f7c5d7f7c5c7f7c5b7f7c5a7f7c597f7c587f7c577f7c567f7c557f7c547f7c537f7c527f7c517f7c7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e01417e7c6421038ff83d8cf12121491609c4939dc11c4aa35503508fe432dc5a5c1905608b92186721023635954789a02e39fb7e54440b6f528d53efd65635ddad7f3c4085f97fdbdc4868ad547f7701207f01207f7701247f517f7801007e02fd00a063546752687f7801007e817f727e7b537f7701147f76020c057f7701147f757b876b7b557a766471567a577a786354807e7e676d68aa880067765158a569765187645294567a5379587a7e7e78637c8c7c53797e577a7e6878637c8c7c53797e577a7e6878637c8c7c53797e577a7e6878637c8c7c53797e577a7e6878637c8c7c53797e577a7e6867567a6876aa587a7d54807e577a597a5a7a786354807e6f7e7eaa727c7e676d6e7eaa7c687b7eaa587a7d877663516752687c72879b69537a6491687c7b547f77517f7853a0916901247f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e816854937f77788c6301247f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e816854937f777852946301247f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e816854937f77686877517f7c52797d8b9f7c53a09b91697c76638c7c587f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e81687f777c6876638c7c587f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e81687f777c6863587f77517f7c01007e817602fc00a06302fd00a063546752687f7c01007e81687f7768587f517f7801007e817602fc00a06302fd00a063546752687f7801007e81727e7b7b687f75537f7c0376a9148801147f775379645579887567726881687863547a677b68587f7c815379635379528763547a6b547a6b7b6b67567a6b567a6b6b7c68677b93687c547f7701207f75748c7a7669765880041976a9147858790376a9147e7e748c7a7d7e5879727e0288ac727e547a00587a64745da0637c748c7a76697d937b7b58807e59790376a9147e748c7a7e59797e7e68676c766976748c7a9d58807e6c0376a9147e748c7a7e6c7e7e68745da0637c748c7a76697d937b7b58807e59790376a9147e748c7a7e59797e7e68745da0637c748c7a76697d937b7b58807e59790376a9147e748c7a7e59797e7e687c577a9d7d7e5979635a795880041976a9145b797e0288ac7e7e6700687d7e597a766302006a7c7e827602fc00a06301fd7c7e536751687f757c7e0058807c7e687d7eaa6b7e7e7e7e7eaa78877c6c877c6c9a9b726d7777"; +let stasTokens = null; +let dstasTokens = null; +const getP2stasTokens = () => { + if (stasTokens === null) { + stasTokens = script_reader_1.ScriptReader.read((0, bytes_1.fromHex)(exports.p2stasSampleHex)); + stasTokens[2] = script_token_1.ScriptToken.forSample(20, 20, true); + } + return stasTokens; +}; +exports.getP2stasTokens = getP2stasTokens; +const getDstasTokens = () => { + if (dstasTokens === null) { + const ownerHex = "1111111111111111111111111111111111111111"; + const redemptionHex = "2222222222222222222222222222222222222222"; + const flagsHex = "00"; + const script = (0, dstas_locking_builder_1.buildDstasLockingScript)({ + ownerPkh: (0, bytes_1.fromHex)(ownerHex), + actionData: null, + redemptionPkh: (0, bytes_1.fromHex)(redemptionHex), + flags: (0, bytes_1.fromHex)(flagsHex), + serviceFields: [], + optionalData: [], + }); + dstasTokens = script_reader_1.ScriptReader.read(script); + if (dstasTokens.length >= 2) { + dstasTokens[0].IsReceiverId = true; + dstasTokens[1].IsActionData = true; + } + const redemptionBytes = (0, bytes_1.fromHex)(redemptionHex); + const flagsBytes = (0, bytes_1.fromHex)(flagsHex); + for (const token of dstasTokens) { + if (token.Data && token.Data.length === redemptionBytes.length) { + let match = true; + for (let i = 0; i < redemptionBytes.length; i++) { + if (token.Data[i] !== redemptionBytes[i]) { + match = false; + break; + } + } + if (match) + token.IsRedemptionId = true; + } + if (token.Data && token.Data.length === flagsBytes.length) { + let match = true; + for (let i = 0; i < flagsBytes.length; i++) { + if (token.Data[i] !== flagsBytes[i]) { + match = false; + break; + } + } + if (match) + token.IsFlagsField = true; + } + } + } + return dstasTokens; +}; +exports.getDstasTokens = getDstasTokens; +//# sourceMappingURL=script-samples.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-samples.js.map b/vendor/dxs-bsv-token-sdk/dist/script/script-samples.js.map new file mode 100644 index 0000000..32f3cce --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-samples.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script-samples.js","sourceRoot":"","sources":["../../src/script/script-samples.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-token.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/script-token.d.ts new file mode 100644 index 0000000..1aaf9e4 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-token.d.ts @@ -0,0 +1,17 @@ +import { OpCode } from "../bitcoin/op-codes"; +import { Bytes } from "../bytes"; +export declare class ScriptToken { + OpCodeNum: number; + OpCode?: OpCode; + Data?: Bytes; + DataLength: number; + IsReceiverId: boolean; + IsActionData: boolean; + IsRedemptionId: boolean; + IsFlagsField: boolean; + constructor(opCodeNum: number, opCode?: OpCode); + static fromBytes(buffer: Bytes): ScriptToken; + static fromScriptToken(from: ScriptToken): ScriptToken; + static forSample(opCodeNum: number, dataLength?: number, isReceiverId?: boolean): ScriptToken; +} +//# sourceMappingURL=script-token.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-token.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/script-token.d.ts.map new file mode 100644 index 0000000..8e2df47 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-token.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script-token.d.ts","sourceRoot":"","sources":["../../src/script/script-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,qBAAa,WAAW;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,MAAM,CAAK;IACvB,YAAY,EAAE,OAAO,CAAS;IAC9B,YAAY,EAAE,OAAO,CAAS;IAC9B,cAAc,EAAE,OAAO,CAAS;IAChC,YAAY,EAAE,OAAO,CAAS;gBAElB,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAK9C,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK;IAwB9B,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,WAAW;IAaxC,MAAM,CAAC,SAAS,CACd,SAAS,EAAE,MAAM,EACjB,UAAU,GAAE,MAAU,EACtB,YAAY,GAAE,OAAe;CAahC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-token.js b/vendor/dxs-bsv-token-sdk/dist/script/script-token.js new file mode 100644 index 0000000..a75c1da --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-token.js @@ -0,0 +1,56 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ScriptToken = void 0; +const op_codes_1 = require("../bitcoin/op-codes"); +const script_utils_1 = require("./script-utils"); +class ScriptToken { + constructor(opCodeNum, opCode) { + this.DataLength = 0; + this.IsReceiverId = false; + this.IsActionData = false; + this.IsRedemptionId = false; + this.IsFlagsField = false; + this.OpCode = opCode; + this.OpCodeNum = opCodeNum; + } + static fromBytes(buffer) { + const opCodeNum = buffer.length === 0 + ? -1 + : buffer.length < 76 + ? buffer.length + : buffer.length <= 255 + ? op_codes_1.OpCode.OP_PUSHDATA1 + : buffer.length <= 65535 + ? op_codes_1.OpCode.OP_PUSHDATA2 + : buffer.length <= 4294967295 + ? op_codes_1.OpCode.OP_PUSHDATA4 + : -1; + if (opCodeNum === -1) + throw new Error(`No data provided: ${buffer.length}`); + const token = new ScriptToken(opCodeNum); + token.Data = buffer; + token.DataLength = buffer.length; + return token; + } + static fromScriptToken(from) { + const token = from.Data + ? ScriptToken.fromBytes(from.Data) + : new ScriptToken(from.OpCodeNum, from.OpCode); + token.IsReceiverId = from.IsReceiverId; + token.IsActionData = from.IsActionData; + token.IsRedemptionId = from.IsRedemptionId; + token.IsFlagsField = from.IsFlagsField; + return token; + } + static forSample(opCodeNum, dataLength = 0, isReceiverId = false) { + const token = new ScriptToken(opCodeNum); + const { valid, opCode } = (0, script_utils_1.isOpCode)(opCodeNum); + if (valid === false) + token.OpCode = opCode; + token.DataLength = dataLength; + token.IsReceiverId = isReceiverId; + return token; + } +} +exports.ScriptToken = ScriptToken; +//# sourceMappingURL=script-token.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-token.js.map b/vendor/dxs-bsv-token-sdk/dist/script/script-token.js.map new file mode 100644 index 0000000..356c571 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-token.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script-token.js","sourceRoot":"","sources":["../../src/script/script-token.ts"],"names":[],"mappings":";;;AAAA,kDAA6C;AAC7C,iDAA0C;AAG1C,MAAa,WAAW;IAUtB,YAAY,SAAiB,EAAE,MAAe;QAN9C,eAAU,GAAW,CAAC,CAAC;QACvB,iBAAY,GAAY,KAAK,CAAC;QAC9B,iBAAY,GAAY,KAAK,CAAC;QAC9B,mBAAc,GAAY,KAAK,CAAC;QAChC,iBAAY,GAAY,KAAK,CAAC;QAG5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,MAAa;QAC5B,MAAM,SAAS,GACb,MAAM,CAAC,MAAM,KAAK,CAAC;YACjB,CAAC,CAAC,CAAC,CAAC;YACJ,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE;gBAClB,CAAC,CAAC,MAAM,CAAC,MAAM;gBACf,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG;oBACpB,CAAC,CAAC,iBAAM,CAAC,YAAY;oBACrB,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,KAAK;wBACtB,CAAC,CAAC,iBAAM,CAAC,YAAY;wBACrB,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,UAAU;4BAC3B,CAAC,CAAC,iBAAM,CAAC,YAAY;4BACrB,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjB,IAAI,SAAS,KAAK,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAE5E,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;QAEzC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC;QACpB,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;QAEjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,IAAiB;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI;YACrB,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;YAClC,CAAC,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAEjD,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QACvC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QACvC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;QAC3C,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QAEvC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,CAAC,SAAS,CACd,SAAiB,EACjB,aAAqB,CAAC,EACtB,eAAwB,KAAK;QAE7B,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;QAEzC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAA,uBAAQ,EAAC,SAAS,CAAC,CAAC;QAE9C,IAAI,KAAK,KAAK,KAAK;YAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;QAE3C,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC;QAC9B,KAAK,CAAC,YAAY,GAAG,YAAY,CAAC;QAElC,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AApED,kCAoEC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-utils.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/script-utils.d.ts new file mode 100644 index 0000000..3a94929 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-utils.d.ts @@ -0,0 +1,5 @@ +export declare const isOpCode: (opCodeNum: number) => { + valid: boolean; + opCode: number; +}; +//# sourceMappingURL=script-utils.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-utils.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/script-utils.d.ts.map new file mode 100644 index 0000000..34ad353 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script-utils.d.ts","sourceRoot":"","sources":["../../src/script/script-utils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ,GAAI,WAAW,MAAM;;;CASzC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-utils.js b/vendor/dxs-bsv-token-sdk/dist/script/script-utils.js new file mode 100644 index 0000000..7934185 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-utils.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isOpCode = void 0; +const op_codes_1 = require("../bitcoin/op-codes"); +const isOpCode = (opCodeNum) => { + if (opCodeNum === op_codes_1.OpCode.OP_0 || + (opCodeNum >= op_codes_1.OpCode.OP_PUSHDATA1 && opCodeNum <= op_codes_1.OpCode.OP_INVALIDOPCODE)) { + return { valid: true, opCode: opCodeNum }; + } + return { valid: false, opCode: op_codes_1.OpCode.OP_INVALIDOPCODE }; +}; +exports.isOpCode = isOpCode; +//# sourceMappingURL=script-utils.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/script-utils.js.map b/vendor/dxs-bsv-token-sdk/dist/script/script-utils.js.map new file mode 100644 index 0000000..1763196 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/script-utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script-utils.js","sourceRoot":"","sources":["../../src/script/script-utils.ts"],"names":[],"mappings":";;;AAAA,kDAA6C;AAEtC,MAAM,QAAQ,GAAG,CAAC,SAAiB,EAAE,EAAE;IAC5C,IACE,SAAS,KAAK,iBAAM,CAAC,IAAI;QACzB,CAAC,SAAS,IAAI,iBAAM,CAAC,YAAY,IAAI,SAAS,IAAI,iBAAM,CAAC,gBAAgB,CAAC,EAC1E,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC5C,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAM,CAAC,gBAAgB,EAAE,CAAC;AAC3D,CAAC,CAAC;AATW,QAAA,QAAQ,YASnB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.d.ts new file mode 100644 index 0000000..a3a8b77 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.d.ts @@ -0,0 +1,8 @@ +import { ScriptToken } from "../script-token"; +export type TemplateToken = { + op?: number; + data?: string; +}; +export declare const DSTAS_LOCKING_TEMPLATE_BASE: TemplateToken[]; +export declare const buildDstasTemplateBaseTokens: () => ScriptToken[]; +//# sourceMappingURL=dstas-locking-template-base.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.d.ts.map new file mode 100644 index 0000000..3350434 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-locking-template-base.d.ts","sourceRoot":"","sources":["../../../src/script/templates/dstas-locking-template-base.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AA0CF,eAAO,MAAM,2BAA2B,EAAE,aAAa,EAEtD,CAAC;AAEF,eAAO,MAAM,4BAA4B,qBAIrC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.js b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.js new file mode 100644 index 0000000..7e564bc --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.buildDstasTemplateBaseTokens = exports.DSTAS_LOCKING_TEMPLATE_BASE = void 0; +const bytes_1 = require("../../bytes"); +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_token_1 = require("../script-token"); +const dstas_locking_template_1 = require("./dstas-locking-template"); +const REDEMPTION_PLACEHOLDER = '<"redemption address"/"protocol ID" - 20 bytes> '; +const parseBaseAsmTokens = (templateAsm) => { + const normalized = templateAsm.replace(/\s+/g, " ").trim(); + const headMarker = ""; + const headIdx = normalized.indexOf(headMarker); + if (headIdx < 0) { + throw new Error("DSTAS template is missing '' marker"); + } + const bodyStart = headIdx + headMarker.length; + const tailMarker = `OP_RETURN ${REDEMPTION_PLACEHOLDER}`; + const tailIdx = normalized.indexOf(tailMarker, bodyStart); + if (tailIdx < 0) { + throw new Error("DSTAS template is missing redemption placeholder tail"); + } + const body = `${normalized.slice(bodyStart, tailIdx).trim()} OP_RETURN`; + const chunks = body.split(" ").filter(Boolean); + const opCodes = op_codes_1.OpCode; + return chunks.map((chunk) => { + if (chunk.startsWith("OP_")) { + const normalizedOp = chunk === "OP_FALSE" ? "OP_0" : chunk; + const op = opCodes[normalizedOp]; + if (typeof op !== "number") { + throw new Error(`Unsupported opcode in DSTAS template: ${chunk}`); + } + return { op }; + } + if (!/^[0-9a-fA-F]+$/.test(chunk)) { + throw new Error(`Unsupported token in DSTAS template: ${chunk}`); + } + return { data: chunk.toLowerCase() }; + }); +}; +exports.DSTAS_LOCKING_TEMPLATE_BASE = parseBaseAsmTokens(dstas_locking_template_1.DSTAS_LOCKING_TEMPLATE_ASM); +const buildDstasTemplateBaseTokens = () => exports.DSTAS_LOCKING_TEMPLATE_BASE.map((t) => { + if (t.data) + return script_token_1.ScriptToken.fromBytes((0, bytes_1.fromHex)(t.data)); + return new script_token_1.ScriptToken(t.op, t.op); +}); +exports.buildDstasTemplateBaseTokens = buildDstasTemplateBaseTokens; +//# sourceMappingURL=dstas-locking-template-base.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.js.map b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.js.map new file mode 100644 index 0000000..f05a07c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template-base.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-locking-template-base.js","sourceRoot":"","sources":["../../../src/script/templates/dstas-locking-template-base.ts"],"names":[],"mappings":";;;AAAA,uCAAsC;AACtC,qDAAgD;AAChD,kDAA8C;AAC9C,qEAAsE;AAOtE,MAAM,sBAAsB,GAC1B,6IAA6I,CAAC;AAEhJ,MAAM,kBAAkB,GAAG,CAAC,WAAmB,EAAmB,EAAE;IAClE,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3D,MAAM,UAAU,GAAG,eAAe,CAAC;IACnC,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC;IAC9C,MAAM,UAAU,GAAG,aAAa,sBAAsB,EAAE,CAAC;IACzD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC1D,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,YAAY,CAAC;IACxE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,iBAA2C,CAAC;IAE5D,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAC1B,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,YAAY,GAAG,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YAC3D,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,yCAAyC,KAAK,EAAE,CAAC,CAAC;YACpE,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,CAAC;QAChB,CAAC;QAED,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,wCAAwC,KAAK,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEW,QAAA,2BAA2B,GAAoB,kBAAkB,CAC5E,mDAA0B,CAC3B,CAAC;AAEK,MAAM,4BAA4B,GAAG,GAAG,EAAE,CAC/C,mCAA2B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;IACpC,IAAI,CAAC,CAAC,IAAI;QAAE,OAAO,0BAAW,CAAC,SAAS,CAAC,IAAA,eAAO,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,0BAAW,CAAC,CAAC,CAAC,EAAG,EAAE,CAAC,CAAC,EAAG,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC;AAJQ,QAAA,4BAA4B,gCAIpC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.d.ts b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.d.ts new file mode 100644 index 0000000..bed06d2 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.d.ts @@ -0,0 +1,2 @@ +export declare const DSTAS_LOCKING_TEMPLATE_ASM = "\n OP_2DROP OP_SIZE OP_IFDUP OP_IF 21 OP_EQUAL OP_IF OP_0 OP_ROT OP_ROT OP_1 OP_SWAP OP_2DUP OP_6 OP_ELSE OP_DUP OP_TOALTSTACK OP_1 OP_SPLIT OP_OVER OP_TOALTSTACK OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_DUP OP_FROMALTSTACK OP_ADD OP_FROMALTSTACK OP_SWAP OP_4 OP_ADD OP_ENDIF OP_ELSE OP_1 OP_ENDIF OP_DUP OP_2 OP_ADD OP_ROLL OP_DUP OP_HASH256 OP_16 OP_SPLIT OP_15 OP_SPLIT OP_SWAP OP_14 OP_SPLIT OP_SWAP OP_13 OP_SPLIT OP_SWAP OP_12 OP_SPLIT OP_SWAP OP_11 OP_SPLIT OP_SWAP OP_10 OP_SPLIT OP_SWAP OP_9 OP_SPLIT OP_SWAP OP_8 OP_SPLIT OP_SWAP OP_7 OP_SPLIT OP_SWAP OP_6 OP_SPLIT OP_SWAP OP_5 OP_SPLIT OP_SWAP OP_4 OP_SPLIT OP_SWAP OP_3 OP_SPLIT OP_SWAP OP_2 OP_SPLIT OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_SWAP OP_15 OP_SPLIT OP_SWAP OP_14 OP_SPLIT OP_SWAP OP_13 OP_SPLIT OP_SWAP OP_12 OP_SPLIT OP_SWAP OP_11 OP_SPLIT OP_SWAP OP_10 OP_SPLIT OP_SWAP OP_9 OP_SPLIT OP_SWAP OP_8 OP_SPLIT OP_SWAP OP_7 OP_SPLIT OP_SWAP OP_6 OP_SPLIT OP_SWAP OP_5 OP_SPLIT OP_SWAP OP_4 OP_SPLIT OP_SWAP OP_3 OP_SPLIT OP_SWAP OP_2 OP_SPLIT OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT 1F OP_SPLIT OP_TUCK OP_CAT 00 OP_CAT OP_BIN2NUM 414136D08C5ED2BF3BA048AFE6DCAEBAFE 00 OP_15 OP_NUM2BIN OP_INVERT OP_CAT 00 OP_CAT OP_DUP OP_2 OP_DIV OP_ROT OP_3 OP_ROLL OP_DUP ff OP_EQUAL OP_SWAP 00 OP_EQUAL OP_BOOLOR OP_TUCK OP_NOTIF OP_1ADD OP_ELSE OP_2 OP_PICK OP_ADD OP_ENDIF OP_3 OP_ROLL OP_TUCK OP_MOD OP_DUP OP_4 OP_ROLL OP_GREATERTHAN OP_IF OP_SUB OP_ELSE OP_NIP OP_ENDIF 3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220 OP_SWAP OP_16 OP_SPLIT OP_15 OP_SPLIT OP_SWAP OP_14 OP_SPLIT OP_SWAP OP_13 OP_SPLIT OP_SWAP OP_12 OP_SPLIT OP_SWAP OP_11 OP_SPLIT OP_SWAP OP_10 OP_SPLIT OP_SWAP OP_9 OP_SPLIT OP_SWAP OP_8 OP_SPLIT OP_SWAP OP_7 OP_SPLIT OP_SWAP OP_6 OP_SPLIT OP_SWAP OP_5 OP_SPLIT OP_SWAP OP_4 OP_SPLIT OP_SWAP OP_3 OP_SPLIT OP_SWAP OP_2 OP_SPLIT OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_SWAP OP_15 OP_SPLIT OP_SWAP OP_14 OP_SPLIT OP_SWAP OP_13 OP_SPLIT OP_SWAP OP_12 OP_SPLIT OP_SWAP OP_11 OP_SPLIT OP_SWAP OP_10 OP_SPLIT OP_SWAP OP_9 OP_SPLIT OP_SWAP OP_8 OP_SPLIT OP_SWAP OP_7 OP_SPLIT OP_SWAP OP_6 OP_SPLIT OP_SWAP OP_5 OP_SPLIT OP_SWAP OP_4 OP_SPLIT OP_SWAP OP_3 OP_SPLIT OP_SWAP OP_2 OP_SPLIT OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT 41 OP_CAT OP_SWAP OP_NOTIF 038ff83d8cf12121491609c4939dc11c4aa35503508fe432dc5a5c1905608b9218 OP_ELSE 023635954789a02e39fb7e54440b6f528d53efd65635ddad7f3c4085f97fdbdc48 OP_ENDIF OP_CHECKSIGVERIFY OP_4 OP_SPLIT OP_NIP 20 OP_SPLIT 20 OP_SPLIT OP_NIP 24 OP_SPLIT OP_1 OP_SPLIT OP_OVER 00 OP_CAT FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_OVER 00 OP_CAT OP_BIN2NUM OP_SPLIT OP_2SWAP OP_CAT OP_ROT OP_1 OP_SPLIT OP_SWAP 14 OP_TUCK OP_EQUALVERIFY OP_SPLIT OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP 61 OP_LESSTHAN OP_VERIFY OP_DUP 4e OP_GREATERTHAN OP_IF OP_TRUE OP_SWAP OP_ROT OP_ELSE OP_DUP 4b OP_GREATERTHAN OP_IF OP_DUP 4d OP_GREATERTHAN OP_IF OP_DROP OP_4 OP_ELSE 4d OP_NUMEQUAL OP_IF OP_2 OP_ELSE OP_1 OP_ENDIF OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_FALSE OP_ROT OP_ROT OP_ENDIF OP_DUP 540b OP_SPLIT OP_NIP 14 OP_SPLIT OP_SWAP OP_5 OP_PICK OP_EQUAL OP_TOALTSTACK OP_SIZE OP_NOTIF OP_DROP 0100 OP_ENDIF OP_TOALTSTACK OP_8 OP_ROLL OP_8 OP_ADD OP_DUP OP_TOALTSTACK OP_ROLL OP_DUP OP_1 OP_5 OP_WITHIN OP_VERIFY OP_FALSE OP_3 OP_PICK OP_IFDUP OP_IF OP_SIZE 3c OP_GREATERTHAN OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_ROT OP_BOOLAND OP_IF OP_2 OP_PICK OP_4 OP_EQUAL OP_IF OP_2ROT 00 OP_SWAP OP_CAT OP_2ROT OP_2ROT 20 OP_SPLIT 14 OP_SPLIT OP_DROP OP_NIP OP_NIP OP_ELSE OP_DROP OP_OVER OP_3 OP_EQUAL OP_NOTIF OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_1ADD OP_1ADD OP_PICK OP_1 OP_EQUALVERIFY OP_ENDIF OP_ENDIF OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_FROMALTSTACK OP_FROMALTSTACK OP_SWAP OP_TOALTSTACK OP_1 OP_SPLIT OP_SWAP OP_BIN2NUM OP_SPLIT OP_OVER OP_SIZE OP_IFDUP OP_IF OP_1SUB OP_SPLIT OP_NIP OP_ELSE OP_DROP 00 OP_ENDIF OP_1 OP_AND OP_IF OP_1 OP_SPLIT OP_SWAP 14 OP_TUCK OP_EQUALVERIFY OP_SPLIT OP_4 OP_PICK OP_2 OP_EQUAL OP_IF OP_2SWAP OP_NIP OP_SWAP OP_2ROT OP_SWAP OP_DUP OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_7 OP_PICK OP_DUP OP_IF OP_2 OP_PICK 52 OP_EQUAL OP_BOOLAND OP_ENDIF OP_BOOLOR OP_IF OP_1 OP_SPLIT OP_NIP OP_6 OP_ROLL OP_DROP OP_ELSE OP_2 OP_SWAP OP_DUP OP_BIN2NUM 4f 61 OP_WITHIN OP_8 OP_ROLL OP_BOOLAND OP_IF 50 OP_SUB OP_ENDIF OP_CAT OP_ENDIF OP_DEPTH OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_12 OP_ADD OP_EQUALVERIFY OP_DEPTH OP_1SUB OP_DUP OP_PICK OP_8 OP_PICK OP_EQUALVERIFY OP_1SUB OP_1SUB OP_PICK OP_OVER OP_EQUALVERIFY OP_ELSE OP_NIP OP_2ROT OP_SWAP OP_6 OP_ROLL OP_6 OP_PICK OP_3 OP_EQUAL OP_NOTIF OP_OVER 52 OP_EQUAL OP_BOOLAND OP_OVER OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_BOOLOR OP_DEPTH OP_3 OP_SUB OP_DUP OP_1ADD OP_PICK OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_SWAP OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_12 OP_ADD OP_2DUP OP_GREATERTHAN OP_IF OP_SWAP OP_1SUB OP_DUP OP_1ADD OP_PICK OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_2SWAP OP_TOALTSTACK OP_BOOLOR OP_SWAP OP_FROMALTSTACK OP_ENDIF OP_2DUP OP_GREATERTHAN OP_IF OP_SWAP OP_3 OP_SUB OP_DUP OP_1ADD OP_PICK OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_2SWAP OP_TOALTSTACK OP_BOOLOR OP_SWAP OP_FROMALTSTACK OP_ENDIF OP_2DUP OP_GREATERTHAN OP_IF OP_DROP OP_4 OP_SUB OP_PICK OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_BOOLOR OP_ELSE OP_2DROP OP_ENDIF OP_BOOLOR OP_IF OP_FALSE OP_VERIFY OP_ENDIF OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_SWAP OP_2ROT OP_2ROT OP_ELSE OP_6 OP_ROLL OP_DROP OP_ENDIF OP_OVER OP_SIZE OP_IFDUP OP_IF OP_1SUB OP_SPLIT OP_NIP OP_ELSE OP_DROP 00 OP_ENDIF OP_2 OP_AND OP_IF OP_1 OP_SPLIT OP_SWAP 14 OP_TUCK OP_EQUALVERIFY OP_SPLIT OP_4 OP_PICK OP_3 OP_EQUAL OP_IF OP_2SWAP OP_NIP OP_SWAP OP_ELSE OP_NIP OP_ENDIF OP_ENDIF OP_2DROP OP_FROMALTSTACK OP_DROP OP_OVER OP_DUP OP_3 OP_EQUAL OP_SWAP OP_2 OP_EQUAL OP_BOOLOR OP_IF OP_FROMALTSTACK OP_DROP OP_0 OP_TOALTSTACK OP_ENDIF OP_SWAP OP_1 OP_EQUAL OP_IF OP_DROP OP_2 OP_PICK OP_ENDIF OP_8 OP_PICK OP_HASH160 OP_EQUALVERIFY OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_SIZE OP_NIP OP_IF OP_CHECKMULTISIGVERIFY OP_ENDIF OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_4 OP_ROLL OP_7 OP_ROLL OP_DUP OP_NOTIF OP_7 OP_ROLL OP_7 OP_ROLL OP_8 OP_ROLL OP_9 OP_ROLL OP_OVER OP_IF OP_4 OP_NUM2BIN OP_CAT OP_CAT OP_ELSE OP_2DROP OP_ENDIF OP_HASH256 OP_EQUALVERIFY OP_0 OP_ELSE OP_ROT OP_SWAP OP_DUP OP_1 OP_EQUAL OP_IF OP_DROP OP_7 OP_ROLL OP_SWAP OP_8 OP_ROLL OP_ELSE OP_FALSE OP_SWAP OP_ENDIF OP_DUP OP_2 OP_8 OP_WITHIN OP_VERIFY OP_DUP OP_1 OP_EQUAL OP_NOTIF OP_2 OP_SUB OP_9 OP_ROLL OP_3 OP_PICK OP_11 OP_ROLL OP_CAT OP_CAT OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_ENDIF OP_2SWAP OP_DUP OP_NOTIF OP_DROP OP_2SWAP OP_ELSE OP_NIP OP_2SWAP OP_DROP OP_1 OP_ENDIF OP_3 OP_ROLL OP_DUP OP_HASH256 OP_10 OP_ROLL OP_TUCK OP_4 OP_NUM2BIN OP_CAT OP_9 OP_ROLL OP_11 OP_ROLL OP_12 OP_ROLL OP_OVER OP_IF OP_4 OP_NUM2BIN OP_CAT OP_3DUP OP_CAT OP_CAT OP_HASH256 OP_2SWAP OP_SWAP OP_CAT OP_ELSE OP_2DROP OP_2DUP OP_CAT OP_HASH256 OP_SWAP OP_ENDIF OP_ROT OP_CAT OP_HASH256 OP_10 OP_ROLL OP_TUCK OP_EQUAL OP_DUP OP_IF OP_1 OP_ELSE OP_2 OP_ENDIF OP_SWAP OP_2SWAP OP_EQUAL OP_BOOLOR OP_VERIFY OP_3 OP_ROLL OP_NOTIF OP_NOT OP_ENDIF OP_SWAP OP_ROT OP_4 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_OVER OP_3 OP_GREATERTHAN OP_NOT OP_VERIFY 24 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_4 OP_ADD OP_SPLIT OP_NIP OP_OVER OP_1SUB OP_IF 24 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_4 OP_ADD OP_SPLIT OP_NIP OP_OVER OP_2 OP_SUB OP_IF 24 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_4 OP_ADD OP_SPLIT OP_NIP OP_ENDIF OP_ENDIF OP_NIP OP_1 OP_SPLIT OP_SWAP OP_2 OP_PICK OP_TUCK OP_1ADD OP_LESSTHAN OP_SWAP OP_3 OP_GREATERTHAN OP_BOOLOR OP_NOT OP_VERIFY OP_SWAP OP_DUP OP_IF OP_1SUB OP_SWAP OP_8 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_NIP OP_SWAP OP_ENDIF OP_DUP OP_IF OP_1SUB OP_SWAP OP_8 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_NIP OP_SWAP OP_ENDIF OP_IF OP_8 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_NIP OP_ENDIF OP_8 OP_SPLIT OP_1 OP_SPLIT OP_OVER 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_OVER 00 OP_CAT OP_BIN2NUM OP_2SWAP OP_CAT OP_ROT OP_ROT OP_ENDIF OP_SPLIT OP_DROP OP_1 OP_SPLIT OP_SWAP 14 OP_TUCK OP_EQUALVERIFY OP_SPLIT OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP 61 OP_LESSTHAN OP_VERIFY OP_DUP 4e OP_GREATERTHAN OP_IF OP_SWAP OP_ELSE OP_DUP 4b OP_GREATERTHAN OP_IF OP_DUP 4d OP_GREATERTHAN OP_IF OP_DROP OP_4 OP_ELSE 4d OP_NUMEQUAL OP_IF OP_2 OP_ELSE OP_1 OP_ENDIF OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_ENDIF OP_5 OP_PICK OP_NOTIF OP_7 OP_PICK OP_EQUALVERIFY OP_DROP OP_2DROP OP_ELSE OP_2ROT OP_ENDIF OP_BIN2NUM OP_ENDIF OP_OVER OP_IF OP_6 OP_ROLL OP_ELSE OP_ROT OP_ENDIF OP_8 OP_SPLIT OP_SWAP OP_BIN2NUM OP_3 OP_PICK OP_IF OP_3 OP_PICK OP_2 OP_EQUAL OP_IF OP_ROT OP_TOALTSTACK OP_3 OP_ROLL OP_TOALTSTACK OP_2ROT OP_SWAP OP_TOALTSTACK OP_TOALTSTACK OP_3 OP_ROLL OP_TOALTSTACK OP_ELSE OP_TOALTSTACK OP_7 OP_ROLL OP_TOALTSTACK OP_9 OP_ROLL OP_TOALTSTACK OP_8 OP_ROLL OP_TOALTSTACK OP_7 OP_ROLL OP_TOALTSTACK OP_SWAP OP_ENDIF OP_ELSE OP_ROT OP_ADD OP_ENDIF OP_SWAP OP_4 OP_SPLIT OP_NIP 20 OP_SPLIT OP_DROP OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_VERIFY OP_DUP OP_8 OP_NUM2BIN 4676a914 OP_OVER 14 OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_2SWAP OP_ROT OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_SIZE OP_NOT OP_OVER OP_SIZE OP_1 OP_EQUAL OP_SWAP OP_DUP OP_1NEGATE OP_EQUAL OP_SWAP OP_BIN2NUM OP_1 11 OP_WITHIN OP_BOOLOR OP_BOOLAND OP_BOOLOR OP_NOTIF OP_SIZE OP_DUP 4b OP_LESSTHANOREQUAL OP_NOTIF OP_DUP ff00 OP_LESSTHANOREQUAL OP_IF OP_1 4c OP_ELSE OP_DUP ffff00 OP_LESSTHANOREQUAL OP_IF OP_2 4d OP_ELSE OP_4 4e OP_ENDIF OP_ENDIF OP_ROT OP_ROT OP_SPLIT OP_DROP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_ELSE OP_IFDUP OP_IF 50 OP_ADD OP_ELSE 00 OP_ENDIF OP_ENDIF OP_12 OP_PICK OP_12 OP_PICK OP_IF OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_IFDUP OP_IF OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_IF 20 OP_SPLIT OP_SWAP OP_2 OP_PICK OP_SHA256 OP_EQUAL OP_SWAP 1c OP_SPLIT OP_5 OP_PICK OP_EQUAL OP_SWAP 14 OP_SPLIT OP_DROP OP_6 OP_PICK OP_EQUAL OP_BOOLAND OP_BOOLAND OP_VERIFY OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_ENDIF OP_CAT OP_NIP OP_CAT OP_CAT OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF OP_DUP FFFF00 OP_GREATERTHAN OP_IF fe OP_SWAP OP_SIZE OP_4 OP_ELSE fd OP_SWAP OP_SIZE OP_2 OP_ENDIF OP_TUCK OP_GREATERTHAN OP_IF OP_SPLIT OP_DROP OP_ELSE OP_NUM2BIN OP_ENDIF OP_CAT OP_ELSE OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_SWAP OP_CAT OP_CAT 888201218763ac67517f 517f73637c7f68 OP_DUP OP_DUP OP_CAT OP_DUP OP_CAT OP_CAT ae68 OP_CAT OP_CAT OP_SWAP OP_5 OP_ROLL OP_0 OP_DEPTH 11 OP_GREATERTHAN OP_IF OP_0 OP_10 OP_PICK OP_NOTIF OP_TOALTSTACK OP_SWAP OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_VERIFY OP_TUCK OP_ADD OP_ROT OP_ROT OP_8 OP_NUM2BIN OP_CAT OP_FROMALTSTACK OP_NOT OP_ELSE OP_SWAP OP_DEPTH OP_1SUB OP_ROLL OP_TUCK OP_8 OP_NUM2BIN OP_CAT OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_5 OP_ROLL OP_ENDIF 14 OP_DEPTH OP_1SUB OP_ROLL OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_SIZE OP_NOT OP_OVER OP_SIZE OP_1 OP_EQUAL OP_SWAP OP_DUP OP_1NEGATE OP_EQUAL OP_SWAP OP_BIN2NUM OP_1 11 OP_WITHIN OP_BOOLOR OP_BOOLAND OP_BOOLOR OP_NOTIF OP_SIZE OP_DUP 4b OP_LESSTHANOREQUAL OP_NOTIF OP_DUP ff00 OP_LESSTHANOREQUAL OP_IF OP_1 4c OP_ELSE OP_DUP ffff00 OP_LESSTHANOREQUAL OP_IF OP_2 4d OP_ELSE OP_4 4e OP_ENDIF OP_ENDIF OP_ROT OP_ROT OP_SPLIT OP_DROP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_ELSE OP_IFDUP OP_IF 50 OP_ADD OP_ELSE 00 OP_ENDIF OP_ENDIF OP_4 OP_PICK OP_IF OP_15 OP_PICK OP_ELSE OP_FROMALTSTACK OP_DUP OP_TOALTSTACK 15 OP_PICK OP_IFDUP OP_IF OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_IF 20 OP_SPLIT OP_SWAP OP_2 OP_PICK OP_SHA256 OP_EQUAL OP_SWAP 1c OP_SPLIT OP_5 OP_PICK OP_EQUAL OP_SWAP 14 OP_SPLIT OP_DROP OP_6 OP_PICK OP_EQUAL OP_BOOLAND OP_BOOLAND OP_VERIFY OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_ENDIF OP_CAT OP_NIP OP_CAT OP_CAT OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF OP_DUP FFFF00 OP_GREATERTHAN OP_IF fe OP_SWAP OP_SIZE OP_4 OP_ELSE fd OP_SWAP OP_SIZE OP_2 OP_ENDIF OP_TUCK OP_GREATERTHAN OP_IF OP_SPLIT OP_DROP OP_ELSE OP_NUM2BIN OP_ENDIF OP_CAT OP_ELSE OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_SWAP OP_CAT OP_SWAP OP_IF OP_CAT OP_ELSE OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_CAT OP_SWAP OP_TOALTSTACK OP_ENDIF OP_ENDIF OP_9 OP_PICK OP_IF OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_OVER OP_TOALTSTACK OP_IFDUP OP_IF OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_IF 34 OP_SPLIT OP_NIP OP_4 OP_SPLIT OP_4 OP_SPLIT OP_DROP OP_OVER OP_IF OP_2 OP_PICK OP_ROT 00 OP_CAT OP_BIN2NUM OP_MUL OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DIV OP_3 OP_PICK OP_LESSTHANOREQUAL OP_VERIFY OP_ELSE OP_2DROP OP_ENDIF OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_12 OP_PICK OP_IFDUP OP_IF OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_IF 34 OP_SPLIT OP_NIP OP_4 OP_SPLIT OP_4 OP_SPLIT OP_DROP OP_OVER OP_IF OP_4 OP_PICK OP_ROT 00 OP_CAT OP_BIN2NUM OP_MUL OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DIV OP_OVER OP_LESSTHANOREQUAL OP_VERIFY OP_ELSE OP_2DROP OP_ENDIF OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_DROP OP_ENDIF OP_DEPTH 11 OP_GREATERTHAN OP_IF OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_VERIFY OP_TUCK OP_8 OP_NUM2BIN OP_CAT OP_FALSE OP_FALSE OP_12 OP_PICK OP_IF OP_14 OP_PICK OP_DUP OP_SIZE OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_1 OP_EQUAL OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_DUP OP_SIZE OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_1 OP_EQUAL OP_ROT OP_2DUP OP_BOOLOR OP_IF OP_OVER OP_NUMEQUAL OP_IF OP_DROP OP_DEPTH OP_2 OP_SUB OP_PICK OP_ROT OP_OVER OP_EQUAL OP_ROT OP_ROT OP_EQUAL OP_TUCK OP_BOOLOR OP_VERIFY OP_IF OP_SWAP OP_NOT OP_SWAP OP_ENDIF OP_NOT OP_ELSE OP_DEPTH OP_2 OP_SUB OP_PICK OP_SWAP OP_IF OP_EQUAL OP_NIP OP_IF OP_SWAP OP_NOT OP_SWAP OP_NOT OP_ENDIF OP_ELSE OP_NIP OP_EQUAL OP_IF OP_NOT OP_ELSE OP_SWAP OP_NOT OP_SWAP OP_ENDIF OP_ENDIF OP_ENDIF OP_ELSE OP_2DROP OP_2DROP OP_ENDIF OP_ENDIF OP_OVER OP_IF OP_3 OP_ROLL OP_FROMALTSTACK OP_ADD OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_6 OP_ROLL OP_6 OP_ROLL OP_4 OP_PICK OP_4 OP_PICK OP_8 OP_ROLL OP_ELSE OP_TOALTSTACK OP_2SWAP OP_ADD OP_ROT OP_ROT OP_12 OP_PICK OP_14 OP_PICK OP_FROMALTSTACK OP_ENDIF OP_DEPTH OP_1SUB OP_ROLL OP_DEPTH OP_1SUB OP_ROLL OP_ROT OP_IF OP_2DUP OP_2ROT OP_ROT OP_ROT OP_EQUAL OP_ROT OP_ROT OP_EQUAL OP_BOOLAND OP_VERIFY OP_ELSE OP_2SWAP OP_2DROP OP_ENDIF 14 OP_ROT OP_CAT OP_SWAP OP_SIZE OP_NOT OP_OVER OP_SIZE OP_1 OP_EQUAL OP_SWAP OP_DUP OP_1NEGATE OP_EQUAL OP_SWAP OP_BIN2NUM OP_1 11 OP_WITHIN OP_BOOLOR OP_BOOLAND OP_BOOLOR OP_NOTIF OP_SIZE OP_DUP 4b OP_LESSTHANOREQUAL OP_NOTIF OP_DUP ff00 OP_LESSTHANOREQUAL OP_IF OP_1 4c OP_ELSE OP_DUP ffff00 OP_LESSTHANOREQUAL OP_IF OP_2 4d OP_ELSE OP_4 4e OP_ENDIF OP_ENDIF OP_ROT OP_ROT OP_SPLIT OP_DROP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_ELSE OP_IFDUP OP_IF 50 OP_ADD OP_ELSE 00 OP_ENDIF OP_ENDIF OP_CAT OP_SWAP OP_IF OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_CAT OP_2SWAP OP_TOALTSTACK OP_TOALTSTACK OP_2SWAP OP_TOALTSTACK OP_TOALTSTACK OP_ELSE OP_11 OP_PICK OP_CAT OP_ENDIF OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF OP_DUP FFFF00 OP_GREATERTHAN OP_IF fe OP_SWAP OP_SIZE OP_4 OP_ELSE fd OP_SWAP OP_SIZE OP_2 OP_ENDIF OP_TUCK OP_GREATERTHAN OP_IF OP_SPLIT OP_DROP OP_ELSE OP_NUM2BIN OP_ENDIF OP_CAT OP_ELSE OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_SWAP OP_CAT OP_CAT OP_ENDIF OP_DEPTH 11 OP_GREATERTHAN OP_IF OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_VERIFY OP_TUCK OP_8 OP_NUM2BIN OP_CAT OP_FALSE OP_FALSE OP_12 OP_PICK OP_IF OP_14 OP_PICK OP_DUP OP_SIZE OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_1 OP_EQUAL OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_DUP OP_SIZE OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_1 OP_EQUAL OP_ROT OP_2DUP OP_BOOLOR OP_IF OP_OVER OP_NUMEQUAL OP_IF OP_DROP OP_DEPTH OP_2 OP_SUB OP_PICK OP_ROT OP_OVER OP_EQUAL OP_ROT OP_ROT OP_EQUAL OP_TUCK OP_BOOLOR OP_VERIFY OP_IF OP_SWAP OP_NOT OP_SWAP OP_ENDIF OP_NOT OP_ELSE OP_DEPTH OP_2 OP_SUB OP_PICK OP_SWAP OP_IF OP_EQUAL OP_NIP OP_IF OP_SWAP OP_NOT OP_SWAP OP_NOT OP_ENDIF OP_ELSE OP_NIP OP_EQUAL OP_IF OP_NOT OP_ELSE OP_SWAP OP_NOT OP_SWAP OP_ENDIF OP_ENDIF OP_ENDIF OP_ELSE OP_2DROP OP_2DROP OP_ENDIF OP_ENDIF OP_OVER OP_IF OP_3 OP_ROLL OP_FROMALTSTACK OP_ADD OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_6 OP_ROLL OP_6 OP_ROLL OP_4 OP_PICK OP_4 OP_PICK OP_8 OP_ROLL OP_ELSE OP_TOALTSTACK OP_2SWAP OP_ADD OP_ROT OP_ROT OP_12 OP_PICK OP_14 OP_PICK OP_FROMALTSTACK OP_ENDIF OP_DEPTH OP_1SUB OP_ROLL OP_DEPTH OP_1SUB OP_ROLL OP_ROT OP_IF OP_2DUP OP_2ROT OP_ROT OP_ROT OP_EQUAL OP_ROT OP_ROT OP_EQUAL OP_BOOLAND OP_VERIFY OP_ELSE OP_2SWAP OP_2DROP OP_ENDIF 14 OP_ROT OP_CAT OP_SWAP OP_SIZE OP_NOT OP_OVER OP_SIZE OP_1 OP_EQUAL OP_SWAP OP_DUP OP_1NEGATE OP_EQUAL OP_SWAP OP_BIN2NUM OP_1 11 OP_WITHIN OP_BOOLOR OP_BOOLAND OP_BOOLOR OP_NOTIF OP_SIZE OP_DUP 4b OP_LESSTHANOREQUAL OP_NOTIF OP_DUP ff00 OP_LESSTHANOREQUAL OP_IF OP_1 4c OP_ELSE OP_DUP ffff00 OP_LESSTHANOREQUAL OP_IF OP_2 4d OP_ELSE OP_4 4e OP_ENDIF OP_ENDIF OP_ROT OP_ROT OP_SPLIT OP_DROP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_ELSE OP_IFDUP OP_IF 50 OP_ADD OP_ELSE 00 OP_ENDIF OP_ENDIF OP_CAT OP_SWAP OP_IF OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_CAT OP_2SWAP OP_TOALTSTACK OP_TOALTSTACK OP_2SWAP OP_TOALTSTACK OP_TOALTSTACK OP_ELSE OP_11 OP_PICK OP_CAT OP_ENDIF OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF OP_DUP FFFF00 OP_GREATERTHAN OP_IF fe OP_SWAP OP_SIZE OP_4 OP_ELSE fd OP_SWAP OP_SIZE OP_2 OP_ENDIF OP_TUCK OP_GREATERTHAN OP_IF OP_SPLIT OP_DROP OP_ELSE OP_NUM2BIN OP_ENDIF OP_CAT OP_ELSE OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_SWAP OP_CAT OP_CAT OP_ENDIF OP_9 OP_ROLL OP_IF OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_2DROP OP_FROMALTSTACK OP_FROMALTSTACK OP_2DROP OP_FROMALTSTACK OP_NUMEQUALVERIFY OP_ENDIF OP_SWAP OP_8 OP_ROLL OP_NUMEQUALVERIFY OP_TUCK OP_CAT OP_12 OP_PICK OP_IF OP_13 OP_PICK OP_8 OP_NUM2BIN 1976a914 OP_14 OP_PICK OP_CAT 88ac OP_CAT OP_CAT OP_ELSE OP_0 OP_ENDIF OP_TUCK OP_CAT OP_12 OP_ROLL OP_DUP OP_IF 006A OP_SWAP OP_CAT OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF fd OP_SWAP OP_CAT OP_3 OP_ELSE OP_1 OP_ENDIF OP_SPLIT OP_DROP OP_SWAP OP_CAT OP_0 OP_8 OP_NUM2BIN OP_SWAP OP_CAT OP_ENDIF OP_TUCK OP_CAT OP_HASH256 OP_TOALTSTACK OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_HASH256 OP_OVER OP_EQUAL OP_SWAP OP_FROMALTSTACK OP_EQUAL OP_SWAP OP_FROMALTSTACK OP_BOOLAND OP_BOOLOR OP_2SWAP OP_2DROP OP_2SWAP OP_2DROP OP_NIP OP_NIP OP_RETURN <\"redemption address\"/\"protocol ID\" - 20 bytes> \n"; +//# sourceMappingURL=dstas-locking-template.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.d.ts.map new file mode 100644 index 0000000..484c1ff --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-locking-template.d.ts","sourceRoot":"","sources":["../../../src/script/templates/dstas-locking-template.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B,mqoBAEtC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.js b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.js new file mode 100644 index 0000000..beecd31 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DSTAS_LOCKING_TEMPLATE_ASM = void 0; +exports.DSTAS_LOCKING_TEMPLATE_ASM = ` + OP_2DROP OP_SIZE OP_IFDUP OP_IF 21 OP_EQUAL OP_IF OP_0 OP_ROT OP_ROT OP_1 OP_SWAP OP_2DUP OP_6 OP_ELSE OP_DUP OP_TOALTSTACK OP_1 OP_SPLIT OP_OVER OP_TOALTSTACK OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_1 OP_SPLIT OP_IFDUP OP_IF OP_SWAP OP_SPLIT OP_ENDIF OP_DUP OP_FROMALTSTACK OP_ADD OP_FROMALTSTACK OP_SWAP OP_4 OP_ADD OP_ENDIF OP_ELSE OP_1 OP_ENDIF OP_DUP OP_2 OP_ADD OP_ROLL OP_DUP OP_HASH256 OP_16 OP_SPLIT OP_15 OP_SPLIT OP_SWAP OP_14 OP_SPLIT OP_SWAP OP_13 OP_SPLIT OP_SWAP OP_12 OP_SPLIT OP_SWAP OP_11 OP_SPLIT OP_SWAP OP_10 OP_SPLIT OP_SWAP OP_9 OP_SPLIT OP_SWAP OP_8 OP_SPLIT OP_SWAP OP_7 OP_SPLIT OP_SWAP OP_6 OP_SPLIT OP_SWAP OP_5 OP_SPLIT OP_SWAP OP_4 OP_SPLIT OP_SWAP OP_3 OP_SPLIT OP_SWAP OP_2 OP_SPLIT OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_SWAP OP_15 OP_SPLIT OP_SWAP OP_14 OP_SPLIT OP_SWAP OP_13 OP_SPLIT OP_SWAP OP_12 OP_SPLIT OP_SWAP OP_11 OP_SPLIT OP_SWAP OP_10 OP_SPLIT OP_SWAP OP_9 OP_SPLIT OP_SWAP OP_8 OP_SPLIT OP_SWAP OP_7 OP_SPLIT OP_SWAP OP_6 OP_SPLIT OP_SWAP OP_5 OP_SPLIT OP_SWAP OP_4 OP_SPLIT OP_SWAP OP_3 OP_SPLIT OP_SWAP OP_2 OP_SPLIT OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT 1F OP_SPLIT OP_TUCK OP_CAT 00 OP_CAT OP_BIN2NUM 414136D08C5ED2BF3BA048AFE6DCAEBAFE 00 OP_15 OP_NUM2BIN OP_INVERT OP_CAT 00 OP_CAT OP_DUP OP_2 OP_DIV OP_ROT OP_3 OP_ROLL OP_DUP ff OP_EQUAL OP_SWAP 00 OP_EQUAL OP_BOOLOR OP_TUCK OP_NOTIF OP_1ADD OP_ELSE OP_2 OP_PICK OP_ADD OP_ENDIF OP_3 OP_ROLL OP_TUCK OP_MOD OP_DUP OP_4 OP_ROLL OP_GREATERTHAN OP_IF OP_SUB OP_ELSE OP_NIP OP_ENDIF 3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220 OP_SWAP OP_16 OP_SPLIT OP_15 OP_SPLIT OP_SWAP OP_14 OP_SPLIT OP_SWAP OP_13 OP_SPLIT OP_SWAP OP_12 OP_SPLIT OP_SWAP OP_11 OP_SPLIT OP_SWAP OP_10 OP_SPLIT OP_SWAP OP_9 OP_SPLIT OP_SWAP OP_8 OP_SPLIT OP_SWAP OP_7 OP_SPLIT OP_SWAP OP_6 OP_SPLIT OP_SWAP OP_5 OP_SPLIT OP_SWAP OP_4 OP_SPLIT OP_SWAP OP_3 OP_SPLIT OP_SWAP OP_2 OP_SPLIT OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_SWAP OP_15 OP_SPLIT OP_SWAP OP_14 OP_SPLIT OP_SWAP OP_13 OP_SPLIT OP_SWAP OP_12 OP_SPLIT OP_SWAP OP_11 OP_SPLIT OP_SWAP OP_10 OP_SPLIT OP_SWAP OP_9 OP_SPLIT OP_SWAP OP_8 OP_SPLIT OP_SWAP OP_7 OP_SPLIT OP_SWAP OP_6 OP_SPLIT OP_SWAP OP_5 OP_SPLIT OP_SWAP OP_4 OP_SPLIT OP_SWAP OP_3 OP_SPLIT OP_SWAP OP_2 OP_SPLIT OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT 41 OP_CAT OP_SWAP OP_NOTIF 038ff83d8cf12121491609c4939dc11c4aa35503508fe432dc5a5c1905608b9218 OP_ELSE 023635954789a02e39fb7e54440b6f528d53efd65635ddad7f3c4085f97fdbdc48 OP_ENDIF OP_CHECKSIGVERIFY OP_4 OP_SPLIT OP_NIP 20 OP_SPLIT 20 OP_SPLIT OP_NIP 24 OP_SPLIT OP_1 OP_SPLIT OP_OVER 00 OP_CAT FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_OVER 00 OP_CAT OP_BIN2NUM OP_SPLIT OP_2SWAP OP_CAT OP_ROT OP_1 OP_SPLIT OP_SWAP 14 OP_TUCK OP_EQUALVERIFY OP_SPLIT OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP 61 OP_LESSTHAN OP_VERIFY OP_DUP 4e OP_GREATERTHAN OP_IF OP_TRUE OP_SWAP OP_ROT OP_ELSE OP_DUP 4b OP_GREATERTHAN OP_IF OP_DUP 4d OP_GREATERTHAN OP_IF OP_DROP OP_4 OP_ELSE 4d OP_NUMEQUAL OP_IF OP_2 OP_ELSE OP_1 OP_ENDIF OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_FALSE OP_ROT OP_ROT OP_ENDIF OP_DUP 540b OP_SPLIT OP_NIP 14 OP_SPLIT OP_SWAP OP_5 OP_PICK OP_EQUAL OP_TOALTSTACK OP_SIZE OP_NOTIF OP_DROP 0100 OP_ENDIF OP_TOALTSTACK OP_8 OP_ROLL OP_8 OP_ADD OP_DUP OP_TOALTSTACK OP_ROLL OP_DUP OP_1 OP_5 OP_WITHIN OP_VERIFY OP_FALSE OP_3 OP_PICK OP_IFDUP OP_IF OP_SIZE 3c OP_GREATERTHAN OP_SWAP OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_ROT OP_BOOLAND OP_IF OP_2 OP_PICK OP_4 OP_EQUAL OP_IF OP_2ROT 00 OP_SWAP OP_CAT OP_2ROT OP_2ROT 20 OP_SPLIT 14 OP_SPLIT OP_DROP OP_NIP OP_NIP OP_ELSE OP_DROP OP_OVER OP_3 OP_EQUAL OP_NOTIF OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_1ADD OP_1ADD OP_PICK OP_1 OP_EQUALVERIFY OP_ENDIF OP_ENDIF OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_FROMALTSTACK OP_FROMALTSTACK OP_SWAP OP_TOALTSTACK OP_1 OP_SPLIT OP_SWAP OP_BIN2NUM OP_SPLIT OP_OVER OP_SIZE OP_IFDUP OP_IF OP_1SUB OP_SPLIT OP_NIP OP_ELSE OP_DROP 00 OP_ENDIF OP_1 OP_AND OP_IF OP_1 OP_SPLIT OP_SWAP 14 OP_TUCK OP_EQUALVERIFY OP_SPLIT OP_4 OP_PICK OP_2 OP_EQUAL OP_IF OP_2SWAP OP_NIP OP_SWAP OP_2ROT OP_SWAP OP_DUP OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_7 OP_PICK OP_DUP OP_IF OP_2 OP_PICK 52 OP_EQUAL OP_BOOLAND OP_ENDIF OP_BOOLOR OP_IF OP_1 OP_SPLIT OP_NIP OP_6 OP_ROLL OP_DROP OP_ELSE OP_2 OP_SWAP OP_DUP OP_BIN2NUM 4f 61 OP_WITHIN OP_8 OP_ROLL OP_BOOLAND OP_IF 50 OP_SUB OP_ENDIF OP_CAT OP_ENDIF OP_DEPTH OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_12 OP_ADD OP_EQUALVERIFY OP_DEPTH OP_1SUB OP_DUP OP_PICK OP_8 OP_PICK OP_EQUALVERIFY OP_1SUB OP_1SUB OP_PICK OP_OVER OP_EQUALVERIFY OP_ELSE OP_NIP OP_2ROT OP_SWAP OP_6 OP_ROLL OP_6 OP_PICK OP_3 OP_EQUAL OP_NOTIF OP_OVER 52 OP_EQUAL OP_BOOLAND OP_OVER OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_BOOLOR OP_DEPTH OP_3 OP_SUB OP_DUP OP_1ADD OP_PICK OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_SWAP OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_12 OP_ADD OP_2DUP OP_GREATERTHAN OP_IF OP_SWAP OP_1SUB OP_DUP OP_1ADD OP_PICK OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_2SWAP OP_TOALTSTACK OP_BOOLOR OP_SWAP OP_FROMALTSTACK OP_ENDIF OP_2DUP OP_GREATERTHAN OP_IF OP_SWAP OP_3 OP_SUB OP_DUP OP_1ADD OP_PICK OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_2SWAP OP_TOALTSTACK OP_BOOLOR OP_SWAP OP_FROMALTSTACK OP_ENDIF OP_2DUP OP_GREATERTHAN OP_IF OP_DROP OP_4 OP_SUB OP_PICK OP_DUP OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_2 OP_EQUAL OP_BOOLOR OP_ELSE OP_2DROP OP_ENDIF OP_BOOLOR OP_IF OP_FALSE OP_VERIFY OP_ENDIF OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_SWAP OP_2ROT OP_2ROT OP_ELSE OP_6 OP_ROLL OP_DROP OP_ENDIF OP_OVER OP_SIZE OP_IFDUP OP_IF OP_1SUB OP_SPLIT OP_NIP OP_ELSE OP_DROP 00 OP_ENDIF OP_2 OP_AND OP_IF OP_1 OP_SPLIT OP_SWAP 14 OP_TUCK OP_EQUALVERIFY OP_SPLIT OP_4 OP_PICK OP_3 OP_EQUAL OP_IF OP_2SWAP OP_NIP OP_SWAP OP_ELSE OP_NIP OP_ENDIF OP_ENDIF OP_2DROP OP_FROMALTSTACK OP_DROP OP_OVER OP_DUP OP_3 OP_EQUAL OP_SWAP OP_2 OP_EQUAL OP_BOOLOR OP_IF OP_FROMALTSTACK OP_DROP OP_0 OP_TOALTSTACK OP_ENDIF OP_SWAP OP_1 OP_EQUAL OP_IF OP_DROP OP_2 OP_PICK OP_ENDIF OP_8 OP_PICK OP_HASH160 OP_EQUALVERIFY OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_TOALTSTACK OP_SIZE OP_NIP OP_IF OP_CHECKMULTISIGVERIFY OP_ENDIF OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_4 OP_ROLL OP_7 OP_ROLL OP_DUP OP_NOTIF OP_7 OP_ROLL OP_7 OP_ROLL OP_8 OP_ROLL OP_9 OP_ROLL OP_OVER OP_IF OP_4 OP_NUM2BIN OP_CAT OP_CAT OP_ELSE OP_2DROP OP_ENDIF OP_HASH256 OP_EQUALVERIFY OP_0 OP_ELSE OP_ROT OP_SWAP OP_DUP OP_1 OP_EQUAL OP_IF OP_DROP OP_7 OP_ROLL OP_SWAP OP_8 OP_ROLL OP_ELSE OP_FALSE OP_SWAP OP_ENDIF OP_DUP OP_2 OP_8 OP_WITHIN OP_VERIFY OP_DUP OP_1 OP_EQUAL OP_NOTIF OP_2 OP_SUB OP_9 OP_ROLL OP_3 OP_PICK OP_11 OP_ROLL OP_CAT OP_CAT OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_OVER OP_IF OP_SWAP OP_1SUB OP_SWAP OP_3 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_ENDIF OP_ENDIF OP_2SWAP OP_DUP OP_NOTIF OP_DROP OP_2SWAP OP_ELSE OP_NIP OP_2SWAP OP_DROP OP_1 OP_ENDIF OP_3 OP_ROLL OP_DUP OP_HASH256 OP_10 OP_ROLL OP_TUCK OP_4 OP_NUM2BIN OP_CAT OP_9 OP_ROLL OP_11 OP_ROLL OP_12 OP_ROLL OP_OVER OP_IF OP_4 OP_NUM2BIN OP_CAT OP_3DUP OP_CAT OP_CAT OP_HASH256 OP_2SWAP OP_SWAP OP_CAT OP_ELSE OP_2DROP OP_2DUP OP_CAT OP_HASH256 OP_SWAP OP_ENDIF OP_ROT OP_CAT OP_HASH256 OP_10 OP_ROLL OP_TUCK OP_EQUAL OP_DUP OP_IF OP_1 OP_ELSE OP_2 OP_ENDIF OP_SWAP OP_2SWAP OP_EQUAL OP_BOOLOR OP_VERIFY OP_3 OP_ROLL OP_NOTIF OP_NOT OP_ENDIF OP_SWAP OP_ROT OP_4 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_OVER OP_3 OP_GREATERTHAN OP_NOT OP_VERIFY 24 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_4 OP_ADD OP_SPLIT OP_NIP OP_OVER OP_1SUB OP_IF 24 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_4 OP_ADD OP_SPLIT OP_NIP OP_OVER OP_2 OP_SUB OP_IF 24 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_4 OP_ADD OP_SPLIT OP_NIP OP_ENDIF OP_ENDIF OP_NIP OP_1 OP_SPLIT OP_SWAP OP_2 OP_PICK OP_TUCK OP_1ADD OP_LESSTHAN OP_SWAP OP_3 OP_GREATERTHAN OP_BOOLOR OP_NOT OP_VERIFY OP_SWAP OP_DUP OP_IF OP_1SUB OP_SWAP OP_8 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_NIP OP_SWAP OP_ENDIF OP_DUP OP_IF OP_1SUB OP_SWAP OP_8 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_NIP OP_SWAP OP_ENDIF OP_IF OP_8 OP_SPLIT OP_NIP OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_NIP OP_ENDIF OP_8 OP_SPLIT OP_1 OP_SPLIT OP_OVER 00 OP_CAT OP_BIN2NUM OP_DUP FC00 OP_GREATERTHAN OP_IF FD00 OP_GREATERTHAN OP_IF OP_4 OP_ELSE OP_2 OP_ENDIF OP_SPLIT OP_OVER 00 OP_CAT OP_BIN2NUM OP_2SWAP OP_CAT OP_ROT OP_ROT OP_ENDIF OP_SPLIT OP_DROP OP_1 OP_SPLIT OP_SWAP 14 OP_TUCK OP_EQUALVERIFY OP_SPLIT OP_1 OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DUP 61 OP_LESSTHAN OP_VERIFY OP_DUP 4e OP_GREATERTHAN OP_IF OP_SWAP OP_ELSE OP_DUP 4b OP_GREATERTHAN OP_IF OP_DUP 4d OP_GREATERTHAN OP_IF OP_DROP OP_4 OP_ELSE 4d OP_NUMEQUAL OP_IF OP_2 OP_ELSE OP_1 OP_ENDIF OP_ENDIF OP_SPLIT OP_SWAP 00 OP_CAT OP_BIN2NUM OP_ENDIF OP_SPLIT OP_ENDIF OP_5 OP_PICK OP_NOTIF OP_7 OP_PICK OP_EQUALVERIFY OP_DROP OP_2DROP OP_ELSE OP_2ROT OP_ENDIF OP_BIN2NUM OP_ENDIF OP_OVER OP_IF OP_6 OP_ROLL OP_ELSE OP_ROT OP_ENDIF OP_8 OP_SPLIT OP_SWAP OP_BIN2NUM OP_3 OP_PICK OP_IF OP_3 OP_PICK OP_2 OP_EQUAL OP_IF OP_ROT OP_TOALTSTACK OP_3 OP_ROLL OP_TOALTSTACK OP_2ROT OP_SWAP OP_TOALTSTACK OP_TOALTSTACK OP_3 OP_ROLL OP_TOALTSTACK OP_ELSE OP_TOALTSTACK OP_7 OP_ROLL OP_TOALTSTACK OP_9 OP_ROLL OP_TOALTSTACK OP_8 OP_ROLL OP_TOALTSTACK OP_7 OP_ROLL OP_TOALTSTACK OP_SWAP OP_ENDIF OP_ELSE OP_ROT OP_ADD OP_ENDIF OP_SWAP OP_4 OP_SPLIT OP_NIP 20 OP_SPLIT OP_DROP OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_VERIFY OP_DUP OP_8 OP_NUM2BIN 4676a914 OP_OVER 14 OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_2SWAP OP_ROT OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_SIZE OP_NOT OP_OVER OP_SIZE OP_1 OP_EQUAL OP_SWAP OP_DUP OP_1NEGATE OP_EQUAL OP_SWAP OP_BIN2NUM OP_1 11 OP_WITHIN OP_BOOLOR OP_BOOLAND OP_BOOLOR OP_NOTIF OP_SIZE OP_DUP 4b OP_LESSTHANOREQUAL OP_NOTIF OP_DUP ff00 OP_LESSTHANOREQUAL OP_IF OP_1 4c OP_ELSE OP_DUP ffff00 OP_LESSTHANOREQUAL OP_IF OP_2 4d OP_ELSE OP_4 4e OP_ENDIF OP_ENDIF OP_ROT OP_ROT OP_SPLIT OP_DROP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_ELSE OP_IFDUP OP_IF 50 OP_ADD OP_ELSE 00 OP_ENDIF OP_ENDIF OP_12 OP_PICK OP_12 OP_PICK OP_IF OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_IFDUP OP_IF OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_IF 20 OP_SPLIT OP_SWAP OP_2 OP_PICK OP_SHA256 OP_EQUAL OP_SWAP 1c OP_SPLIT OP_5 OP_PICK OP_EQUAL OP_SWAP 14 OP_SPLIT OP_DROP OP_6 OP_PICK OP_EQUAL OP_BOOLAND OP_BOOLAND OP_VERIFY OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_ENDIF OP_CAT OP_NIP OP_CAT OP_CAT OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF OP_DUP FFFF00 OP_GREATERTHAN OP_IF fe OP_SWAP OP_SIZE OP_4 OP_ELSE fd OP_SWAP OP_SIZE OP_2 OP_ENDIF OP_TUCK OP_GREATERTHAN OP_IF OP_SPLIT OP_DROP OP_ELSE OP_NUM2BIN OP_ENDIF OP_CAT OP_ELSE OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_SWAP OP_CAT OP_CAT 888201218763ac67517f 517f73637c7f68 OP_DUP OP_DUP OP_CAT OP_DUP OP_CAT OP_CAT ae68 OP_CAT OP_CAT OP_SWAP OP_5 OP_ROLL OP_0 OP_DEPTH 11 OP_GREATERTHAN OP_IF OP_0 OP_10 OP_PICK OP_NOTIF OP_TOALTSTACK OP_SWAP OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_VERIFY OP_TUCK OP_ADD OP_ROT OP_ROT OP_8 OP_NUM2BIN OP_CAT OP_FROMALTSTACK OP_NOT OP_ELSE OP_SWAP OP_DEPTH OP_1SUB OP_ROLL OP_TUCK OP_8 OP_NUM2BIN OP_CAT OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_5 OP_ROLL OP_ENDIF 14 OP_DEPTH OP_1SUB OP_ROLL OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_SIZE OP_NOT OP_OVER OP_SIZE OP_1 OP_EQUAL OP_SWAP OP_DUP OP_1NEGATE OP_EQUAL OP_SWAP OP_BIN2NUM OP_1 11 OP_WITHIN OP_BOOLOR OP_BOOLAND OP_BOOLOR OP_NOTIF OP_SIZE OP_DUP 4b OP_LESSTHANOREQUAL OP_NOTIF OP_DUP ff00 OP_LESSTHANOREQUAL OP_IF OP_1 4c OP_ELSE OP_DUP ffff00 OP_LESSTHANOREQUAL OP_IF OP_2 4d OP_ELSE OP_4 4e OP_ENDIF OP_ENDIF OP_ROT OP_ROT OP_SPLIT OP_DROP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_ELSE OP_IFDUP OP_IF 50 OP_ADD OP_ELSE 00 OP_ENDIF OP_ENDIF OP_4 OP_PICK OP_IF OP_15 OP_PICK OP_ELSE OP_FROMALTSTACK OP_DUP OP_TOALTSTACK 15 OP_PICK OP_IFDUP OP_IF OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_IF 20 OP_SPLIT OP_SWAP OP_2 OP_PICK OP_SHA256 OP_EQUAL OP_SWAP 1c OP_SPLIT OP_5 OP_PICK OP_EQUAL OP_SWAP 14 OP_SPLIT OP_DROP OP_6 OP_PICK OP_EQUAL OP_BOOLAND OP_BOOLAND OP_VERIFY OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_ENDIF OP_CAT OP_NIP OP_CAT OP_CAT OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF OP_DUP FFFF00 OP_GREATERTHAN OP_IF fe OP_SWAP OP_SIZE OP_4 OP_ELSE fd OP_SWAP OP_SIZE OP_2 OP_ENDIF OP_TUCK OP_GREATERTHAN OP_IF OP_SPLIT OP_DROP OP_ELSE OP_NUM2BIN OP_ENDIF OP_CAT OP_ELSE OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_SWAP OP_CAT OP_SWAP OP_IF OP_CAT OP_ELSE OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_CAT OP_SWAP OP_TOALTSTACK OP_ENDIF OP_ENDIF OP_9 OP_PICK OP_IF OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_OVER OP_TOALTSTACK OP_IFDUP OP_IF OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_IF 34 OP_SPLIT OP_NIP OP_4 OP_SPLIT OP_4 OP_SPLIT OP_DROP OP_OVER OP_IF OP_2 OP_PICK OP_ROT 00 OP_CAT OP_BIN2NUM OP_MUL OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DIV OP_3 OP_PICK OP_LESSTHANOREQUAL OP_VERIFY OP_ELSE OP_2DROP OP_ENDIF OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_12 OP_PICK OP_IFDUP OP_IF OP_1 OP_SPLIT OP_SWAP OP_1 OP_EQUAL OP_IF 34 OP_SPLIT OP_NIP OP_4 OP_SPLIT OP_4 OP_SPLIT OP_DROP OP_OVER OP_IF OP_4 OP_PICK OP_ROT 00 OP_CAT OP_BIN2NUM OP_MUL OP_SWAP 00 OP_CAT OP_BIN2NUM OP_DIV OP_OVER OP_LESSTHANOREQUAL OP_VERIFY OP_ELSE OP_2DROP OP_ENDIF OP_ELSE OP_DROP OP_ENDIF OP_ENDIF OP_DROP OP_ENDIF OP_DEPTH 11 OP_GREATERTHAN OP_IF OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_VERIFY OP_TUCK OP_8 OP_NUM2BIN OP_CAT OP_FALSE OP_FALSE OP_12 OP_PICK OP_IF OP_14 OP_PICK OP_DUP OP_SIZE OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_1 OP_EQUAL OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_DUP OP_SIZE OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_1 OP_EQUAL OP_ROT OP_2DUP OP_BOOLOR OP_IF OP_OVER OP_NUMEQUAL OP_IF OP_DROP OP_DEPTH OP_2 OP_SUB OP_PICK OP_ROT OP_OVER OP_EQUAL OP_ROT OP_ROT OP_EQUAL OP_TUCK OP_BOOLOR OP_VERIFY OP_IF OP_SWAP OP_NOT OP_SWAP OP_ENDIF OP_NOT OP_ELSE OP_DEPTH OP_2 OP_SUB OP_PICK OP_SWAP OP_IF OP_EQUAL OP_NIP OP_IF OP_SWAP OP_NOT OP_SWAP OP_NOT OP_ENDIF OP_ELSE OP_NIP OP_EQUAL OP_IF OP_NOT OP_ELSE OP_SWAP OP_NOT OP_SWAP OP_ENDIF OP_ENDIF OP_ENDIF OP_ELSE OP_2DROP OP_2DROP OP_ENDIF OP_ENDIF OP_OVER OP_IF OP_3 OP_ROLL OP_FROMALTSTACK OP_ADD OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_6 OP_ROLL OP_6 OP_ROLL OP_4 OP_PICK OP_4 OP_PICK OP_8 OP_ROLL OP_ELSE OP_TOALTSTACK OP_2SWAP OP_ADD OP_ROT OP_ROT OP_12 OP_PICK OP_14 OP_PICK OP_FROMALTSTACK OP_ENDIF OP_DEPTH OP_1SUB OP_ROLL OP_DEPTH OP_1SUB OP_ROLL OP_ROT OP_IF OP_2DUP OP_2ROT OP_ROT OP_ROT OP_EQUAL OP_ROT OP_ROT OP_EQUAL OP_BOOLAND OP_VERIFY OP_ELSE OP_2SWAP OP_2DROP OP_ENDIF 14 OP_ROT OP_CAT OP_SWAP OP_SIZE OP_NOT OP_OVER OP_SIZE OP_1 OP_EQUAL OP_SWAP OP_DUP OP_1NEGATE OP_EQUAL OP_SWAP OP_BIN2NUM OP_1 11 OP_WITHIN OP_BOOLOR OP_BOOLAND OP_BOOLOR OP_NOTIF OP_SIZE OP_DUP 4b OP_LESSTHANOREQUAL OP_NOTIF OP_DUP ff00 OP_LESSTHANOREQUAL OP_IF OP_1 4c OP_ELSE OP_DUP ffff00 OP_LESSTHANOREQUAL OP_IF OP_2 4d OP_ELSE OP_4 4e OP_ENDIF OP_ENDIF OP_ROT OP_ROT OP_SPLIT OP_DROP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_ELSE OP_IFDUP OP_IF 50 OP_ADD OP_ELSE 00 OP_ENDIF OP_ENDIF OP_CAT OP_SWAP OP_IF OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_CAT OP_2SWAP OP_TOALTSTACK OP_TOALTSTACK OP_2SWAP OP_TOALTSTACK OP_TOALTSTACK OP_ELSE OP_11 OP_PICK OP_CAT OP_ENDIF OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF OP_DUP FFFF00 OP_GREATERTHAN OP_IF fe OP_SWAP OP_SIZE OP_4 OP_ELSE fd OP_SWAP OP_SIZE OP_2 OP_ENDIF OP_TUCK OP_GREATERTHAN OP_IF OP_SPLIT OP_DROP OP_ELSE OP_NUM2BIN OP_ENDIF OP_CAT OP_ELSE OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_SWAP OP_CAT OP_CAT OP_ENDIF OP_DEPTH 11 OP_GREATERTHAN OP_IF OP_DEPTH OP_1SUB OP_ROLL OP_DUP OP_VERIFY OP_TUCK OP_8 OP_NUM2BIN OP_CAT OP_FALSE OP_FALSE OP_12 OP_PICK OP_IF OP_14 OP_PICK OP_DUP OP_SIZE OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_1 OP_EQUAL OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_DUP OP_SIZE OP_IF OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_1 OP_EQUAL OP_ROT OP_2DUP OP_BOOLOR OP_IF OP_OVER OP_NUMEQUAL OP_IF OP_DROP OP_DEPTH OP_2 OP_SUB OP_PICK OP_ROT OP_OVER OP_EQUAL OP_ROT OP_ROT OP_EQUAL OP_TUCK OP_BOOLOR OP_VERIFY OP_IF OP_SWAP OP_NOT OP_SWAP OP_ENDIF OP_NOT OP_ELSE OP_DEPTH OP_2 OP_SUB OP_PICK OP_SWAP OP_IF OP_EQUAL OP_NIP OP_IF OP_SWAP OP_NOT OP_SWAP OP_NOT OP_ENDIF OP_ELSE OP_NIP OP_EQUAL OP_IF OP_NOT OP_ELSE OP_SWAP OP_NOT OP_SWAP OP_ENDIF OP_ENDIF OP_ENDIF OP_ELSE OP_2DROP OP_2DROP OP_ENDIF OP_ENDIF OP_OVER OP_IF OP_3 OP_ROLL OP_FROMALTSTACK OP_ADD OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_6 OP_ROLL OP_6 OP_ROLL OP_4 OP_PICK OP_4 OP_PICK OP_8 OP_ROLL OP_ELSE OP_TOALTSTACK OP_2SWAP OP_ADD OP_ROT OP_ROT OP_12 OP_PICK OP_14 OP_PICK OP_FROMALTSTACK OP_ENDIF OP_DEPTH OP_1SUB OP_ROLL OP_DEPTH OP_1SUB OP_ROLL OP_ROT OP_IF OP_2DUP OP_2ROT OP_ROT OP_ROT OP_EQUAL OP_ROT OP_ROT OP_EQUAL OP_BOOLAND OP_VERIFY OP_ELSE OP_2SWAP OP_2DROP OP_ENDIF 14 OP_ROT OP_CAT OP_SWAP OP_SIZE OP_NOT OP_OVER OP_SIZE OP_1 OP_EQUAL OP_SWAP OP_DUP OP_1NEGATE OP_EQUAL OP_SWAP OP_BIN2NUM OP_1 11 OP_WITHIN OP_BOOLOR OP_BOOLAND OP_BOOLOR OP_NOTIF OP_SIZE OP_DUP 4b OP_LESSTHANOREQUAL OP_NOTIF OP_DUP ff00 OP_LESSTHANOREQUAL OP_IF OP_1 4c OP_ELSE OP_DUP ffff00 OP_LESSTHANOREQUAL OP_IF OP_2 4d OP_ELSE OP_4 4e OP_ENDIF OP_ENDIF OP_ROT OP_ROT OP_SPLIT OP_DROP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_ELSE OP_IFDUP OP_IF 50 OP_ADD OP_ELSE 00 OP_ENDIF OP_ENDIF OP_CAT OP_SWAP OP_IF OP_FROMALTSTACK OP_DUP OP_TOALTSTACK OP_CAT OP_2SWAP OP_TOALTSTACK OP_TOALTSTACK OP_2SWAP OP_TOALTSTACK OP_TOALTSTACK OP_ELSE OP_11 OP_PICK OP_CAT OP_ENDIF OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF OP_DUP FFFF00 OP_GREATERTHAN OP_IF fe OP_SWAP OP_SIZE OP_4 OP_ELSE fd OP_SWAP OP_SIZE OP_2 OP_ENDIF OP_TUCK OP_GREATERTHAN OP_IF OP_SPLIT OP_DROP OP_ELSE OP_NUM2BIN OP_ENDIF OP_CAT OP_ELSE OP_1 OP_SPLIT OP_DROP OP_ENDIF OP_SWAP OP_CAT OP_CAT OP_ENDIF OP_9 OP_ROLL OP_IF OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_2DROP OP_FROMALTSTACK OP_FROMALTSTACK OP_2DROP OP_FROMALTSTACK OP_NUMEQUALVERIFY OP_ENDIF OP_SWAP OP_8 OP_ROLL OP_NUMEQUALVERIFY OP_TUCK OP_CAT OP_12 OP_PICK OP_IF OP_13 OP_PICK OP_8 OP_NUM2BIN 1976a914 OP_14 OP_PICK OP_CAT 88ac OP_CAT OP_CAT OP_ELSE OP_0 OP_ENDIF OP_TUCK OP_CAT OP_12 OP_ROLL OP_DUP OP_IF 006A OP_SWAP OP_CAT OP_SIZE OP_DUP FC00 OP_GREATERTHAN OP_IF fd OP_SWAP OP_CAT OP_3 OP_ELSE OP_1 OP_ENDIF OP_SPLIT OP_DROP OP_SWAP OP_CAT OP_0 OP_8 OP_NUM2BIN OP_SWAP OP_CAT OP_ENDIF OP_TUCK OP_CAT OP_HASH256 OP_TOALTSTACK OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_CAT OP_HASH256 OP_OVER OP_EQUAL OP_SWAP OP_FROMALTSTACK OP_EQUAL OP_SWAP OP_FROMALTSTACK OP_BOOLAND OP_BOOLOR OP_2SWAP OP_2DROP OP_2SWAP OP_2DROP OP_NIP OP_NIP OP_RETURN <"redemption address"/"protocol ID" - 20 bytes> +`; +//# sourceMappingURL=dstas-locking-template.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.js.map b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.js.map new file mode 100644 index 0000000..ebace8b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/script/templates/dstas-locking-template.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dstas-locking-template.js","sourceRoot":"","sources":["../../../src/script/templates/dstas-locking-template.ts"],"names":[],"mappings":";;;AAAa,QAAA,0BAA0B,GAAG;;CAEzC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.d.ts b/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.d.ts new file mode 100644 index 0000000..0a8ae55 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.d.ts @@ -0,0 +1,21 @@ +export type StrictScriptEvaluationLimits = { + maxScriptSizeBytes: number; + maxOps: number; + maxStackDepth: number; + maxElementSizeBytes: number; +}; +export type StrictModeConfig = { + strictTxParse: boolean; + strictOutPointValidation: boolean; + strictFeeRateValidation: boolean; + maxFeeRateSatsPerByte: number; + strictPresetUnlockingScript: boolean; + strictMultisigKeys: boolean; + strictScriptReader: boolean; + strictScriptEvaluation: boolean; + scriptEvaluationLimits: StrictScriptEvaluationLimits; +}; +export declare const getStrictModeConfig: () => StrictModeConfig; +export declare const configureStrictMode: (patch: Partial) => StrictModeConfig; +export declare const resetStrictMode: () => StrictModeConfig; +//# sourceMappingURL=strict-mode.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.d.ts.map new file mode 100644 index 0000000..7501b82 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"strict-mode.d.ts","sourceRoot":"","sources":["../../src/security/strict-mode.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,4BAA4B,GAAG;IACzC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,wBAAwB,EAAE,OAAO,CAAC;IAClC,uBAAuB,EAAE,OAAO,CAAC;IACjC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,2BAA2B,EAAE,OAAO,CAAC;IACrC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,sBAAsB,EAAE,OAAO,CAAC;IAChC,sBAAsB,EAAE,4BAA4B,CAAC;CACtD,CAAC;AA0BF,eAAO,MAAM,mBAAmB,QAAO,gBAAoC,CAAC;AAE5E,eAAO,MAAM,mBAAmB,GAC9B,OAAO,OAAO,CAAC,gBAAgB,CAAC,KAC/B,gBAWF,CAAC;AAEF,eAAO,MAAM,eAAe,QAAO,gBASlC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.js b/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.js new file mode 100644 index 0000000..e28faad --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.resetStrictMode = exports.configureStrictMode = exports.getStrictModeConfig = void 0; +const defaultStrictModeConfig = { + strictTxParse: true, + strictOutPointValidation: true, + strictFeeRateValidation: true, + maxFeeRateSatsPerByte: 1000, + strictPresetUnlockingScript: false, + strictMultisigKeys: false, + strictScriptReader: true, + strictScriptEvaluation: true, + scriptEvaluationLimits: { + maxScriptSizeBytes: 100000, + maxOps: 50000, + maxStackDepth: 1000, + maxElementSizeBytes: 1024 * 1024, + }, +}; +let strictModeConfig = Object.assign(Object.assign({}, defaultStrictModeConfig), { scriptEvaluationLimits: Object.assign({}, defaultStrictModeConfig.scriptEvaluationLimits) }); +const getStrictModeConfig = () => strictModeConfig; +exports.getStrictModeConfig = getStrictModeConfig; +const configureStrictMode = (patch) => { + var _a; + strictModeConfig = Object.assign(Object.assign(Object.assign({}, strictModeConfig), patch), { scriptEvaluationLimits: Object.assign(Object.assign({}, strictModeConfig.scriptEvaluationLimits), ((_a = patch.scriptEvaluationLimits) !== null && _a !== void 0 ? _a : {})) }); + return strictModeConfig; +}; +exports.configureStrictMode = configureStrictMode; +const resetStrictMode = () => { + strictModeConfig = Object.assign(Object.assign({}, defaultStrictModeConfig), { scriptEvaluationLimits: Object.assign({}, defaultStrictModeConfig.scriptEvaluationLimits) }); + return strictModeConfig; +}; +exports.resetStrictMode = resetStrictMode; +//# sourceMappingURL=strict-mode.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.js.map b/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.js.map new file mode 100644 index 0000000..8b04f3b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/security/strict-mode.js.map @@ -0,0 +1 @@ +{"version":3,"file":"strict-mode.js","sourceRoot":"","sources":["../../src/security/strict-mode.ts"],"names":[],"mappings":";;;AAmBA,MAAM,uBAAuB,GAAqB;IAChD,aAAa,EAAE,IAAI;IACnB,wBAAwB,EAAE,IAAI;IAC9B,uBAAuB,EAAE,IAAI;IAC7B,qBAAqB,EAAE,IAAI;IAC3B,2BAA2B,EAAE,KAAK;IAClC,kBAAkB,EAAE,KAAK;IACzB,kBAAkB,EAAE,IAAI;IACxB,sBAAsB,EAAE,IAAI;IAC5B,sBAAsB,EAAE;QACtB,kBAAkB,EAAE,MAAM;QAC1B,MAAM,EAAE,KAAK;QACb,aAAa,EAAE,IAAI;QAGnB,mBAAmB,EAAE,IAAI,GAAG,IAAI;KACjC;CACF,CAAC;AAEF,IAAI,gBAAgB,mCACf,uBAAuB,KAC1B,sBAAsB,oBAAO,uBAAuB,CAAC,sBAAsB,IAC5E,CAAC;AAEK,MAAM,mBAAmB,GAAG,GAAqB,EAAE,CAAC,gBAAgB,CAAC;AAA/D,QAAA,mBAAmB,uBAA4C;AAErE,MAAM,mBAAmB,GAAG,CACjC,KAAgC,EACd,EAAE;;IACpB,gBAAgB,iDACX,gBAAgB,GAChB,KAAK,KACR,sBAAsB,kCACjB,gBAAgB,CAAC,sBAAsB,GACvC,CAAC,MAAA,KAAK,CAAC,sBAAsB,mCAAI,EAAE,CAAC,IAE1C,CAAC;IAEF,OAAO,gBAAgB,CAAC;AAC1B,CAAC,CAAC;AAbW,QAAA,mBAAmB,uBAa9B;AAEK,MAAM,eAAe,GAAG,GAAqB,EAAE;IACpD,gBAAgB,mCACX,uBAAuB,KAC1B,sBAAsB,oBACjB,uBAAuB,CAAC,sBAAsB,IAEpD,CAAC;IAEF,OAAO,gBAAgB,CAAC;AAC1B,CAAC,CAAC;AATW,QAAA,eAAe,mBAS1B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.d.ts b/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.d.ts new file mode 100644 index 0000000..122dc17 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.d.ts @@ -0,0 +1,35 @@ +import { Address, OutPoint, TokenScheme, Transaction, Wallet } from "./bitcoin"; +import { Bytes } from "./bytes"; +export declare const AvgFeeForMerge = 500; +export type TFundingUtxoRequest = { + utxoIdsToSpend: string[]; + estimatedFeeSatoshis: number; + transactionsCount: number; +}; +export type TGetUtxoFunction = (satoshis?: number) => Promise; +export type TGetFundingUtxoFunction = (request: TFundingUtxoRequest) => Promise; +export type TGetTransactionsFunction = (ids: string[]) => Promise>; +export type TStasPayoutBundle = { + transactions?: string[]; + feeSatoshis: number; + message?: string; + devMessage?: string; +}; +export declare class StasBundleFactory { + private readonly tokenScheme; + private readonly stasWallet; + private readonly feeWallet; + private readonly getFundingUtxo; + private readonly getStasUtxoSet; + private readonly getTransactions; + constructor(tokenScheme: TokenScheme, stasWallet: Wallet, feeWallet: Wallet, getFundingUtxo: TGetFundingUtxoFunction, getStasUtxoSet: TGetUtxoFunction, getTransactions: TGetTransactionsFunction); + createBundle: (amountSatoshis: number, to: Address, note?: Bytes[]) => Promise; + private buildFeeProbeOutPoint; + private _createBundle; + private getStasUtxo; + private buildFeeTransaction; + private mergeStasTransactions; + private buildTransferTransaction; + private buildSplitTransaction; +} +//# sourceMappingURL=stas-bundle-factory.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.d.ts.map new file mode 100644 index 0000000..1f5006c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"stas-bundle-factory.d.ts","sourceRoot":"","sources":["../src/stas-bundle-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,QAAQ,EAGR,WAAW,EAEX,WAAW,EACX,MAAM,EACP,MAAM,WAAW,CAAC;AAQnB,OAAO,EAAE,KAAK,EAAS,MAAM,SAAS,CAAC;AAIvC,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC1E,MAAM,MAAM,uBAAuB,GAAG,CACpC,OAAO,EAAE,mBAAmB,KACzB,OAAO,CAAC,QAAQ,CAAC,CAAC;AACvB,MAAM,MAAM,wBAAwB,GAAG,CACrC,GAAG,EAAE,MAAM,EAAE,KACV,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AAC1C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe;gBALf,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,uBAAuB,EACvC,cAAc,EAAE,gBAAgB,EAChC,eAAe,EAAE,wBAAwB;IAGrD,YAAY,GACjB,gBAAgB,MAAM,EACtB,IAAI,OAAO,EACX,OAAO,KAAK,EAAE,KACb,OAAO,CAAC,iBAAiB,CAAC,CAmD3B;IAMF,OAAO,CAAC,qBAAqB,CAY3B;IAEF,OAAO,CAAC,aAAa,CA0CnB;IAEF,OAAO,CAAC,WAAW,CAiBjB;IAEF,OAAO,CAAC,mBAAmB,CAoCzB;IAEF,OAAO,CAAC,qBAAqB,CAyH3B;IAEF,OAAO,CAAC,wBAAwB,CAa3B;IAEL,OAAO,CAAC,qBAAqB,CAoBxB;CACN"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.js b/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.js new file mode 100644 index 0000000..231d99a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.js @@ -0,0 +1,226 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.StasBundleFactory = exports.AvgFeeForMerge = void 0; +const bitcoin_1 = require("./bitcoin"); +const transaction_1 = require("./transaction"); +const transaction_factory_1 = require("./transaction-factory"); +const bytes_1 = require("./bytes"); +const hashes_1 = require("./hashes"); +const p2pkh_builder_1 = require("./script/build/p2pkh-builder"); +exports.AvgFeeForMerge = 500; +class StasBundleFactory { + constructor(tokenScheme, stasWallet, feeWallet, getFundingUtxo, getStasUtxoSet, getTransactions) { + this.tokenScheme = tokenScheme; + this.stasWallet = stasWallet; + this.feeWallet = feeWallet; + this.getFundingUtxo = getFundingUtxo; + this.getStasUtxoSet = getStasUtxoSet; + this.getTransactions = getTransactions; + this.createBundle = (amountSatoshis, to, note) => __awaiter(this, void 0, void 0, function* () { + const stasUtxoSet = (yield this.getStasUtxoSet(amountSatoshis)).sort((a, b) => a.Satoshis - b.Satoshis); + const availableSatoshis = stasUtxoSet.reduce((a, x) => a + x.Satoshis, 0); + if (availableSatoshis < amountSatoshis) + return { + message: "Insufficient STAS tokens balance", + feeSatoshis: 0, + }; + const stasUtxos = this.getStasUtxo(stasUtxoSet, amountSatoshis); + const { feeSatoshis: estimatedFee, transactions: { length: transactionsCount }, } = yield this._createBundle([], stasUtxos, amountSatoshis, this.buildFeeProbeOutPoint(), to, note); + const adjustedEstimatedFee = estimatedFee + stasUtxos.length * 9 + 1; + const fudingUtxo = yield this.getFundingUtxo({ + utxoIdsToSpend: stasUtxos.map((x) => `${x.TxId}:${x.Vout}`), + estimatedFeeSatoshis: adjustedEstimatedFee + 1, + transactionsCount, + }); + const transactions = []; + return this._createBundle(transactions, stasUtxos, amountSatoshis, fudingUtxo, to, note); + }); + this.buildFeeProbeOutPoint = () => { + const probeTxId = (0, bytes_1.toHex)((0, hashes_1.hash256)(this.feeWallet.PublicKey)); + const probeScript = new p2pkh_builder_1.P2pkhBuilder(this.feeWallet.Address).toBytes(); + return new bitcoin_1.OutPoint(probeTxId, 0, probeScript, 5000000000, this.feeWallet.Address, bitcoin_1.ScriptType.p2pkh); + }; + this._createBundle = (transactions, stasUtxos, satoshisToSend, feeUtxo, to, note) => __awaiter(this, void 0, void 0, function* () { + const { mergeTransactions, mergeFeeUtxo, stasUtxo } = yield this.mergeStasTransactions(stasUtxos, satoshisToSend, feeUtxo); + if (mergeTransactions) { + for (const mergeTx of mergeTransactions) { + transactions.push(mergeTx); + } + } + if (stasUtxo.Satoshis === satoshisToSend) { + transactions.push(this.buildTransferTransaction(stasUtxo, mergeFeeUtxo, to, note)); + } + else { + transactions.push(this.buildSplitTransaction(stasUtxo, satoshisToSend, to, mergeFeeUtxo, note)); + } + const transferTx = transaction_1.TransactionReader.readHex(transactions[transactions.length - 1]); + const feeUtxoIdx = note + ? transferTx.Outputs.length - 2 + : transferTx.Outputs.length - 1; + const paidFee = feeUtxo.Satoshis - transferTx.Outputs[feeUtxoIdx].Satoshis; + return { transactions, feeSatoshis: paidFee }; + }); + this.getStasUtxo = (utxos, satoshis) => { + const exactOrGreater = utxos.find((x) => x.Satoshis >= satoshis); + if (exactOrGreater && exactOrGreater.Satoshis === satoshis) { + return [exactOrGreater]; + } + const result = []; + let accumulated = 0; + for (const utxo of utxos) { + result.push(utxo); + accumulated += utxo.Satoshis; + if (accumulated >= satoshis) + return result; + } + return [exactOrGreater]; + }; + this.buildFeeTransaction = (utxos, satoshis) => { + if (utxos.length === 1) + return { + feeUtxo: utxos[0], + }; + const txBuilder = transaction_1.TransactionBuilder.init().addP2PkhOutput(0, this.feeWallet.Address); + let accumulated = 0; + for (const utxo of utxos) { + txBuilder.addInput(utxo, this.feeWallet); + const fee = txBuilder.getFee(transaction_factory_1.FeeRate); + accumulated += utxo.Satoshis; + if (accumulated - fee >= satoshis) + break; + } + txBuilder.Outputs = []; + const result = txBuilder + .addChangeOutputWithFee(this.feeWallet.Address, accumulated, transaction_factory_1.FeeRate) + .sign() + .toHex(); + return { feeTransaction: result, feeUtxo: bitcoin_1.OutPoint.fromHex(result, 0) }; + }; + this.mergeStasTransactions = (stasUtxos, satoshis, mergeFeeUtxo) => __awaiter(this, void 0, void 0, function* () { + if (stasUtxos.length === 1) + return { mergeFeeUtxo, stasUtxo: stasUtxos[0] }; + const mergeTransactions = []; + const utxos = stasUtxos.map(({ TxId, Vout }) => ({ TxId, Vout })); + const txIds = Array.from(new Set(stasUtxos.map(({ TxId }) => TxId))); + const sourceTransactions = yield this.getTransactions(txIds); + const mergeLevels = [[]]; + for (const { TxId, Vout } of utxos) { + const tx = sourceTransactions[TxId]; + if (!tx) + throw new Error(`Transaction ${TxId} not found`); + mergeLevels[0].push(bitcoin_1.OutPoint.fromTransaction(tx, Vout)); + } + const feePayment = { + OutPoint: mergeFeeUtxo, + Owner: this.feeWallet, + }; + let currentLevel = mergeLevels[0]; + let levelsBeforeTransfer = 0; + let stasUtxo = stasUtxos[0]; + while (currentLevel.length !== 1) { + const newLevel = []; + mergeLevels.push(newLevel); + if (levelsBeforeTransfer === 3) { + levelsBeforeTransfer = 0; + for (const outPoint of currentLevel) { + const stasPayment = { + OutPoint: outPoint, + Owner: this.stasWallet, + }; + const txRaw = (0, transaction_factory_1.BuildTransferTx)({ + tokenScheme: this.tokenScheme, + stasPayment, + feePayment, + to: this.stasWallet.Address, + feeRate: transaction_factory_1.FeeRate, + }); + const tx = transaction_1.TransactionReader.readHex(txRaw); + newLevel.push(bitcoin_1.OutPoint.fromTransaction(tx, 0)); + mergeTransactions.push(txRaw); + stasUtxo = bitcoin_1.OutPoint.fromTransaction(tx, 0); + feePayment.OutPoint = bitcoin_1.OutPoint.fromTransaction(tx, 1); + } + } + else { + levelsBeforeTransfer++; + const mergeCounts = Math.floor(currentLevel.length / 2); + const remainder = currentLevel.length % 2; + if (remainder !== 0) + newLevel.push(currentLevel[currentLevel.length - 1]); + let currentIdx = 0; + for (let i = 0; i < mergeCounts; i++) { + const outPoint1 = currentLevel[currentIdx++]; + const outPoint2 = currentLevel[currentIdx++]; + const lastMerge = mergeCounts === 1 && remainder === 0; + const inputSatoshis = outPoint1.Satoshis + outPoint2.Satoshis; + let destination = { + Address: this.stasWallet.Address, + Satoshis: inputSatoshis, + }; + let splitDestination; + if (lastMerge && inputSatoshis !== satoshis) { + destination = { + Address: this.stasWallet.Address, + Satoshis: satoshis, + }; + splitDestination = { + Address: this.stasWallet.Address, + Satoshis: inputSatoshis - satoshis, + }; + } + const txRaw = (0, transaction_factory_1.BuildMergeTx)({ + tokenScheme: this.tokenScheme, + outPoint1, + outPoint2, + owner: this.stasWallet, + feePayment, + destination, + splitDestination, + feeRate: transaction_factory_1.FeeRate, + }); + const tx = transaction_1.TransactionReader.readHex(txRaw); + newLevel.push(bitcoin_1.OutPoint.fromTransaction(tx, 0)); + mergeTransactions.push(txRaw); + stasUtxo = bitcoin_1.OutPoint.fromTransaction(tx, 0); + feePayment.OutPoint = bitcoin_1.OutPoint.fromTransaction(tx, tx.Outputs.length - 1); + } + } + currentLevel = newLevel; + } + return { mergeTransactions, mergeFeeUtxo: feePayment.OutPoint, stasUtxo }; + }); + this.buildTransferTransaction = (stasUtxo, feeUtxo, to, note) => (0, transaction_factory_1.BuildTransferTx)({ + tokenScheme: this.tokenScheme, + stasPayment: { OutPoint: stasUtxo, Owner: this.stasWallet }, + feePayment: { OutPoint: feeUtxo, Owner: this.feeWallet }, + to, + note, + feeRate: transaction_factory_1.FeeRate, + }); + this.buildSplitTransaction = (stasUtxo, satoshis, to, feeUtxo, note) => (0, transaction_factory_1.BuildSplitTx)({ + tokenScheme: this.tokenScheme, + stasPayment: { OutPoint: stasUtxo, Owner: this.stasWallet }, + feePayment: { OutPoint: feeUtxo, Owner: this.feeWallet }, + destinations: [ + { Satoshis: satoshis, Address: to }, + { + Satoshis: stasUtxo.Satoshis - satoshis, + Address: this.stasWallet.Address, + }, + ], + note, + feeRate: transaction_factory_1.FeeRate, + }); + } +} +exports.StasBundleFactory = StasBundleFactory; +//# sourceMappingURL=stas-bundle-factory.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.js.map b/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.js.map new file mode 100644 index 0000000..617f1fc --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/stas-bundle-factory.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stas-bundle-factory.js","sourceRoot":"","sources":["../src/stas-bundle-factory.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,uCASmB;AACnB,+CAAsE;AACtE,+DAK+B;AAC/B,mCAAuC;AACvC,qCAAmC;AACnC,gEAA4D;AAE/C,QAAA,cAAc,GAAG,GAAG,CAAC;AAqBlC,MAAa,iBAAiB;IAC5B,YACmB,WAAwB,EACxB,UAAkB,EAClB,SAAiB,EACjB,cAAuC,EACvC,cAAgC,EAChC,eAAyC;QALzC,gBAAW,GAAX,WAAW,CAAa;QACxB,eAAU,GAAV,UAAU,CAAQ;QAClB,cAAS,GAAT,SAAS,CAAQ;QACjB,mBAAc,GAAd,cAAc,CAAyB;QACvC,mBAAc,GAAd,cAAc,CAAkB;QAChC,oBAAe,GAAf,eAAe,CAA0B;QAGrD,iBAAY,GAAG,CACpB,cAAsB,EACtB,EAAW,EACX,IAAc,EACc,EAAE;YAC9B,MAAM,WAAW,GAAG,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAClE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAClC,CAAC;YACF,MAAM,iBAAiB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAE1E,IAAI,iBAAiB,GAAG,cAAc;gBACpC,OAAO;oBACL,OAAO,EAAE,kCAAkC;oBAC3C,WAAW,EAAE,CAAC;iBACf,CAAC;YAEJ,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAChE,MAAM,EACJ,WAAW,EAAE,YAAY,EACzB,YAAY,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,GAC5C,GAAG,MAAM,IAAI,CAAC,aAAa,CAC1B,EAAE,EACF,SAAS,EACT,cAAc,EACd,IAAI,CAAC,qBAAqB,EAAE,EAC5B,EAAE,EACF,IAAI,CACL,CAAC;YAEF,MAAM,oBAAoB,GACxB,YAAY,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC;gBAC3C,cAAc,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,oBAAoB,EAAE,oBAAoB,GAAG,CAAC;gBAC9C,iBAAiB;aAClB,CAAC,CAAC;YAUH,MAAM,YAAY,GAAa,EAAE,CAAC;YAElC,OAAO,IAAI,CAAC,aAAa,CACvB,YAAY,EACZ,SAAS,EACT,cAAc,EACd,UAAU,EACV,EAAE,EACF,IAAI,CACL,CAAC;QACJ,CAAC,CAAA,CAAC;QAMM,0BAAqB,GAAG,GAAa,EAAE;YAC7C,MAAM,SAAS,GAAG,IAAA,aAAK,EAAC,IAAA,gBAAO,EAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;YAC3D,MAAM,WAAW,GAAG,IAAI,4BAAY,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;YAEvE,OAAO,IAAI,kBAAQ,CACjB,SAAS,EACT,CAAC,EACD,WAAW,EACX,UAAa,EACb,IAAI,CAAC,SAAS,CAAC,OAAO,EACtB,oBAAU,CAAC,KAAK,CACjB,CAAC;QACJ,CAAC,CAAC;QAEM,kBAAa,GAAG,CACtB,YAAsB,EACtB,SAAqB,EACrB,cAAsB,EACtB,OAAiB,EACjB,EAAW,EACX,IAAc,EACd,EAAE;YACF,MAAM,EAAE,iBAAiB,EAAE,YAAY,EAAE,QAAQ,EAAE,GACjD,MAAM,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;YAEvE,IAAI,iBAAiB,EAAE,CAAC;gBACtB,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;oBACxC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;YAED,IAAI,QAAQ,CAAC,QAAQ,KAAK,cAAc,EAAE,CAAC;gBACzC,YAAY,CAAC,IAAI,CACf,IAAI,CAAC,wBAAwB,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,IAAI,CAAC,CAChE,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,YAAY,CAAC,IAAI,CACf,IAAI,CAAC,qBAAqB,CACxB,QAAQ,EACR,cAAc,EACd,EAAE,EACF,YAAY,EACZ,IAAI,CACL,CACF,CAAC;YACJ,CAAC;YAED,MAAM,UAAU,GAAG,+BAAiB,CAAC,OAAO,CAC1C,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CACtC,CAAC;YACF,MAAM,UAAU,GAAG,IAAI;gBACrB,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBAC/B,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;YAClC,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC;YAE3E,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;QAChD,CAAC,CAAA,CAAC;QAEM,gBAAW,GAAG,CAAC,KAAiB,EAAE,QAAgB,EAAc,EAAE;YACxE,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC;YAEjE,IAAI,cAAc,IAAI,cAAc,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC3D,OAAO,CAAC,cAAc,CAAC,CAAC;YAC1B,CAAC;YAED,MAAM,MAAM,GAAe,EAAE,CAAC;YAC9B,IAAI,WAAW,GAAG,CAAC,CAAC;YACpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClB,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC;gBAE7B,IAAI,WAAW,IAAI,QAAQ;oBAAE,OAAO,MAAM,CAAC;YAC7C,CAAC;YAED,OAAO,CAAC,cAAe,CAAC,CAAC;QAC3B,CAAC,CAAC;QAEM,wBAAmB,GAAG,CAC5B,KAAiB,EACjB,QAAgB,EAIhB,EAAE;YACF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBACpB,OAAO;oBACL,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;iBAClB,CAAC;YAEJ,MAAM,SAAS,GAAG,gCAAkB,CAAC,IAAI,EAAE,CAAC,cAAc,CACxD,CAAC,EACD,IAAI,CAAC,SAAS,CAAC,OAAO,CACvB,CAAC;YACF,IAAI,WAAW,GAAG,CAAC,CAAC;YAEpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBAEzC,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,6BAAO,CAAC,CAAC;gBAEtC,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC;gBAE7B,IAAI,WAAW,GAAG,GAAG,IAAI,QAAQ;oBAAE,MAAM;YAC3C,CAAC;YAED,SAAS,CAAC,OAAO,GAAG,EAAE,CAAC;YAEvB,MAAM,MAAM,GAAG,SAAS;iBACrB,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,6BAAO,CAAC;iBACpE,IAAI,EAAE;iBACN,KAAK,EAAE,CAAC;YAEX,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;QAC1E,CAAC,CAAC;QAEM,0BAAqB,GAAG,CAC9B,SAAqB,EACrB,QAAgB,EAChB,YAAsB,EAKrB,EAAE;YACH,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAE5E,MAAM,iBAAiB,GAAa,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACrE,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAC7D,MAAM,WAAW,GAAiB,CAAC,EAAE,CAAC,CAAC;YAEvC,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;gBACnC,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;gBAEpC,IAAI,CAAC,EAAE;oBAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,YAAY,CAAC,CAAC;gBAE1D,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;YAC1D,CAAC;YAED,MAAM,UAAU,GAAa;gBAC3B,QAAQ,EAAE,YAAY;gBACtB,KAAK,EAAE,IAAI,CAAC,SAAS;aACtB,CAAC;YACF,IAAI,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,oBAAoB,GAAG,CAAC,CAAC;YAC7B,IAAI,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAE5B,OAAO,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjC,MAAM,QAAQ,GAAe,EAAE,CAAC;gBAChC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAE3B,IAAI,oBAAoB,KAAK,CAAC,EAAE,CAAC;oBAC/B,oBAAoB,GAAG,CAAC,CAAC;oBAEzB,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;wBACpC,MAAM,WAAW,GAAa;4BAC5B,QAAQ,EAAE,QAAQ;4BAClB,KAAK,EAAE,IAAI,CAAC,UAAU;yBACvB,CAAC;wBACF,MAAM,KAAK,GAAG,IAAA,qCAAe,EAAC;4BAC5B,WAAW,EAAE,IAAI,CAAC,WAAW;4BAC7B,WAAW;4BACX,UAAU;4BACV,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO;4BAC3B,OAAO,EAAE,6BAAO;yBACjB,CAAC,CAAC;wBACH,MAAM,EAAE,GAAG,+BAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;wBAE5C,QAAQ,CAAC,IAAI,CAAC,kBAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;wBAC/C,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;wBAE9B,QAAQ,GAAG,kBAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;wBAC3C,UAAU,CAAC,QAAQ,GAAG,kBAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;oBACxD,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,oBAAoB,EAAE,CAAC;oBAEvB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBACxD,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;oBAE1C,IAAI,SAAS,KAAK,CAAC;wBACjB,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;oBAEvD,IAAI,UAAU,GAAG,CAAC,CAAC;oBAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;wBACrC,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC;wBAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC;wBAC7C,MAAM,SAAS,GAAG,WAAW,KAAK,CAAC,IAAI,SAAS,KAAK,CAAC,CAAC;wBACvD,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC;wBAE9D,IAAI,WAAW,GAAiB;4BAC9B,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO;4BAChC,QAAQ,EAAE,aAAa;yBACxB,CAAC;wBACF,IAAI,gBAA0C,CAAC;wBAE/C,IAAI,SAAS,IAAI,aAAa,KAAK,QAAQ,EAAE,CAAC;4BAC5C,WAAW,GAAG;gCACZ,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO;gCAChC,QAAQ,EAAE,QAAQ;6BACnB,CAAC;4BACF,gBAAgB,GAAG;gCACjB,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO;gCAChC,QAAQ,EAAE,aAAa,GAAG,QAAQ;6BACnC,CAAC;wBACJ,CAAC;wBAED,MAAM,KAAK,GAAG,IAAA,kCAAY,EAAC;4BACzB,WAAW,EAAE,IAAI,CAAC,WAAW;4BAC7B,SAAS;4BACT,SAAS;4BACT,KAAK,EAAE,IAAI,CAAC,UAAU;4BACtB,UAAU;4BACV,WAAW;4BACX,gBAAgB;4BAChB,OAAO,EAAE,6BAAO;yBACjB,CAAC,CAAC;wBACH,MAAM,EAAE,GAAG,+BAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;wBAE5C,QAAQ,CAAC,IAAI,CAAC,kBAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;wBAC/C,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;wBAE9B,QAAQ,GAAG,kBAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;wBAC3C,UAAU,CAAC,QAAQ,GAAG,kBAAQ,CAAC,eAAe,CAC5C,EAAE,EACF,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CACtB,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAED,YAAY,GAAG,QAAQ,CAAC;YAC1B,CAAC;YAED,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC;QAC5E,CAAC,CAAA,CAAC;QAEM,6BAAwB,GAAG,CACjC,QAAkB,EAClB,OAAiB,EACjB,EAAW,EACX,IAAc,EACN,EAAE,CACV,IAAA,qCAAe,EAAC;YACd,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE;YAC3D,UAAU,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE;YACxD,EAAE;YACF,IAAI;YACJ,OAAO,EAAE,6BAAO;SACjB,CAAC,CAAC;QAEG,0BAAqB,GAAG,CAC9B,QAAkB,EAClB,QAAgB,EAChB,EAAW,EACX,OAAiB,EACjB,IAAc,EACN,EAAE,CACV,IAAA,kCAAY,EAAC;YACX,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE;YAC3D,UAAU,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE;YACxD,YAAY,EAAE;gBACZ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;gBACnC;oBACE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ;oBACtC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO;iBACjC;aACF;YACD,IAAI;YACJ,OAAO,EAAE,6BAAO;SACjB,CAAC,CAAC;IAhVF,CAAC;CAiVL;AAzVD,8CAyVC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/stas.d.ts b/vendor/dxs-bsv-token-sdk/dist/stas.d.ts new file mode 100644 index 0000000..d8ed0ad --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/stas.d.ts @@ -0,0 +1,3 @@ +export * from "./transaction-factory"; +export { AvgFeeForMerge, TFundingUtxoRequest, TGetUtxoFunction, TGetFundingUtxoFunction, TGetTransactionsFunction, TStasPayoutBundle, StasBundleFactory, } from "./stas-bundle-factory"; +//# sourceMappingURL=stas.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/stas.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/stas.d.ts.map new file mode 100644 index 0000000..cbac835 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/stas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"stas.d.ts","sourceRoot":"","sources":["../src/stas.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/stas.js b/vendor/dxs-bsv-token-sdk/dist/stas.js new file mode 100644 index 0000000..3f073e4 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/stas.js @@ -0,0 +1,22 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.StasBundleFactory = exports.AvgFeeForMerge = void 0; +__exportStar(require("./transaction-factory"), exports); +var stas_bundle_factory_1 = require("./stas-bundle-factory"); +Object.defineProperty(exports, "AvgFeeForMerge", { enumerable: true, get: function () { return stas_bundle_factory_1.AvgFeeForMerge; } }); +Object.defineProperty(exports, "StasBundleFactory", { enumerable: true, get: function () { return stas_bundle_factory_1.StasBundleFactory; } }); +//# sourceMappingURL=stas.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/stas.js.map b/vendor/dxs-bsv-token-sdk/dist/stas.js.map new file mode 100644 index 0000000..d1c94af --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/stas.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stas.js","sourceRoot":"","sources":["../src/stas.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,wDAAsC;AACtC,6DAQ+B;AAP7B,qHAAA,cAAc,OAAA;AAMd,wHAAA,iBAAiB,OAAA"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction-factory.d.ts b/vendor/dxs-bsv-token-sdk/dist/transaction-factory.d.ts new file mode 100644 index 0000000..a851e08 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction-factory.d.ts @@ -0,0 +1,43 @@ +import { Address, OutPointFull, PrivateKey, TDestination, TokenScheme, TPayment, Wallet } from "./bitcoin"; +import { Bytes } from "./bytes"; +export declare const FeeRate = 0.1; +export type TBuildTransferTxRequest = { + tokenScheme: TokenScheme; + stasPayment: TPayment; + feePayment: TPayment; + to: Address; + note?: Bytes[]; + feeRate: number; +}; +export declare const BuildTransferTx: ({ tokenScheme, stasPayment, feePayment, to, note, feeRate, }: TBuildTransferTxRequest) => string; +export type TBuildSplitTxRequest = { + tokenScheme: TokenScheme; + stasPayment: TPayment; + feePayment: TPayment; + destinations: TDestination[]; + note?: Bytes[]; + feeRate: number; +}; +export declare const BuildSplitTx: ({ tokenScheme, stasPayment, feePayment, destinations, note, feeRate, }: TBuildSplitTxRequest) => string; +export type TBuildMergeTxRequest = { + tokenScheme: TokenScheme; + outPoint1: OutPointFull; + outPoint2: OutPointFull; + owner: PrivateKey | Wallet; + feePayment: TPayment; + destination: TDestination; + splitDestination?: TDestination; + note?: Bytes[]; + feeRate: number; +}; +export declare const BuildMergeTx: ({ tokenScheme, outPoint1, outPoint2, owner, feePayment, destination, splitDestination, note, feeRate, }: TBuildMergeTxRequest) => string; +export type TBuildRedeemTxRequest = { + tokenScheme: TokenScheme; + stasPayment: TPayment; + feePayment: TPayment; + splitDestinations?: TDestination[]; + note?: Bytes[]; + feeRate: number; +}; +export declare const BuildRedeemTx: ({ tokenScheme, stasPayment, feePayment, splitDestinations, note, feeRate, }: TBuildRedeemTxRequest) => string; +//# sourceMappingURL=transaction-factory.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction-factory.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/transaction-factory.d.ts.map new file mode 100644 index 0000000..3629a13 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction-factory.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-factory.d.ts","sourceRoot":"","sources":["../src/transaction-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,MAAM,EACP,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,eAAO,MAAM,OAAO,MAAM,CAAC;AAE3B,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,QAAQ,CAAC;IACtB,UAAU,EAAE,QAAQ,CAAC;IACrB,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,8DAO7B,uBAAuB,WAmBzB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,QAAQ,CAAC;IACtB,UAAU,EAAE,QAAQ,CAAC;IACrB,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,wEAO1B,oBAAoB,WAmCtB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,YAAY,CAAC;IACxB,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC;IAC3B,UAAU,EAAE,QAAQ,CAAC;IACrB,WAAW,EAAE,YAAY,CAAC;IAC1B,gBAAgB,CAAC,EAAE,YAAY,CAAC;IAChC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,yGAU1B,oBAAoB,WAwCtB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,QAAQ,CAAC;IACtB,UAAU,EAAE,QAAQ,CAAC;IACrB,iBAAiB,CAAC,EAAE,YAAY,EAAE,CAAC;IACnC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,6EAO3B,qBAAqB,WA6CvB,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction-factory.js b/vendor/dxs-bsv-token-sdk/dist/transaction-factory.js new file mode 100644 index 0000000..62331d9 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction-factory.js @@ -0,0 +1,93 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BuildRedeemTx = exports.BuildMergeTx = exports.BuildSplitTx = exports.BuildTransferTx = exports.FeeRate = void 0; +const bitcoin_1 = require("./bitcoin"); +const transaction_builder_1 = require("./transaction/build/transaction-builder"); +exports.FeeRate = 0.1; +const BuildTransferTx = ({ tokenScheme, stasPayment, feePayment, to, note, feeRate, }) => { + const txBuilder = transaction_builder_1.TransactionBuilder.init() + .addInput(stasPayment.OutPoint, stasPayment.Owner) + .addInput(feePayment.OutPoint, feePayment.Owner) + .addStasOutputByScheme(tokenScheme, stasPayment.OutPoint.Satoshis, to); + const feeOutputIdx = txBuilder.Outputs.length; + if (note) + txBuilder.addNullDataOutput(note); + return txBuilder + .addChangeOutputWithFee(feePayment.OutPoint.Address, feePayment.OutPoint.Satoshis, feeRate, feeOutputIdx) + .sign() + .toHex(); +}; +exports.BuildTransferTx = BuildTransferTx; +const BuildSplitTx = ({ tokenScheme, stasPayment, feePayment, destinations, note, feeRate, }) => { + if (destinations.length === 0 || destinations.length > 4) + throw new Error("Destinations count must be no less than one and no more than four"); + const outputSatoshis = destinations.reduce((a, x) => a + x.Satoshis, 0); + if (outputSatoshis !== stasPayment.OutPoint.Satoshis) + throw new Error("Input satoshis must be equal output satoshis"); + const txBuilder = transaction_builder_1.TransactionBuilder.init() + .addInput(stasPayment.OutPoint, stasPayment.Owner) + .addInput(feePayment.OutPoint, feePayment.Owner); + for (const destination of destinations) + txBuilder.addStasOutputByScheme(tokenScheme, destination.Satoshis, destination.Address); + const feeOutputIdx = txBuilder.Outputs.length; + if (note) + txBuilder.addNullDataOutput(note); + return txBuilder + .addChangeOutputWithFee(feePayment.OutPoint.Address, feePayment.OutPoint.Satoshis, feeRate, feeOutputIdx) + .sign() + .toHex(); +}; +exports.BuildSplitTx = BuildSplitTx; +const BuildMergeTx = ({ tokenScheme, outPoint1, outPoint2, owner, feePayment, destination, splitDestination, note, feeRate, }) => { + var _a; + if (outPoint1.Address.Value !== outPoint2.Address.Value) + throw new Error("Both inputs have to belong to same address"); + const outputSatoshis = destination.Satoshis + ((_a = splitDestination === null || splitDestination === void 0 ? void 0 : splitDestination.Satoshis) !== null && _a !== void 0 ? _a : 0); + if (outputSatoshis !== outPoint1.Satoshis + outPoint2.Satoshis) + throw new Error("Input satoshis must be equal output satoshis"); + const txBuilder = transaction_builder_1.TransactionBuilder.init() + .addStasMergeInput(outPoint1, owner) + .addStasMergeInput(outPoint2, owner) + .addInput(feePayment.OutPoint, feePayment.Owner) + .addStasOutputByScheme(tokenScheme, destination.Satoshis, destination.Address); + if (splitDestination) + txBuilder.addStasOutputByScheme(tokenScheme, splitDestination.Satoshis, splitDestination.Address); + const feeOutputIdx = txBuilder.Outputs.length; + if (note) + txBuilder.addNullDataOutput(note); + return txBuilder + .addChangeOutputWithFee(feePayment.OutPoint.Address, feePayment.OutPoint.Satoshis, feeRate, feeOutputIdx) + .sign() + .toHex(); +}; +exports.BuildMergeTx = BuildMergeTx; +const BuildRedeemTx = ({ tokenScheme, stasPayment, feePayment, splitDestinations, note, feeRate, }) => { + var _a, _b; + const redeemAddress = bitcoin_1.Address.fromHash160Hex(tokenScheme.TokenId); + if (stasPayment.OutPoint.Address.Value !== redeemAddress.Value) + throw new Error("Only owner of redeem address can redeem STAS tokens"); + if (((_a = splitDestinations === null || splitDestinations === void 0 ? void 0 : splitDestinations.length) !== null && _a !== void 0 ? _a : 0) > 3) + throw new Error("Destinations count must be no more than 3"); + const splitAmount = (_b = splitDestinations === null || splitDestinations === void 0 ? void 0 : splitDestinations.reduce((a, x) => a + x.Satoshis, 0)) !== null && _b !== void 0 ? _b : 0; + const redeemAmount = stasPayment.OutPoint.Satoshis - splitAmount; + if (redeemAmount < 0) + throw new Error("Input satoshis must be equal output satoshis"); + if (redeemAmount === 0) + throw new Error("redeemAmount must be at least 1 satoshi"); + const txBuilder = transaction_builder_1.TransactionBuilder.init() + .addInput(stasPayment.OutPoint, stasPayment.Owner) + .addInput(feePayment.OutPoint, feePayment.Owner) + .addP2PkhOutput(redeemAmount, redeemAddress); + if (splitDestinations) + for (const splitDestination of splitDestinations) + txBuilder.addStasOutputByScheme(tokenScheme, splitDestination.Satoshis, splitDestination.Address); + const feeOutputIdx = txBuilder.Outputs.length; + if (note) + txBuilder.addNullDataOutput(note); + return txBuilder + .addChangeOutputWithFee(feePayment.OutPoint.Address, feePayment.OutPoint.Satoshis, feeRate, feeOutputIdx) + .sign() + .toHex(); +}; +exports.BuildRedeemTx = BuildRedeemTx; +//# sourceMappingURL=transaction-factory.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction-factory.js.map b/vendor/dxs-bsv-token-sdk/dist/transaction-factory.js.map new file mode 100644 index 0000000..76ddda6 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction-factory.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-factory.js","sourceRoot":"","sources":["../src/transaction-factory.ts"],"names":[],"mappings":";;;AAAA,uCAQmB;AACnB,iFAA6E;AAGhE,QAAA,OAAO,GAAG,GAAG,CAAC;AAWpB,MAAM,eAAe,GAAG,CAAC,EAC9B,WAAW,EACX,WAAW,EACX,UAAU,EACV,EAAE,EACF,IAAI,EACJ,OAAO,GACiB,EAAE,EAAE;IAC5B,MAAM,SAAS,GAAG,wCAAkB,CAAC,IAAI,EAAE;SACxC,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC;SACjD,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC;SAC/C,qBAAqB,CAAC,WAAW,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEzE,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;IAE9C,IAAI,IAAI;QAAE,SAAS,CAAC,iBAAiB,CAAC,IAAK,CAAC,CAAC;IAE7C,OAAO,SAAS;SACb,sBAAsB,CACrB,UAAU,CAAC,QAAQ,CAAC,OAAQ,EAC5B,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAC5B,OAAO,EACP,YAAY,CACb;SACA,IAAI,EAAE;SACN,KAAK,EAAE,CAAC;AACb,CAAC,CAAC;AA1BW,QAAA,eAAe,mBA0B1B;AAWK,MAAM,YAAY,GAAG,CAAC,EAC3B,WAAW,EACX,WAAW,EACX,UAAU,EACV,YAAY,EACZ,IAAI,EACJ,OAAO,GACc,EAAE,EAAE;IACzB,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;IAEJ,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAExE,IAAI,cAAc,KAAK,WAAW,CAAC,QAAQ,CAAC,QAAQ;QAClD,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAElE,MAAM,SAAS,GAAG,wCAAkB,CAAC,IAAI,EAAE;SACxC,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC;SACjD,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAEnD,KAAK,MAAM,WAAW,IAAI,YAAY;QACpC,SAAS,CAAC,qBAAqB,CAC7B,WAAW,EACX,WAAW,CAAC,QAAQ,EACpB,WAAW,CAAC,OAAO,CACpB,CAAC;IAEJ,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;IAE9C,IAAI,IAAI;QAAE,SAAS,CAAC,iBAAiB,CAAC,IAAK,CAAC,CAAC;IAE7C,OAAO,SAAS;SACb,sBAAsB,CACrB,UAAU,CAAC,QAAQ,CAAC,OAAQ,EAC5B,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAC5B,OAAO,EACP,YAAY,CACb;SACA,IAAI,EAAE;SACN,KAAK,EAAE,CAAC;AACb,CAAC,CAAC;AA1CW,QAAA,YAAY,gBA0CvB;AAcK,MAAM,YAAY,GAAG,CAAC,EAC3B,WAAW,EACX,SAAS,EACT,SAAS,EACT,KAAK,EACL,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,IAAI,EACJ,OAAO,GACc,EAAE,EAAE;;IACzB,IAAI,SAAS,CAAC,OAAQ,CAAC,KAAK,KAAK,SAAS,CAAC,OAAQ,CAAC,KAAK;QACvD,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAEhE,MAAM,cAAc,GAClB,WAAW,CAAC,QAAQ,GAAG,CAAC,MAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAE,QAAQ,mCAAI,CAAC,CAAC,CAAC;IAE3D,IAAI,cAAc,KAAK,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,QAAQ;QAC5D,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAElE,MAAM,SAAS,GAAG,wCAAkB,CAAC,IAAI,EAAE;SACxC,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC;SACnC,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC;SACnC,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC;SAC/C,qBAAqB,CACpB,WAAW,EACX,WAAW,CAAC,QAAQ,EACpB,WAAW,CAAC,OAAO,CACpB,CAAC;IAEJ,IAAI,gBAAgB;QAClB,SAAS,CAAC,qBAAqB,CAC7B,WAAW,EACX,gBAAgB,CAAC,QAAQ,EACzB,gBAAgB,CAAC,OAAO,CACzB,CAAC;IAEJ,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;IAE9C,IAAI,IAAI;QAAE,SAAS,CAAC,iBAAiB,CAAC,IAAK,CAAC,CAAC;IAE7C,OAAO,SAAS;SACb,sBAAsB,CACrB,UAAU,CAAC,QAAQ,CAAC,OAAQ,EAC5B,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAC5B,OAAO,EACP,YAAY,CACb;SACA,IAAI,EAAE;SACN,KAAK,EAAE,CAAC;AACb,CAAC,CAAC;AAlDW,QAAA,YAAY,gBAkDvB;AAWK,MAAM,aAAa,GAAG,CAAC,EAC5B,WAAW,EACX,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,IAAI,EACJ,OAAO,GACe,EAAE,EAAE;;IAC1B,MAAM,aAAa,GAAG,iBAAO,CAAC,cAAc,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAElE,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAQ,CAAC,KAAK,KAAK,aAAa,CAAC,KAAK;QAC7D,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IAEzE,IAAI,CAAC,MAAA,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,MAAM,mCAAI,CAAC,CAAC,GAAG,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAE/D,MAAM,WAAW,GACf,MAAA,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,mCAAI,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,GAAG,WAAW,CAAC;IAEjE,IAAI,YAAY,GAAG,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAElE,IAAI,YAAY,KAAK,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAE7D,MAAM,SAAS,GAAG,wCAAkB,CAAC,IAAI,EAAE;SACxC,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC;SACjD,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC;SAC/C,cAAc,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAE/C,IAAI,iBAAiB;QACnB,KAAK,MAAM,gBAAgB,IAAI,iBAAiB;YAC9C,SAAS,CAAC,qBAAqB,CAC7B,WAAW,EACX,gBAAgB,CAAC,QAAQ,EACzB,gBAAgB,CAAC,OAAO,CACzB,CAAC;IAEN,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;IAE9C,IAAI,IAAI;QAAE,SAAS,CAAC,iBAAiB,CAAC,IAAK,CAAC,CAAC;IAE7C,OAAO,SAAS;SACb,sBAAsB,CACrB,UAAU,CAAC,QAAQ,CAAC,OAAQ,EAC5B,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAC5B,OAAO,EACP,YAAY,CACb;SACA,IAAI,EAAE;SACN,KAAK,EAAE,CAAC;AACb,CAAC,CAAC;AApDW,QAAA,aAAa,iBAoDxB"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.d.ts new file mode 100644 index 0000000..48b886a --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.d.ts @@ -0,0 +1,46 @@ +import { ByteWriter } from "../../binary"; +import { OutPoint } from "../../bitcoin/out-point"; +import { PrivateKey } from "../../bitcoin/private-key"; +import { SignatureHashType } from "../../bitcoin/sig-hash-type"; +import { TransactionBuilder } from "./transaction-builder"; +import { Wallet } from "../../bitcoin"; +import { Bytes } from "../../bytes"; +export declare class InputBilder { + protected TxBuilder: TransactionBuilder; + protected Owner: PrivateKey | Wallet; + protected Idx: number; + OutPoint: OutPoint; + Merge: boolean; + UnlockingScript?: Bytes; + AllowPresetUnlockingScript: boolean; + PresetUnlockingScriptSizeHint?: number; + AuthoritySignaturesCount?: number; + AuthorityPubKeysCount?: number; + DstasSpendingType: number; + Sequence: number; + private _mergeVout; + private _mergeSegments; + private _swapCounterpartyScript; + constructor(txBuilder: TransactionBuilder, outPoint: OutPoint, signer: PrivateKey | Wallet, merge: boolean); + sign: (force?: boolean) => void; + writeTo(writer: ByteWriter): void; + size: () => number; + preimageLength: () => number; + stasNullDataLength: () => number; + private resolveOutputOwnerField; + private isStasScriptType; + private isP2PkLike; + private hasDstasSwapActionData; + private isDstasRedeemLike; + private resolveFundingInput; + prevoutHashLength: () => number; + unlockingScriptSize: () => number; + preimage: (signatureHashType: SignatureHashType) => Uint8Array; + private writePrevoutHash; + private writeSequenceHash; + private writeOutputsHash; + private writeSingleOutputHash; + private writeZeroHash; + private prepareMergeInfo; +} +//# sourceMappingURL=input-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.d.ts.map new file mode 100644 index 0000000..acf95b7 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"input-builder.d.ts","sourceRoot":"","sources":["../../../src/transaction/build/input-builder.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAS7C,qBAAa,WAAW;IACtB,SAAS,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACxC,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC;IACrC,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC;IAEtB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,KAAK,CAAC;IACxB,0BAA0B,UAAS;IACnC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iBAAiB,SAAK;IACtB,QAAQ,SAAsC;IAE9C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,cAAc,CAAe;IACrC,OAAO,CAAC,uBAAuB,CAAsB;gBAGnD,SAAS,EAAE,kBAAkB,EAC7B,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,UAAU,GAAG,MAAM,EAC3B,KAAK,EAAE,OAAO;IAShB,IAAI,GAAI,eAAa,UAwHnB;IAEF,OAAO,CAAC,MAAM,EAAE,UAAU;IAO1B,IAAI,eAIA;IAEJ,cAAc,QAAO,MAAM,CAWvB;IAEJ,kBAAkB,eAQhB;IAEF,OAAO,CAAC,uBAAuB,CAS7B;IAEF,OAAO,CAAC,gBAAgB,CAC8C;IAEtE,OAAO,CAAC,UAAU,CACoD;IACtE,OAAO,CAAC,sBAAsB,CAY5B;IAUF,OAAO,CAAC,iBAAiB,CAUvB;IAEF,OAAO,CAAC,mBAAmB,CAmBzB;IAEF,iBAAiB,eAAiD;IAElE,mBAAmB,QAAO,MAAM,CAiI9B;IAKF,QAAQ,GAAI,mBAAmB,iBAAiB,6BA4C9C;IAEF,OAAO,CAAC,gBAAgB,CAWtB;IAEF,OAAO,CAAC,iBAAiB,CAQvB;IAEF,OAAO,CAAC,gBAAgB,CAYtB;IAEF,OAAO,CAAC,qBAAqB,CAY3B;IAEF,OAAO,CAAC,aAAa,CAEnB;IAEF,OAAO,CAAC,gBAAgB,CAkCtB;CACH"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.js b/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.js new file mode 100644 index 0000000..f1b8375 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.js @@ -0,0 +1,404 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.InputBilder = void 0; +const buffer_utils_1 = require("../../buffer/buffer-utils"); +const binary_1 = require("../../binary"); +const op_codes_1 = require("../../bitcoin/op-codes"); +const script_type_1 = require("../../bitcoin/script-type"); +const sig_hash_type_1 = require("../../bitcoin/sig-hash-type"); +const hashes_1 = require("../../hashes"); +const script_builder_1 = require("../../script/build/script-builder"); +const transaction_builder_1 = require("./transaction-builder"); +const bytes_1 = require("../../bytes"); +const strict_mode_1 = require("../../security/strict-mode"); +const dstas_swap_script_1 = require("../../script/dstas-swap-script"); +const dstas_action_data_1 = require("../../script/dstas-action-data"); +const script_reader_1 = require("../../script/read/script-reader"); +class InputBilder { + constructor(txBuilder, outPoint, signer, merge) { + this.AllowPresetUnlockingScript = false; + this.DstasSpendingType = 1; + this.Sequence = transaction_builder_1.TransactionBuilder.DefaultSequence; + this._mergeVout = 0; + this._mergeSegments = []; + this._swapCounterpartyScript = null; + this.sign = (force = false) => { + if (!force && this.UnlockingScript !== undefined) { + if ((0, strict_mode_1.getStrictModeConfig)().strictPresetUnlockingScript && + !this.AllowPresetUnlockingScript) { + throw new Error("Preset unlocking script is disabled in strict mode for this input"); + } + return; + } + const scriptType = this.OutPoint.ScriptType; + const preimage = this.preimage(transaction_builder_1.TransactionBuilder.DefaultSighashType); + const hashedPreimage = (0, hashes_1.hash256)(preimage); + const der = this.Owner.sign(hashedPreimage); + const derWithSigHashType = new Uint8Array(der.length + 1); + derWithSigHashType.set(der); + derWithSigHashType[der.length] = transaction_builder_1.TransactionBuilder.DefaultSighashType; + if (scriptType === script_type_1.ScriptType.p2pkh || scriptType === script_type_1.ScriptType.p2mpkh) { + const size = (0, buffer_utils_1.getChunkSize)(derWithSigHashType) + (0, buffer_utils_1.getChunkSize)(this.Owner.PublicKey); + const buffer = new Uint8Array(size); + const bufferWriter = new binary_1.ByteWriter(buffer); + bufferWriter.writeVarChunk(derWithSigHashType); + bufferWriter.writeVarChunk(this.Owner.PublicKey); + this.UnlockingScript = buffer; + } + else if (scriptType === script_type_1.ScriptType.p2stas || + scriptType === script_type_1.ScriptType.dstas) { + this.prepareMergeInfo(); + const script = new script_builder_1.ScriptBuilder(script_type_1.ScriptType.p2stas); + let hasNote = false; + let hasChangeOutput = false; + for (let outIdx = 0; outIdx < this.TxBuilder.Outputs.length; outIdx++) { + const output = this.TxBuilder.Outputs[outIdx]; + if (output.LockingScript.ScriptType === script_type_1.ScriptType.nullData) { + const nulldata = output.LockingScript.toBytes(); + const payload = nulldata.subarray(2); + script.addData(payload); + hasNote = true; + } + else { + script + .addNumber(output.Satoshis) + .addData(this.resolveOutputOwnerField(output.LockingScript)); + if (output.LockingScript.ScriptType === script_type_1.ScriptType.dstas) { + const actionDataToken = output.LockingScript._tokens[1]; + if (actionDataToken === null || actionDataToken === void 0 ? void 0 : actionDataToken.Data) { + script.addData(actionDataToken.Data); + } + else if (actionDataToken) { + script.addOpCode(actionDataToken.OpCodeNum); + } + else { + throw new Error("Divisible STAS output is missing action-data token in locking script"); + } + } + else if (this.isDstasRedeemLike() && + outIdx === 0 && + this.isP2PkLike(output.LockingScript.ScriptType)) { + script.addOpCode(op_codes_1.OpCode.OP_0); + } + if (this.isP2PkLike(output.LockingScript.ScriptType)) { + hasChangeOutput = true; + } + } + } + if (!hasChangeOutput) { + script.addOpCode(op_codes_1.OpCode.OP_0); + script.addOpCode(op_codes_1.OpCode.OP_0); + } + if (!hasNote) + script.addOpCode(op_codes_1.OpCode.OP_0); + const fundingInput = this.resolveFundingInput(); + script + .addNumber(fundingInput.OutPoint.Vout) + .addData((0, buffer_utils_1.reverseBytes)((0, bytes_1.fromHex)(fundingInput.OutPoint.TxId))); + if (this.Merge) { + script.addNumber(this._mergeVout).addDatas(this._mergeSegments); + if (this._swapCounterpartyScript) { + script + .addNumber(this._mergeSegments.length) + .addData(this._swapCounterpartyScript) + .addNumber(1); + } + else { + script.addNumber(this._mergeSegments.length); + } + } + else { + script.addOpCode(op_codes_1.OpCode.OP_0); + } + script.addData(preimage); + if (scriptType === script_type_1.ScriptType.dstas) { + script.addNumber(this.DstasSpendingType); + } + script.addData(derWithSigHashType).addData(this.Owner.PublicKey); + this.UnlockingScript = script.toBytes(); + } + }; + this.size = () => 32 + + 4 + + this.unlockingScriptSize() + + 4; + this.preimageLength = () => 4 + + 32 + + 32 + + 32 + + 4 + + (0, buffer_utils_1.getChunkSize)(this.OutPoint.LockingScript) + + 8 + + 4 + + 32 + + 4 + + 4; + this.stasNullDataLength = () => { + const nullDataOutput = this.TxBuilder.Outputs.find((x) => x.LockingScript.ScriptType === script_type_1.ScriptType.nullData); + if (!nullDataOutput) + return 1; + return (0, buffer_utils_1.estimateChunkSize)(nullDataOutput.LockingScript.size() - 2); + }; + this.resolveOutputOwnerField = (script) => { + if (script.ToAddress) + return script.ToAddress.Hash160; + const ownerToken = script._tokens[0]; + if (!(ownerToken === null || ownerToken === void 0 ? void 0 : ownerToken.Data) || ownerToken.Data.length === 0) { + throw new Error("Output locking script is missing owner field"); + } + return ownerToken.Data; + }; + this.isStasScriptType = (scriptType) => scriptType === script_type_1.ScriptType.p2stas || scriptType === script_type_1.ScriptType.dstas; + this.isP2PkLike = (scriptType) => scriptType === script_type_1.ScriptType.p2pkh || scriptType === script_type_1.ScriptType.p2mpkh; + this.hasDstasSwapActionData = (lockingScript) => { + const tokens = script_reader_1.ScriptReader.read(lockingScript); + const actionDataToken = tokens[1]; + if (!(actionDataToken === null || actionDataToken === void 0 ? void 0 : actionDataToken.Data) || actionDataToken.Data.length === 0) { + return false; + } + try { + return (0, dstas_action_data_1.decodeActionData)(actionDataToken.Data).kind === "swap"; + } + catch (_a) { + return false; + } + }; + this.isDstasRedeemLike = () => { + if (this.OutPoint.ScriptType !== script_type_1.ScriptType.dstas) + return false; + if (this.TxBuilder.Outputs.length === 0) + return false; + const hasDstasOutput = this.TxBuilder.Outputs.some((x) => x.LockingScript.ScriptType === script_type_1.ScriptType.dstas); + if (hasDstasOutput) + return false; + return this.isP2PkLike(this.TxBuilder.Outputs[0].LockingScript.ScriptType); + }; + this.resolveFundingInput = () => { + const candidates = this.TxBuilder.Inputs.filter((input, idx) => idx !== this.Idx && !this.isStasScriptType(input.OutPoint.ScriptType)); + if (candidates.length === 0) { + throw new Error("Unable to resolve funding input: expected one non-STAS input"); + } + if (candidates.length > 1) { + throw new Error("Unable to resolve funding input: multiple non-STAS inputs are present"); + } + return candidates[0]; + }; + this.prevoutHashLength = () => (32 + 4) * this.TxBuilder.Inputs.length; + this.unlockingScriptSize = () => { + if (this.UnlockingScript !== undefined) { + return (0, buffer_utils_1.estimateChunkSize)(this.UnlockingScript.length); + } + if (this.PresetUnlockingScriptSizeHint !== undefined) { + if (!Number.isInteger(this.PresetUnlockingScriptSizeHint)) { + throw new Error("Preset unlocking script size hint must be an integer"); + } + if (this.PresetUnlockingScriptSizeHint <= 0) { + throw new Error("Preset unlocking script size hint must be greater than zero"); + } + return (0, buffer_utils_1.estimateChunkSize)(this.PresetUnlockingScriptSizeHint); + } + const singleSigTailSize = 1 + + 73 + + 1 + + 33; + const authorityTailSize = () => { + if (this.AuthoritySignaturesCount === undefined || + this.AuthorityPubKeysCount === undefined) { + return singleSigTailSize; + } + const sigCount = this.AuthoritySignaturesCount; + const pubKeyCount = this.AuthorityPubKeysCount; + if (sigCount <= 0 || pubKeyCount <= 0) { + throw new Error("Authority signature/public-key counts must be > 0"); + } + const mlpkhPreimageSize = 1 + + pubKeyCount * (1 + 33) + + 1; + return (1 + + sigCount * (1 + 73) + + (0, buffer_utils_1.estimateChunkSize)(mlpkhPreimageSize)); + }; + if (this.OutPoint.ScriptType === script_type_1.ScriptType.p2pkh || + this.OutPoint.ScriptType === script_type_1.ScriptType.p2mpkh) { + return (0, buffer_utils_1.estimateChunkSize)(singleSigTailSize); + } + let size = 0; + if (this.OutPoint.ScriptType === script_type_1.ScriptType.p2stas || + this.OutPoint.ScriptType === script_type_1.ScriptType.dstas) { + this.prepareMergeInfo(); + const fundingOutpoint = this.resolveFundingInput().OutPoint; + size += this.stasNullDataLength(); + let hasChangeOutput = false; + size += this.TxBuilder.Outputs.reduce((a, x, outIdx) => { + if (x.LockingScript.ScriptType === script_type_1.ScriptType.nullData) + return a; + const ownerField = this.resolveOutputOwnerField(x.LockingScript); + a += (0, buffer_utils_1.getNumberSize)(x.Satoshis) + (0, buffer_utils_1.estimateChunkSize)(ownerField.length); + if (x.LockingScript.ScriptType === script_type_1.ScriptType.dstas) { + a += (0, buffer_utils_1.estimateChunkSize)(x.LockingScript._tokens[1].DataLength); + } + else if (this.isDstasRedeemLike() && + outIdx === 0 && + this.isP2PkLike(x.LockingScript.ScriptType)) { + a += 1; + } + if (this.isP2PkLike(x.LockingScript.ScriptType)) { + hasChangeOutput = true; + } + return a; + }, 0); + if (!hasChangeOutput) { + size += 2; + } + size += (0, buffer_utils_1.getNumberSize)(fundingOutpoint.Vout); + size += (0, buffer_utils_1.estimateChunkSize)(32); + size += (0, buffer_utils_1.estimateChunkSize)(this.preimageLength()); + if (!this.Merge) { + size += 1; + } + else { + size += (0, buffer_utils_1.getNumberSize)(this._mergeVout); + size += (0, buffer_utils_1.getNumberSize)(this._mergeSegments.length); + size += this._mergeSegments.reduce((a, x) => (0, buffer_utils_1.getChunkSize)(x) + a, 0); + if (this._swapCounterpartyScript) { + size += (0, buffer_utils_1.estimateChunkSize)(this._swapCounterpartyScript.length); + size += (0, buffer_utils_1.getNumberSize)(1); + } + } + if (this.OutPoint.ScriptType === script_type_1.ScriptType.dstas) { + size += (0, buffer_utils_1.getNumberSize)(this.DstasSpendingType); + } + if (this.OutPoint.ScriptType === script_type_1.ScriptType.dstas) { + size += authorityTailSize(); + } + else { + size += singleSigTailSize; + } + } + if (size === 0) { + size = singleSigTailSize; + } + return (0, buffer_utils_1.estimateChunkSize)(size); + }; + this.preimage = (signatureHashType) => { + const size = this.preimageLength(); + const buffer = new Uint8Array(size); + const writer = new binary_1.ByteWriter(buffer); + const baseType = signatureHashType & 0x1f; + const anyoneCanPay = (signatureHashType & sig_hash_type_1.SignatureHashType.SIGHASH_ANYONECANPAY) !== 0; + writer.writeUInt32(this.TxBuilder.Version); + if (anyoneCanPay) { + this.writeZeroHash(writer); + } + else { + this.writePrevoutHash(writer); + } + if (anyoneCanPay || + baseType === sig_hash_type_1.SignatureHashType.SIGHASH_NONE || + baseType === sig_hash_type_1.SignatureHashType.SIGHASH_SINGLE) { + this.writeZeroHash(writer); + } + else { + this.writeSequenceHash(writer); + } + writer.writeChunk((0, buffer_utils_1.reverseBytes)((0, bytes_1.fromHex)(this.OutPoint.TxId))); + writer.writeUInt32(this.OutPoint.Vout); + writer.writeVarChunk(this.OutPoint.LockingScript); + writer.writeUInt64(this.OutPoint.Satoshis); + writer.writeUInt32(this.Sequence); + if (baseType === sig_hash_type_1.SignatureHashType.SIGHASH_ALL) { + this.writeOutputsHash(writer); + } + else if (baseType === sig_hash_type_1.SignatureHashType.SIGHASH_SINGLE) { + this.writeSingleOutputHash(writer); + } + else { + this.writeZeroHash(writer); + } + writer.writeUInt32(this.TxBuilder.LockTime); + writer.writeUInt32(signatureHashType); + return buffer; + }; + this.writePrevoutHash = (writer) => { + const size = this.prevoutHashLength(); + const buffer = new Uint8Array(size); + const bufferWriter = new binary_1.ByteWriter(buffer); + for (const input of this.TxBuilder.Inputs) { + bufferWriter.writeChunk((0, buffer_utils_1.reverseBytes)((0, bytes_1.fromHex)(input.OutPoint.TxId))); + bufferWriter.writeUInt32(input.OutPoint.Vout); + } + writer.writeChunk((0, hashes_1.hash256)(buffer)); + }; + this.writeSequenceHash = (writer) => { + const buffer = new Uint8Array(4 * this.TxBuilder.Inputs.length); + const bufferWriter = new binary_1.ByteWriter(buffer); + for (const input of this.TxBuilder.Inputs) + bufferWriter.writeUInt32(input.Sequence); + writer.writeChunk((0, hashes_1.hash256)(buffer)); + }; + this.writeOutputsHash = (writer) => { + const size = this.TxBuilder.Outputs.reduce((a, x) => a + x.size(), 0); + const buffer = new Uint8Array(size); + const bufferWriter = new binary_1.ByteWriter(buffer); + for (const output of this.TxBuilder.Outputs) { + bufferWriter.writeUInt64(output.Satoshis); + bufferWriter.writeVarChunk(output.LockingScript.toBytes()); + } + writer.writeChunk((0, hashes_1.hash256)(buffer)); + }; + this.writeSingleOutputHash = (writer) => { + if (this.Idx >= this.TxBuilder.Outputs.length) { + this.writeZeroHash(writer); + return; + } + const output = this.TxBuilder.Outputs[this.Idx]; + const buffer = new Uint8Array(output.size()); + const bufferWriter = new binary_1.ByteWriter(buffer); + output.writeTo(bufferWriter); + writer.writeChunk((0, hashes_1.hash256)(buffer)); + }; + this.writeZeroHash = (writer) => { + writer.writeChunk(new Uint8Array(32)); + }; + this.prepareMergeInfo = () => { + var _a; + if (!this.Merge || this._mergeSegments.length > 0) + return; + const mergeUtxo = this.TxBuilder.Inputs[this.Idx === 0 ? 1 : 0]; + const mergeRaw = (_a = mergeUtxo.OutPoint.Transaction) === null || _a === void 0 ? void 0 : _a.Raw; + if (!mergeRaw) { + throw new Error("Merge input requires source transaction raw bytes"); + } + this._mergeVout = mergeUtxo.OutPoint.Vout; + if (this.OutPoint.ScriptType === script_type_1.ScriptType.dstas) { + const isSwap = this.hasDstasSwapActionData(this.OutPoint.LockingScript) || + this.hasDstasSwapActionData(mergeUtxo.OutPoint.LockingScript); + const scriptSource = isSwap + ? mergeUtxo.OutPoint.LockingScript + : this.TxBuilder.Inputs[0].OutPoint.LockingScript; + const scriptToCut = (0, dstas_swap_script_1.extractDstasCounterpartyScript)(scriptSource); + this._mergeSegments = (0, dstas_swap_script_1.splitDstasPreviousTransactionByCounterpartyScript)(mergeRaw, scriptToCut).reverse(); + if (isSwap) { + this._swapCounterpartyScript = scriptToCut; + } + return; + } + const lockingScript = this.TxBuilder.Inputs[0].OutPoint.LockingScript; + const scriptToCut = (0, buffer_utils_1.cloneBytes)(lockingScript, 0, 23); + this._mergeSegments = (0, buffer_utils_1.splitBytes)(mergeRaw, scriptToCut).reverse(); + }; + this.TxBuilder = txBuilder; + this.Idx = txBuilder.Inputs.length; + this.OutPoint = outPoint; + this.Owner = signer; + this.Merge = merge; + } + writeTo(writer) { + writer.writeChunk((0, buffer_utils_1.reverseBytes)((0, bytes_1.fromHex)(this.OutPoint.TxId))); + writer.writeUInt32(this.OutPoint.Vout); + writer.writeVarChunk(this.UnlockingScript); + writer.writeUInt32(this.Sequence); + } +} +exports.InputBilder = InputBilder; +//# sourceMappingURL=input-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.js.map new file mode 100644 index 0000000..7a0386e --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/input-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"input-builder.js","sourceRoot":"","sources":["../../../src/transaction/build/input-builder.ts"],"names":[],"mappings":";;;AAAA,4DAOmC;AACnC,yCAA0C;AAC1C,qDAAgD;AAGhD,2DAAuD;AACvD,+DAAgE;AAChE,yCAAuC;AACvC,sEAAkE;AAClE,+DAA2D;AAE3D,uCAA6C;AAC7C,4DAAiE;AACjE,sEAGwC;AACxC,sEAAkE;AAClE,mEAA+D;AAE/D,MAAa,WAAW;IAmBtB,YACE,SAA6B,EAC7B,QAAkB,EAClB,MAA2B,EAC3B,KAAc;QAfhB,+BAA0B,GAAG,KAAK,CAAC;QAInC,sBAAiB,GAAG,CAAC,CAAC;QACtB,aAAQ,GAAG,wCAAkB,CAAC,eAAe,CAAC;QAEtC,eAAU,GAAW,CAAC,CAAC;QACvB,mBAAc,GAAY,EAAE,CAAC;QAC7B,4BAAuB,GAAiB,IAAI,CAAC;QAerD,SAAI,GAAG,CAAC,KAAK,GAAG,KAAK,EAAE,EAAE;YACvB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;gBACjD,IACE,IAAA,iCAAmB,GAAE,CAAC,2BAA2B;oBACjD,CAAC,IAAI,CAAC,0BAA0B,EAChC,CAAC;oBACD,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;gBACJ,CAAC;gBACD,OAAO;YACT,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,wCAAkB,CAAC,kBAAkB,CAAC,CAAC;YACtE,MAAM,cAAc,GAAG,IAAA,gBAAO,EAAC,QAAQ,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC5C,MAAM,kBAAkB,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC1D,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5B,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,wCAAkB,CAAC,kBAAkB,CAAC;YAEvE,IAAI,UAAU,KAAK,wBAAU,CAAC,KAAK,IAAI,UAAU,KAAK,wBAAU,CAAC,MAAM,EAAE,CAAC;gBACxE,MAAM,IAAI,GACR,IAAA,2BAAY,EAAC,kBAAkB,CAAC,GAAG,IAAA,2BAAY,EAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBACxE,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;gBACpC,MAAM,YAAY,GAAG,IAAI,mBAAU,CAAC,MAAM,CAAC,CAAC;gBAE5C,YAAY,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC;gBAC/C,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBAEjD,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;YAChC,CAAC;iBAAM,IACL,UAAU,KAAK,wBAAU,CAAC,MAAM;gBAChC,UAAU,KAAK,wBAAU,CAAC,KAAK,EAC/B,CAAC;gBACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAExB,MAAM,MAAM,GAAG,IAAI,8BAAa,CAAC,wBAAU,CAAC,MAAM,CAAC,CAAC;gBAEpD,IAAI,OAAO,GAAG,KAAK,CAAC;gBACpB,IAAI,eAAe,GAAG,KAAK,CAAC;gBAE5B,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;oBACtE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBAC9C,IAAI,MAAM,CAAC,aAAa,CAAC,UAAU,KAAK,wBAAU,CAAC,QAAQ,EAAE,CAAC;wBAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;wBAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;wBAErC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;wBAExB,OAAO,GAAG,IAAI,CAAC;oBACjB,CAAC;yBAAM,CAAC;wBACN,MAAM;6BACH,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;6BAC1B,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;wBAE/D,IAAI,MAAM,CAAC,aAAa,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK,EAAE,CAAC;4BACzD,MAAM,eAAe,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;4BAExD,IAAI,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,IAAI,EAAE,CAAC;gCAC1B,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;4BACvC,CAAC;iCAAM,IAAI,eAAe,EAAE,CAAC;gCAC3B,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;4BAC9C,CAAC;iCAAM,CAAC;gCACN,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;4BACJ,CAAC;wBACH,CAAC;6BAAM,IACL,IAAI,CAAC,iBAAiB,EAAE;4BACxB,MAAM,KAAK,CAAC;4BACZ,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,EAChD,CAAC;4BACD,MAAM,CAAC,SAAS,CAAC,iBAAM,CAAC,IAAI,CAAC,CAAC;wBAChC,CAAC;wBAED,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;4BACrD,eAAe,GAAG,IAAI,CAAC;wBACzB,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,MAAM,CAAC,SAAS,CAAC,iBAAM,CAAC,IAAI,CAAC,CAAC;oBAC9B,MAAM,CAAC,SAAS,CAAC,iBAAM,CAAC,IAAI,CAAC,CAAC;gBAChC,CAAC;gBAED,IAAI,CAAC,OAAO;oBAAE,MAAM,CAAC,SAAS,CAAC,iBAAM,CAAC,IAAI,CAAC,CAAC;gBAE5C,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAEhD,MAAM;qBACH,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;qBACrC,OAAO,CAAC,IAAA,2BAAY,EAAC,IAAA,eAAO,EAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAE9D,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;oBAEhE,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;wBACjC,MAAM;6BACH,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;6BACrC,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC;6BACrC,SAAS,CAAC,CAAC,CAAC,CAAC;oBAClB,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;oBAC/C,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,SAAS,CAAC,iBAAM,CAAC,IAAI,CAAC,CAAC;gBAChC,CAAC;gBAED,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAEzB,IAAI,UAAU,KAAK,wBAAU,CAAC,KAAK,EAAE,CAAC;oBACpC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBAC3C,CAAC;gBAED,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBAEjE,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YAC1C,CAAC;QACH,CAAC,CAAC;QASF,SAAI,GAAG,GAAG,EAAE,CACV,EAAE;YACF,CAAC;YACD,IAAI,CAAC,mBAAmB,EAAE;YAC1B,CAAC,CAAC;QAEJ,mBAAc,GAAG,GAAW,EAAE,CAC5B,CAAC;YACD,EAAE;YACF,EAAE;YACF,EAAE;YACF,CAAC;YACD,IAAA,2BAAY,EAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;YACzC,CAAC;YACD,CAAC;YACD,EAAE;YACF,CAAC;YACD,CAAC,CAAC;QAEJ,uBAAkB,GAAG,GAAG,EAAE;YACxB,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAChD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,KAAK,wBAAU,CAAC,QAAQ,CAC1D,CAAC;YAEF,IAAI,CAAC,cAAc;gBAAE,OAAO,CAAC,CAAC;YAE9B,OAAO,IAAA,gCAAiB,EAAC,cAAc,CAAC,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACpE,CAAC,CAAC;QAEM,4BAAuB,GAAG,CAAC,MAAqB,EAAS,EAAE;YACjE,IAAI,MAAM,CAAC,SAAS;gBAAE,OAAO,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC;YAEtD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACrC,IAAI,CAAC,CAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,IAAI,CAAA,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtD,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;YAED,OAAO,UAAU,CAAC,IAAI,CAAC;QACzB,CAAC,CAAC;QAEM,qBAAgB,GAAG,CAAC,UAAsB,EAAW,EAAE,CAC7D,UAAU,KAAK,wBAAU,CAAC,MAAM,IAAI,UAAU,KAAK,wBAAU,CAAC,KAAK,CAAC;QAE9D,eAAU,GAAG,CAAC,UAAsB,EAAW,EAAE,CACvD,UAAU,KAAK,wBAAU,CAAC,KAAK,IAAI,UAAU,KAAK,wBAAU,CAAC,MAAM,CAAC;QAC9D,2BAAsB,GAAG,CAAC,aAAoB,EAAW,EAAE;YACjE,MAAM,MAAM,GAAG,4BAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAChD,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC,CAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,IAAI,CAAA,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAChE,OAAO,KAAK,CAAC;YACf,CAAC;YAED,IAAI,CAAC;gBACH,OAAO,IAAA,oCAAgB,EAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;YAChE,CAAC;YAAC,WAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC,CAAC;QAUM,sBAAiB,GAAG,GAAY,EAAE;YACxC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK;gBAAE,OAAO,KAAK,CAAC;YAChE,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YAEtD,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAChD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK,CACvD,CAAC;YACF,IAAI,cAAc;gBAAE,OAAO,KAAK,CAAC;YAEjC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QAC7E,CAAC,CAAC;QAEM,wBAAmB,GAAG,GAAgB,EAAE;YAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAC7C,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CACb,GAAG,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CACxE,CAAC;YAEF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACb,8DAA8D,CAC/D,CAAC;YACJ,CAAC;YAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CACb,uEAAuE,CACxE,CAAC;YACJ,CAAC;YAED,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC,CAAC;QAEF,sBAAiB,GAAG,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;QAElE,wBAAmB,GAAG,GAAW,EAAE;YACjC,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;gBACvC,OAAO,IAAA,gCAAiB,EAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;YACxD,CAAC;YAED,IAAI,IAAI,CAAC,6BAA6B,KAAK,SAAS,EAAE,CAAC;gBACrD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,6BAA6B,CAAC,EAAE,CAAC;oBAC1D,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;gBAC1E,CAAC;gBACD,IAAI,IAAI,CAAC,6BAA6B,IAAI,CAAC,EAAE,CAAC;oBAC5C,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;gBACJ,CAAC;gBACD,OAAO,IAAA,gCAAiB,EAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,iBAAiB,GACrB,CAAC;gBACD,EAAE;gBACF,CAAC;gBACD,EAAE,CAAC;YAEL,MAAM,iBAAiB,GAAG,GAAG,EAAE;gBAC7B,IACE,IAAI,CAAC,wBAAwB,KAAK,SAAS;oBAC3C,IAAI,CAAC,qBAAqB,KAAK,SAAS,EACxC,CAAC;oBACD,OAAO,iBAAiB,CAAC;gBAC3B,CAAC;gBAED,MAAM,QAAQ,GAAG,IAAI,CAAC,wBAAwB,CAAC;gBAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,qBAAqB,CAAC;gBAE/C,IAAI,QAAQ,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;oBACtC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;gBACvE,CAAC;gBAED,MAAM,iBAAiB,GACrB,CAAC;oBACD,WAAW,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;oBACtB,CAAC,CAAC;gBAEJ,OAAO,CACL,CAAC;oBACD,QAAQ,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;oBACnB,IAAA,gCAAiB,EAAC,iBAAiB,CAAC,CACrC,CAAC;YACJ,CAAC,CAAC;YAEF,IACE,IAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK;gBAC7C,IAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,wBAAU,CAAC,MAAM,EAC9C,CAAC;gBACD,OAAO,IAAA,gCAAiB,EAAC,iBAAiB,CAAC,CAAC;YAC9C,CAAC;YAED,IAAI,IAAI,GAAG,CAAC,CAAC;YAEb,IACE,IAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,wBAAU,CAAC,MAAM;gBAC9C,IAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK,EAC7C,CAAC;gBACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAExB,MAAM,eAAe,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC,QAAQ,CAAC;gBAE5D,IAAI,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAElC,IAAI,eAAe,GAAG,KAAK,CAAC;gBAE5B,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE;oBACrD,IAAI,CAAC,CAAC,aAAa,CAAC,UAAU,KAAK,wBAAU,CAAC,QAAQ;wBAAE,OAAO,CAAC,CAAC;oBAEjE,MAAM,UAAU,GAAG,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;oBACjE,CAAC,IAAI,IAAA,4BAAa,EAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAA,gCAAiB,EAAC,UAAU,CAAC,MAAM,CAAC,CAAC;oBAEtE,IAAI,CAAC,CAAC,aAAa,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK,EAAE,CAAC;wBACpD,CAAC,IAAI,IAAA,gCAAiB,EAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;oBAChE,CAAC;yBAAM,IACL,IAAI,CAAC,iBAAiB,EAAE;wBACxB,MAAM,KAAK,CAAC;wBACZ,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,EAC3C,CAAC;wBACD,CAAC,IAAI,CAAC,CAAC;oBACT,CAAC;oBAED,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;wBAChD,eAAe,GAAG,IAAI,CAAC;oBACzB,CAAC;oBAED,OAAO,CAAC,CAAC;gBACX,CAAC,EAAE,CAAC,CAAC,CAAC;gBAEN,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,IAAI,IAAI,CAAC,CAAC;gBACZ,CAAC;gBAED,IAAI,IAAI,IAAA,4BAAa,EAAC,eAAe,CAAC,IAAI,CAAC,CAAC;gBAC5C,IAAI,IAAI,IAAA,gCAAiB,EAAC,EAAE,CAAC,CAAC;gBAC9B,IAAI,IAAI,IAAA,gCAAiB,EAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;gBAEjD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBAChB,IAAI,IAAI,CAAC,CAAC;gBACZ,CAAC;qBAAM,CAAC;oBACN,IAAI,IAAI,IAAA,4BAAa,EAAC,IAAI,CAAC,UAAU,CAAC,CAAC;oBACvC,IAAI,IAAI,IAAA,4BAAa,EAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;oBAClD,IAAI,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAA,2BAAY,EAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;oBACrE,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;wBACjC,IAAI,IAAI,IAAA,gCAAiB,EAAC,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;wBAC/D,IAAI,IAAI,IAAA,4BAAa,EAAC,CAAC,CAAC,CAAC;oBAC3B,CAAC;gBACH,CAAC;gBAED,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK,EAAE,CAAC;oBAClD,IAAI,IAAI,IAAA,4BAAa,EAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBAChD,CAAC;gBAED,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK,EAAE,CAAC;oBAClD,IAAI,IAAI,iBAAiB,EAAE,CAAC;gBAC9B,CAAC;qBAAM,CAAC;oBACN,IAAI,IAAI,iBAAiB,CAAC;gBAC5B,CAAC;YACH,CAAC;YAED,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,IAAI,GAAG,iBAAiB,CAAC;YAC3B,CAAC;YAED,OAAO,IAAA,gCAAiB,EAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC;QAKF,aAAQ,GAAG,CAAC,iBAAoC,EAAE,EAAE;YAClD,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,IAAI,mBAAU,CAAC,MAAM,CAAC,CAAC;YACtC,MAAM,QAAQ,GAAG,iBAAiB,GAAG,IAAI,CAAC;YAC1C,MAAM,YAAY,GAChB,CAAC,iBAAiB,GAAG,iCAAiB,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAErE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAE3C,IAAI,YAAY,EAAE,CAAC;gBACjB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;YAED,IACE,YAAY;gBACZ,QAAQ,KAAK,iCAAiB,CAAC,YAAY;gBAC3C,QAAQ,KAAK,iCAAiB,CAAC,cAAc,EAC7C,CAAC;gBACD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACjC,CAAC;YAED,MAAM,CAAC,UAAU,CAAC,IAAA,2BAAY,EAAC,IAAA,eAAO,EAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7D,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;YAClD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC3C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAElC,IAAI,QAAQ,KAAK,iCAAiB,CAAC,WAAW,EAAE,CAAC;gBAC/C,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;iBAAM,IAAI,QAAQ,KAAK,iCAAiB,CAAC,cAAc,EAAE,CAAC;gBACzD,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC;YAED,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;YAEtC,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;QAEM,qBAAgB,GAAG,CAAC,MAAkB,EAAE,EAAE;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,YAAY,GAAG,IAAI,mBAAU,CAAC,MAAM,CAAC,CAAC;YAE5C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;gBAC1C,YAAY,CAAC,UAAU,CAAC,IAAA,2BAAY,EAAC,IAAA,eAAO,EAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACpE,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAChD,CAAC;YAED,MAAM,CAAC,UAAU,CAAC,IAAA,gBAAO,EAAC,MAAM,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC;QAEM,sBAAiB,GAAG,CAAC,MAAkB,EAAE,EAAE;YACjD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAChE,MAAM,YAAY,GAAG,IAAI,mBAAU,CAAC,MAAM,CAAC,CAAC;YAE5C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM;gBACvC,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAE3C,MAAM,CAAC,UAAU,CAAC,IAAA,gBAAO,EAAC,MAAM,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC;QAEM,qBAAgB,GAAG,CAAC,MAAkB,EAAE,EAAE;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;YAEtE,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,YAAY,GAAG,IAAI,mBAAU,CAAC,MAAM,CAAC,CAAC;YAE5C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;gBAC5C,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC1C,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7D,CAAC;YAED,MAAM,CAAC,UAAU,CAAC,IAAA,gBAAO,EAAC,MAAM,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC;QAEM,0BAAqB,GAAG,CAAC,MAAkB,EAAE,EAAE;YACrD,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC9C,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7C,MAAM,YAAY,GAAG,IAAI,mBAAU,CAAC,MAAM,CAAC,CAAC;YAE5C,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC7B,MAAM,CAAC,UAAU,CAAC,IAAA,gBAAO,EAAC,MAAM,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC;QAEM,kBAAa,GAAG,CAAC,MAAkB,EAAE,EAAE;YAC7C,MAAM,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,CAAC,CAAC;QAEM,qBAAgB,GAAG,GAAG,EAAE;;YAC9B,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO;YAE1D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,MAAA,SAAS,CAAC,QAAQ,CAAC,WAAW,0CAAE,GAAG,CAAC;YACrD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACvE,CAAC;YAED,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC1C,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,wBAAU,CAAC,KAAK,EAAE,CAAC;gBAClD,MAAM,MAAM,GACV,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;oBACxD,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;gBAEhE,MAAM,YAAY,GAAG,MAAM;oBACzB,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,aAAa;oBAClC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAEpD,MAAM,WAAW,GAAG,IAAA,kDAA8B,EAAC,YAAY,CAAC,CAAC;gBACjE,IAAI,CAAC,cAAc,GAAG,IAAA,qEAAiD,EACrE,QAAQ,EACR,WAAW,CACZ,CAAC,OAAO,EAAE,CAAC;gBAEZ,IAAI,MAAM,EAAE,CAAC;oBACX,IAAI,CAAC,uBAAuB,GAAG,WAAW,CAAC;gBAC7C,CAAC;gBACD,OAAO;YACT,CAAC;YAED,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;YACtE,MAAM,WAAW,GAAG,IAAA,yBAAU,EAAC,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACrD,IAAI,CAAC,cAAc,GAAG,IAAA,yBAAU,EAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;QACpE,CAAC,CAAC;QA3fA,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC;QACpB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IA4HD,OAAO,CAAC,MAAkB;QACxB,MAAM,CAAC,UAAU,CAAC,IAAA,2BAAY,EAAC,IAAA,eAAO,EAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7D,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,eAAgB,CAAC,CAAC;QAC5C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;CAsXF;AArhBD,kCAqhBC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.d.ts new file mode 100644 index 0000000..ba3856f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.d.ts @@ -0,0 +1,10 @@ +import { ByteWriter } from "../../binary"; +import { ScriptBuilder } from "../../script/build/script-builder"; +export declare class OutputBuilder { + Satoshis: number; + LockingScript: ScriptBuilder; + constructor(lockingScript: ScriptBuilder, satoshis: number); + size(): number; + writeTo(writer: ByteWriter): void; +} +//# sourceMappingURL=output-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.d.ts.map new file mode 100644 index 0000000..3e3cd10 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"output-builder.d.ts","sourceRoot":"","sources":["../../../src/transaction/build/output-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,qBAAa,aAAa;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,aAAa,CAAC;gBAEjB,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM;IAK1D,IAAI;IAOJ,OAAO,CAAC,MAAM,EAAE,UAAU;CAI3B"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.js b/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.js new file mode 100644 index 0000000..056dcd7 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.OutputBuilder = void 0; +const buffer_utils_1 = require("../../buffer/buffer-utils"); +class OutputBuilder { + constructor(lockingScript, satoshis) { + this.LockingScript = lockingScript; + this.Satoshis = satoshis; + } + size() { + return (8 + + (0, buffer_utils_1.estimateChunkSize)(this.LockingScript.size())); + } + writeTo(writer) { + writer.writeUInt64(this.Satoshis); + writer.writeVarChunk(this.LockingScript.toBytes()); + } +} +exports.OutputBuilder = OutputBuilder; +//# sourceMappingURL=output-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.js.map new file mode 100644 index 0000000..64ff2ec --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/output-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"output-builder.js","sourceRoot":"","sources":["../../../src/transaction/build/output-builder.ts"],"names":[],"mappings":";;;AAAA,4DAA8D;AAI9D,MAAa,aAAa;IAIxB,YAAY,aAA4B,EAAE,QAAgB;QACxD,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,IAAI;QACF,OAAO,CACL,CAAC;YACD,IAAA,gCAAiB,EAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAC7C,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,MAAkB;QACxB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;CACF;AApBD,sCAoBC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.d.ts b/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.d.ts new file mode 100644 index 0000000..6774921 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.d.ts @@ -0,0 +1,36 @@ +import { Address } from "../../bitcoin/address"; +import { OutPoint } from "../../bitcoin/out-point"; +import { PrivateKey } from "../../bitcoin/private-key"; +import { TokenScheme } from "../../bitcoin/token-scheme"; +import { InputBilder } from "./input-builder"; +import { OutputBuilder } from "./output-builder"; +import { Wallet } from "../../bitcoin"; +import { Bytes } from "../../bytes"; +export declare class TransactionBuilderError extends Error { + devMessage: string; + constructor(message: string, devMessage: string); +} +export declare class TransactionBuilder { + static DefaultSequence: number; + static DefaultSighashType: number; + Inputs: InputBilder[]; + Outputs: OutputBuilder[]; + Version: number; + LockTime: number; + static init: () => TransactionBuilder; + private validateFeeRate; + size: () => number; + getFee: (satoshisPerByte: number) => number; + addInput: (outPoint: OutPoint, signer: PrivateKey | Wallet, sequence?: number) => this; + addStasMergeInput: (outPoint: OutPoint, signer: PrivateKey | Wallet, sequence?: number) => this; + addP2PkhOutput: (value: number, to: Address, data?: Bytes[]) => this; + addP2MpkhOutput: (value: number, to: Address) => this; + addNullDataOutput(data: Bytes[]): this; + addChangeOutputWithFee(to: Address, change: number, satoshisPerByte: number, idx?: number | null): this; + addStasOutputByScheme: (schema: TokenScheme, satoshis: number, to: Address, data?: Bytes[]) => this; + addStasOutputByPrevLockingScript: (satoshis: number, to: Address, prevStasLockingScript: Bytes) => this; + sign: (force?: boolean) => this; + toBytes: () => Uint8Array; + toHex: () => string; +} +//# sourceMappingURL=transaction-builder.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.d.ts.map new file mode 100644 index 0000000..e7af335 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-builder.d.ts","sourceRoot":"","sources":["../../../src/transaction/build/transaction-builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAMzD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,KAAK,EAAsB,MAAM,aAAa,CAAC;AAGxD,qBAAa,uBAAwB,SAAQ,KAAK;IAGvC,UAAU,EAAE,MAAM;gBADzB,OAAO,EAAE,MAAM,EACR,UAAU,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAkB;IAK7B,MAAM,CAAC,eAAe,SAAc;IACpC,MAAM,CAAC,kBAAkB,SAC0C;IAEnE,MAAM,EAAE,WAAW,EAAE,CAAM;IAC3B,OAAO,EAAE,aAAa,EAAE,CAAM;IAE9B,OAAO,SAAK;IACZ,QAAQ,SAAK;IAEb,MAAM,CAAC,IAAI,2BAAkC;IAE7C,OAAO,CAAC,eAAe,CAiBrB;IAEF,IAAI,eAM6C;IAEjD,MAAM,GAAI,iBAAiB,MAAM,YAG/B;IAEF,QAAQ,GACN,UAAU,QAAQ,EAClB,QAAQ,UAAU,GAAG,MAAM,EAC3B,WAAU,MAA2C,UAOrD;IAEF,iBAAiB,GACf,UAAU,QAAQ,EAClB,QAAQ,UAAU,GAAG,MAAM,EAC3B,WAAU,MAA2C,UAOrD;IAEF,cAAc,GAAI,OAAO,MAAM,EAAE,IAAI,OAAO,EAAE,OAAM,KAAK,EAAO,UAU9D;IAEF,eAAe,GAAI,OAAO,MAAM,EAAE,IAAI,OAAO,UAI3C;IAEF,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE;IAQ/B,sBAAsB,CACpB,EAAE,EAAE,OAAO,EACX,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,EACvB,GAAG,GAAE,MAAM,GAAG,IAAW;IAqB3B,qBAAqB,GACnB,QAAQ,WAAW,EACnB,UAAU,MAAM,EAChB,IAAI,OAAO,EACX,OAAM,KAAK,EAAO,UAWlB;IAEF,gCAAgC,GAC9B,UAAU,MAAM,EAChB,IAAI,OAAO,EACX,uBAAuB,KAAK,UA0C5B;IAEF,IAAI,GAAI,eAAa,UAMnB;IAEF,OAAO,gCAgBL;IAEF,KAAK,eAA+B;CACrC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.js b/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.js new file mode 100644 index 0000000..08b695f --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.js @@ -0,0 +1,154 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TransactionBuilder = exports.TransactionBuilderError = void 0; +const buffer_utils_1 = require("../../buffer/buffer-utils"); +const binary_1 = require("../../binary"); +const op_codes_1 = require("../../bitcoin/op-codes"); +const sig_hash_type_1 = require("../../bitcoin/sig-hash-type"); +const null_data_builder_1 = require("../../script/build/null-data-builder"); +const p2mpkh_builder_1 = require("../../script/build/p2mpkh-builder"); +const p2pkh_builder_1 = require("../../script/build/p2pkh-builder"); +const p2stas_builder_1 = require("../../script/build/p2stas-builder"); +const script_reader_1 = require("../../script/read/script-reader"); +const input_builder_1 = require("./input-builder"); +const output_builder_1 = require("./output-builder"); +const bytes_1 = require("../../bytes"); +const strict_mode_1 = require("../../security/strict-mode"); +class TransactionBuilderError extends Error { + constructor(message, devMessage) { + super(message); + this.devMessage = devMessage; + } +} +exports.TransactionBuilderError = TransactionBuilderError; +class TransactionBuilder { + constructor() { + this.Inputs = []; + this.Outputs = []; + this.Version = 1; + this.LockTime = 0; + this.validateFeeRate = (satoshisPerByte) => { + const strict = (0, strict_mode_1.getStrictModeConfig)(); + if (!strict.strictFeeRateValidation) + return; + if (!Number.isFinite(satoshisPerByte) || satoshisPerByte <= 0) { + throw new TransactionBuilderError("Invalid fee rate", `feeRate must be a positive finite number, got: ${satoshisPerByte}`); + } + if (satoshisPerByte > strict.maxFeeRateSatsPerByte) { + throw new TransactionBuilderError("Fee rate too high", `feeRate ${satoshisPerByte} exceeds strict max ${strict.maxFeeRateSatsPerByte}`); + } + }; + this.size = () => 4 + + 4 + + (0, buffer_utils_1.getVarIntLength)(this.Inputs.length) + + this.Inputs.reduce((a, x) => a + x.size(), 0) + + (0, buffer_utils_1.getVarIntLength)(this.Outputs.length) + + this.Outputs.reduce((a, x) => a + x.size(), 0); + this.getFee = (satoshisPerByte) => { + this.validateFeeRate(satoshisPerByte); + return Math.ceil(this.size() * satoshisPerByte); + }; + this.addInput = (outPoint, signer, sequence = TransactionBuilder.DefaultSequence) => { + const input = new input_builder_1.InputBilder(this, outPoint, signer, false); + input.Sequence = sequence; + this.Inputs.push(input); + return this; + }; + this.addStasMergeInput = (outPoint, signer, sequence = TransactionBuilder.DefaultSequence) => { + const input = new input_builder_1.InputBilder(this, outPoint, signer, true); + input.Sequence = sequence; + this.Inputs.push(input); + return this; + }; + this.addP2PkhOutput = (value, to, data = []) => { + const script = new p2pkh_builder_1.P2pkhBuilder(to); + for (const d of data) { + script.addReturnData(d); + } + this.Outputs.push(new output_builder_1.OutputBuilder(script, value)); + return this; + }; + this.addP2MpkhOutput = (value, to) => { + const script = new p2mpkh_builder_1.P2mpkhBuilder(to); + this.Outputs.push(new output_builder_1.OutputBuilder(script, value)); + return this; + }; + this.addStasOutputByScheme = (schema, satoshis, to, data = []) => { + const script = new p2stas_builder_1.P2stasBuilder(to, schema.TokenId, schema.Symbol); + for (const d of data) { + script.addData(d); + } + this.Outputs.push(new output_builder_1.OutputBuilder(script, satoshis)); + return this; + }; + this.addStasOutputByPrevLockingScript = (satoshis, to, prevStasLockingScript) => { + const prevScriptTokens = script_reader_1.ScriptReader.read(prevStasLockingScript); + const opReturnIdx = prevScriptTokens.findIndex((x) => x.OpCodeNum === op_codes_1.OpCode.OP_RETURN); + if (opReturnIdx < 0) { + throw new TransactionBuilderError("Invalid STAS locking script", "OP_RETURN marker was not found in previous STAS locking script"); + } + const tokenIdToken = prevScriptTokens[opReturnIdx + 1]; + const symbolToken = prevScriptTokens[opReturnIdx + 2]; + if (!(tokenIdToken === null || tokenIdToken === void 0 ? void 0 : tokenIdToken.Data) || !(symbolToken === null || symbolToken === void 0 ? void 0 : symbolToken.Data)) { + throw new TransactionBuilderError("Invalid STAS locking script", "TokenId and symbol pushdatas must follow OP_RETURN in previous STAS locking script"); + } + const toknenId = (0, bytes_1.toHex)(tokenIdToken.Data); + const symbol = (0, bytes_1.bytesToUtf8)(symbolToken.Data); + const data = []; + for (let i = opReturnIdx + 3; i < prevScriptTokens.length; i++) { + const token = prevScriptTokens[i]; + if (!token.Data) { + throw new TransactionBuilderError("Invalid STAS locking script", `Unexpected opcode after OP_RETURN payload at token index ${i}`); + } + data.push(token.Data); + } + const script = new p2stas_builder_1.P2stasBuilder(to, toknenId, symbol, data); + this.Outputs.push(new output_builder_1.OutputBuilder(script, satoshis)); + return this; + }; + this.sign = (force = false) => { + for (const input of this.Inputs) { + input.sign(force); + } + return this; + }; + this.toBytes = () => { + const size = this.size(); + const buffer = new Uint8Array(size); + const bufferWriter = new binary_1.ByteWriter(buffer); + bufferWriter.writeUInt32(this.Version); + bufferWriter.writeVarInt(this.Inputs.length); + for (const input of this.Inputs) + input.writeTo(bufferWriter); + bufferWriter.writeVarInt(this.Outputs.length); + for (const output of this.Outputs) + output.writeTo(bufferWriter); + bufferWriter.writeUInt32(this.LockTime); + return buffer; + }; + this.toHex = () => (0, bytes_1.toHex)(this.toBytes()); + } + addNullDataOutput(data) { + const script = new null_data_builder_1.NullDataBuilder(data); + this.Outputs.push(new output_builder_1.OutputBuilder(script, 0)); + return this; + } + addChangeOutputWithFee(to, change, satoshisPerByte, idx = null) { + const script = new p2pkh_builder_1.P2pkhBuilder(to); + const output = new output_builder_1.OutputBuilder(script, change); + if (idx !== null) + this.Outputs.splice(idx, 0, output); + else + this.Outputs.push(output); + const fee = this.getFee(satoshisPerByte); + if (fee >= change) + throw new TransactionBuilderError(`Insufficient satoshis to pay fee`, `Insufficient satoshis to pay fee. Change: ${change}; Fee: ${fee}`); + output.Satoshis = change - fee; + return this; + } +} +exports.TransactionBuilder = TransactionBuilder; +TransactionBuilder.DefaultSequence = 0xffffffff; +TransactionBuilder.DefaultSighashType = sig_hash_type_1.SignatureHashType.SIGHASH_ALL | sig_hash_type_1.SignatureHashType.SIGHASH_FORKID; +TransactionBuilder.init = () => new TransactionBuilder(); +//# sourceMappingURL=transaction-builder.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.js.map b/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.js.map new file mode 100644 index 0000000..2489d57 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/build/transaction-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-builder.js","sourceRoot":"","sources":["../../../src/transaction/build/transaction-builder.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/index.d.ts b/vendor/dxs-bsv-token-sdk/dist/transaction/index.d.ts new file mode 100644 index 0000000..d039fd8 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/index.d.ts @@ -0,0 +1,5 @@ +export * from "./build/input-builder"; +export * from "./build/output-builder"; +export * from "./build/transaction-builder"; +export * from "./read/transaction-reader"; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/index.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/transaction/index.d.ts.map new file mode 100644 index 0000000..1296723 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transaction/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/index.js b/vendor/dxs-bsv-token-sdk/dist/transaction/index.js new file mode 100644 index 0000000..228c18c --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/index.js @@ -0,0 +1,21 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./build/input-builder"), exports); +__exportStar(require("./build/output-builder"), exports); +__exportStar(require("./build/transaction-builder"), exports); +__exportStar(require("./read/transaction-reader"), exports); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/index.js.map b/vendor/dxs-bsv-token-sdk/dist/transaction/index.js.map new file mode 100644 index 0000000..cc1886b --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transaction/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC;AACtC,yDAAuC;AACvC,8DAA4C;AAC5C,4DAA0C"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.d.ts b/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.d.ts new file mode 100644 index 0000000..decfc01 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.d.ts @@ -0,0 +1,12 @@ +import { ByteReader } from "../../binary"; +import { Bytes } from "../../bytes"; +import { Transaction } from "../../bitcoin/transaction"; +import { TransactionInput } from "../../bitcoin/transaction-input"; +import { TransactionOutput } from "../../bitcoin/transaction-output"; +export declare class TransactionReader { + static readHex: (raw: string) => Transaction; + static readBytes: (buffer: Bytes) => Transaction; + static readInput: (reader: ByteReader) => TransactionInput; + static readOutput: (reader: ByteReader) => TransactionOutput; +} +//# sourceMappingURL=transaction-reader.d.ts.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.d.ts.map b/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.d.ts.map new file mode 100644 index 0000000..b4f91d5 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-reader.d.ts","sourceRoot":"","sources":["../../../src/transaction/read/transaction-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,KAAK,EAAkB,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,qBAAa,iBAAiB;IAC5B,MAAM,CAAC,OAAO,GAAI,KAAK,MAAM,iBAA+C;IAE5E,MAAM,CAAC,SAAS,GAAI,QAAQ,KAAK,iBAgC/B;IAEF,MAAM,CAAC,SAAS,GAAI,QAAQ,UAAU,KAAG,gBAAgB,CAOvD;IAEF,MAAM,CAAC,UAAU,GAAI,QAAQ,UAAU,KAAG,iBAAiB,CAKzD;CACH"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.js b/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.js new file mode 100644 index 0000000..17115d5 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TransactionReader = void 0; +const binary_1 = require("../../binary"); +const buffer_utils_1 = require("../../buffer/buffer-utils"); +const bytes_1 = require("../../bytes"); +const transaction_1 = require("../../bitcoin/transaction"); +const transaction_input_1 = require("../../bitcoin/transaction-input"); +const transaction_output_1 = require("../../bitcoin/transaction-output"); +const strict_mode_1 = require("../../security/strict-mode"); +class TransactionReader { +} +exports.TransactionReader = TransactionReader; +TransactionReader.readHex = (raw) => TransactionReader.readBytes((0, bytes_1.fromHex)(raw)); +TransactionReader.readBytes = (buffer) => { + const reader = new binary_1.ByteReader(buffer); + const version = reader.readUInt32(); + const inputCount = reader.readVarInt(); + const inputs = []; + for (let i = 0; i < inputCount; i++) { + inputs.push(TransactionReader.readInput(reader)); + } + const outputCount = reader.readVarInt(); + const outputs = []; + for (let i = 0; i < outputCount; i++) { + outputs.push(TransactionReader.readOutput(reader)); + } + const lockTime = reader.readUInt32(); + if ((0, strict_mode_1.getStrictModeConfig)().strictTxParse && + reader.offset !== buffer.length) { + throw new Error(`Unexpected trailing bytes after locktime: ${buffer.length - reader.offset}`); + } + return new transaction_1.Transaction(buffer, inputs, outputs, version, lockTime); +}; +TransactionReader.readInput = (reader) => { + const txId = (0, buffer_utils_1.reverseBytes)(reader.readChunk(32)); + const vout = reader.readUInt32(); + const unlockingScript = reader.readVarChunk(); + const sequence = reader.readUInt32(); + return new transaction_input_1.TransactionInput((0, bytes_1.toHex)(txId), vout, unlockingScript, sequence); +}; +TransactionReader.readOutput = (reader) => { + const satoshis = reader.readUInt64(); + const lockignScript = reader.readVarChunk(); + return new transaction_output_1.TransactionOutput(satoshis, lockignScript); +}; +//# sourceMappingURL=transaction-reader.js.map \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.js.map b/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.js.map new file mode 100644 index 0000000..2d277c7 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/dist/transaction/read/transaction-reader.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transaction-reader.js","sourceRoot":"","sources":["../../../src/transaction/read/transaction-reader.ts"],"names":[],"mappings":";;;AAAA,yCAA0C;AAC1C,4DAAyD;AACzD,uCAAoD;AACpD,2DAAwD;AACxD,uEAAmE;AACnE,yEAAqE;AACrE,4DAAiE;AAEjE,MAAa,iBAAiB;;AAA9B,8CAoDC;AAnDQ,yBAAO,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,IAAA,eAAO,EAAC,GAAG,CAAC,CAAC,CAAC;AAErE,2BAAS,GAAG,CAAC,MAAa,EAAE,EAAE;IACnC,MAAM,MAAM,GAAG,IAAI,mBAAU,CAAC,MAAM,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACpC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,EAAE,CAAC;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAErC,IACE,IAAA,iCAAmB,GAAE,CAAC,aAAa;QACnC,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAC/B,CAAC;QACD,MAAM,IAAI,KAAK,CACb,6CACE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MACzB,EAAE,CACH,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,yBAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AACrE,CAAC,CAAC;AAEK,2BAAS,GAAG,CAAC,MAAkB,EAAoB,EAAE;IAC1D,MAAM,IAAI,GAAG,IAAA,2BAAY,EAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACjC,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAErC,OAAO,IAAI,oCAAgB,CAAC,IAAA,aAAK,EAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;AAC5E,CAAC,CAAC;AAEK,4BAAU,GAAG,CAAC,MAAkB,EAAqB,EAAE;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACrC,MAAM,aAAa,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IAE5C,OAAO,IAAI,sCAAiB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC,CAAC"} \ No newline at end of file diff --git a/vendor/dxs-bsv-token-sdk/package.json b/vendor/dxs-bsv-token-sdk/package.json new file mode 100644 index 0000000..d9bbdf6 --- /dev/null +++ b/vendor/dxs-bsv-token-sdk/package.json @@ -0,0 +1,86 @@ +{ + "name": "dxs-bsv-token-sdk", + "version": "1.0.4", + "description": "TypeScript SDK for Bitcoin SV with first-class DSTAS flows, older STAS helpers, and low-level BSV primitives for transaction and script work.", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/dxsapp/dxs-bsv-token-sdk" + }, + "directories": { + "test": "tests" + }, + "author": "oleg@dxs.app (https://github.com/panagushin)", + "license": "MIT", + "files": [ + "dist", + "README.md" + ], + "dependencies": { + "@noble/curves": "^2.0.1", + "@noble/hashes": "^2.0.1", + "@noble/secp256k1": "^3.0.0", + "@scure/base": "^2.0.0", + "@scure/bip32": "^2.0.1", + "@scure/bip39": "^2.0.1" + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.js", + "default": "./dist/index.js" + }, + "./bsv": { + "types": "./dist/bsv.d.ts", + "import": "./dist/bsv.js", + "require": "./dist/bsv.js", + "default": "./dist/bsv.js" + }, + "./dstas": { + "types": "./dist/dstas.d.ts", + "import": "./dist/dstas.js", + "require": "./dist/dstas.js", + "default": "./dist/dstas.js" + }, + "./stas": { + "types": "./dist/stas.d.ts", + "import": "./dist/stas.js", + "require": "./dist/stas.js", + "default": "./dist/stas.js" + }, + "./script/read/locking-script-reader": { + "types": "./dist/script/read/locking-script-reader.d.ts", + "import": "./dist/script/read/locking-script-reader.js", + "require": "./dist/script/read/locking-script-reader.js", + "default": "./dist/script/read/locking-script-reader.js" + }, + "./script/build/dstas-locking-builder": { + "types": "./dist/script/build/dstas-locking-builder.d.ts", + "import": "./dist/script/build/dstas-locking-builder.js", + "require": "./dist/script/build/dstas-locking-builder.js", + "default": "./dist/script/build/dstas-locking-builder.js" + }, + "./script/eval/script-evaluator": { + "types": "./dist/script/eval/script-evaluator.d.ts", + "import": "./dist/script/eval/script-evaluator.js", + "require": "./dist/script/eval/script-evaluator.js", + "default": "./dist/script/eval/script-evaluator.js" + }, + "./package.json": "./package.json" + }, + "homepage": "https://github.com/dxsapp/dxs-bsv-token-sdk", + "bugs": { + "url": "https://github.com/dxsapp/dxs-bsv-token-sdk/issues" + }, + "keywords": [ + "bitcoin-sv", + "dstas", + "stas", + "typescript", + "bsv", + "bitcoin-script", + "sdk" + ] +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 32a4348..df9eb85 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,10 +1,20 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; +import { nodePolyfills } from 'vite-plugin-node-polyfills'; import path from 'path'; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [react()], + plugins: [ + react(), + // Polyfill Node globals (Buffer, process, global, etc.) for the + // browser. Needed by legacy bsv@1.5.6 (which stas-js depends on) — + // it references Node primitives throughout its module bodies. + nodePolyfills({ + globals: { Buffer: true, global: true, process: true }, + protocolImports: true, + }), + ], resolve: { alias: { '@': path.resolve(__dirname, './src'), @@ -15,8 +25,47 @@ export default defineConfig({ build: { outDir: 'dist', emptyOutDir: true, + // Force Rollup's CommonJS plugin to run on the vendored dxs SDK + // dist files. Without this, prod builds fail with + // *"ScriptType is not exported by …/bsv.js"* etc. — Rollup sees the + // CJS source raw and can't extract named exports. The + // `transformMixedEsModules: true` flag handles the SDK's runtime + // `__exportStar(require("./submodule"), exports)` pattern for the + // ./script subtree (where LockingScriptReader lives). Vite dev is + // unaffected (esbuild pre-bundles via optimizeDeps). + commonjsOptions: { + include: [/dxs-bsv-token-sdk/, /node_modules/], + transformMixedEsModules: true, + }, }, server: { port: 5173, }, + // dxs-bsv-token-sdk is a CJS package installed via `file:` (sibling dir). + // Vite's auto-discovery does not reliably pre-bundle file:-linked subpaths, + // and serving raw CJS to the browser breaks named-export imports + // (e.g. `import { LockingScriptReader } from 'dxs-bsv-token-sdk/bsv'`). + // Listing the subpaths here forces esbuild pre-bundling, which converts the + // CJS exports into ESM named exports. + optimizeDeps: { + include: [ + 'dxs-bsv-token-sdk/bsv', + 'dxs-bsv-token-sdk/dstas', + // SDK leaf-module paths — same ones the wallet imports directly to + // bypass Rollup's `__exportStar` blindness on prod builds. Without + // these here, Vite dev serves the raw CJS files to the browser and + // they explode with "exports is not defined". The leaf paths are + // whitelisted in the SDK's package.json `exports` field. + 'dxs-bsv-token-sdk/script/read/locking-script-reader', + 'dxs-bsv-token-sdk/script/build/dstas-locking-builder', + 'dxs-bsv-token-sdk/script/eval/script-evaluator', + // stas-js + its bsv-js peer for the BRC-100 STAS transfer path. + // Explicit file paths — stas-js's package.json points `module` at + // `dist/index` but ships no `dist/` folder, so plain `stas-js` + // resolution fails. Bypass via the file paths directly. + 'stas-js/index.js', + 'stas-js/lib/stas.js', + 'bsv', + ], + }, }); From 1086f74595d26ba875f5bc8f2bb23e8f2141a5d5 Mon Sep 17 00:00:00 2001 From: Deggen Date: Thu, 16 Jul 2026 09:04:56 +0100 Subject: [PATCH 2/3] fix(ci): add missing menu_transfers translation key The Transfers menu item added by the token-integration merge referenced menu_transfers via t(), but the key didn't exist in translations.ts for any language, failing the translation-coverage test. --- src/lib/i18n/translations.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lib/i18n/translations.ts b/src/lib/i18n/translations.ts index 2a64aa6..472a5e8 100644 --- a/src/lib/i18n/translations.ts +++ b/src/lib/i18n/translations.ts @@ -531,6 +531,7 @@ const en = { menu_profiles_identity_key: 'Identity Key', menu_new_profile: 'New Profile', menu_apps: 'Apps', + menu_transfers: 'Transfers', menu_transactions: 'Transactions', menu_identity: 'Identity', menu_trust: 'Trust', @@ -1458,6 +1459,7 @@ const es = { menu_profiles_identity_key: 'Clave de Identidad', menu_new_profile: 'Nuevo Perfil', menu_apps: 'Aplicaciones', + menu_transfers: 'Transferencias', menu_transactions: 'Transacciones', menu_identity: 'Identidad', menu_trust: 'Confianza', @@ -2397,6 +2399,7 @@ const fr = { menu_profiles_identity_key: 'Clé d\'Identité', menu_new_profile: 'Nouveau Profil', menu_apps: 'Applications', + menu_transfers: 'Transferts', menu_transactions: 'Transactions', menu_identity: 'Identité', menu_trust: 'Confiance', @@ -3336,6 +3339,7 @@ const pt = { menu_profiles_identity_key: 'Chave de Identidade', menu_new_profile: 'Novo Perfil', menu_apps: 'Aplicativos', + menu_transfers: 'Transferências', menu_transactions: 'Transações', menu_identity: 'Identidade', menu_trust: 'Confiança', @@ -4275,6 +4279,7 @@ const zh = { menu_profiles_identity_key: '身份密钥', menu_new_profile: '新建账户', menu_apps: '应用', + menu_transfers: '转账', menu_transactions: '交易', menu_identity: '身份', menu_trust: '信任', @@ -5214,6 +5219,7 @@ const hi = { menu_profiles_identity_key: 'पहचान कुंजी', menu_new_profile: 'नई प्रोफाइल', menu_apps: 'ऐप्स', + menu_transfers: 'स्थानांतरण', menu_transactions: 'लेन-देन', menu_identity: 'पहचान', menu_trust: 'विश्वास', @@ -6153,6 +6159,7 @@ const bn = { menu_profiles_identity_key: 'পরিচয় কী', menu_new_profile: 'নতুন প্রোফাইল', menu_apps: 'অ্যাপস', + menu_transfers: 'স্থানান্তর', menu_transactions: 'লেনদেন', menu_identity: 'পরিচয়', menu_trust: 'বিশ্বাস', @@ -7092,6 +7099,7 @@ const ar = { menu_profiles_identity_key: 'مفتاح الهوية', menu_new_profile: 'ملف شخصي جديد', menu_apps: 'التطبيقات', + menu_transfers: 'التحويلات', menu_transactions: 'المعاملات', menu_identity: 'الهوية', menu_trust: 'الثقة', @@ -8031,6 +8039,7 @@ const ru = { menu_profiles_identity_key: 'Ключ идентификации', menu_new_profile: 'Новый профиль', menu_apps: 'Приложения', + menu_transfers: 'Переводы', menu_transactions: 'Транзакции', menu_identity: 'Идентификация', menu_trust: 'Доверие', @@ -8970,6 +8979,7 @@ const id = { menu_profiles_identity_key: 'Kunci Identitas', menu_new_profile: 'Profil Baru', menu_apps: 'Aplikasi', + menu_transfers: 'Transfer', menu_transactions: 'Transaksi', menu_identity: 'Identitas', menu_trust: 'Kepercayaan', @@ -9972,6 +9982,7 @@ const ja = { menu_profiles_identity_key: 'IDキー', menu_new_profile: '新しいプロファイル', menu_apps: 'アプリ', + menu_transfers: '送金', menu_transactions: 'トランザクション', menu_identity: 'ID', menu_trust: '信頼', @@ -10957,6 +10968,7 @@ const pl = { menu_profiles_identity_key: 'Klucz tożsamości', menu_new_profile: 'Nowy profil', menu_apps: 'Aplikacje', + menu_transfers: 'Transfery', menu_transactions: 'Transakcje', menu_identity: 'Tożsamość', menu_trust: 'Zaufanie', From 848cdd736fbbbe221725b73cea42253b2c8e5acf Mon Sep 17 00:00:00 2001 From: Deggen Date: Thu, 16 Jul 2026 09:39:58 +0100 Subject: [PATCH 3/3] fix(ci): drop Node 18.x from Install and Test matrix better-sqlite3@12.x and @electron/rebuild@4.x already require Node >=20/22; the 18.x job only appeared to pass because push.yaml's cache key hashes only package.json, so PRs that don't touch it get a stale cache hit and skip npm install (and its postinstall rebuild) entirely. This PR's dependency changes miss that cache and hit the real, already pre-existing incompatibility. --- .github/workflows/push.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index aed29f8..e4529ef 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [18.x, 20.x, 22.x] + node-version: [20.x, 22.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }}