@laceio/sdk 0.1.1 → 0.1.2-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{TransactionBuilder-DrB3NVTi.cjs → TransactionBuilder-X1H9Gze6.cjs} +64 -14
- package/dist/{TransactionBuilder-V6aLx4SV.js → TransactionBuilder-bp2aMDhg.js} +23 -15
- package/dist/{_polyfill-buffer-patch-BnPVerlG.cjs → _polyfill-buffer-patch-CM8X7JiY.cjs} +21 -2
- package/dist/_polyfill-buffer-patch-yNxN4d5E.js +1467 -0
- package/dist/_web-crypto-random-bytes-Bo-GTcRS.js +197 -0
- package/dist/acc-module-4iIUv6My.cjs +27654 -0
- package/dist/acc-module-Cmj8EsIb.js +27624 -0
- package/dist/account-BOQruszJ.js +6 -0
- package/dist/account-BUOj4pYJ.cjs +11 -0
- package/dist/account-call-7wnopBq0.cjs +5 -0
- package/dist/account-call-B9d_2Xwi.js +4 -0
- package/dist/account-call-Bd4Rpbvt.cjs +323 -0
- package/dist/account-call-C3CkDqEC.js +276 -0
- package/dist/account-guards-BtjTGxDZ.cjs +42 -0
- package/dist/account-guards-D9Lu5T3W.js +36 -0
- package/dist/account-tokens-DvkOFVON.js +16 -0
- package/dist/account-tokens-nwcvwLu4.cjs +21 -0
- package/dist/{activity-type.stable-BJEfeLxL.cjs → activity-type-Ch6ljxBy.cjs} +2 -1
- package/dist/{activity-type.stable-C76_hWd7.js → activity-type-GsJGWs-3.js} +2 -1
- package/dist/address-B9ntKL8K.js +13761 -0
- package/dist/address-BXp-mY8H.cjs +11270 -0
- package/dist/{address-book-address-validator-DIUolI-s.js → address-book-address-validator-0J9XAADH.js} +2 -2
- package/dist/address-book-address-validator-DK0dnsRS.cjs +41 -0
- package/dist/address-book-address-validator-Di_ywo8M.js +39 -0
- package/dist/{address-book-address-validator-DNwQGlOB.cjs → address-book-address-validator-Dte_YQ2L.cjs} +2 -2
- package/dist/artefact-loader-BWWYAD7E.cjs +183 -0
- package/dist/artefact-loader-Dik4HIfv.js +160 -0
- package/dist/auto-dismiss-failure-on-success-C-qoJuid.cjs +37 -0
- package/dist/auto-dismiss-failure-on-success-s8MGDEIu.js +31 -0
- package/dist/bip32-D6wd_QMn.cjs +3851 -0
- package/dist/bitcoin-data-provider-BYPSmuZS.js +21 -0
- package/dist/bitcoin-data-provider-w1oEDSU3.cjs +26 -0
- package/dist/bitcoin.cjs +45 -0
- package/dist/bitcoin.d.ts +29906 -1
- package/dist/bitcoin.js +20 -0
- package/dist/{blockfrost-tx-submit-provider-DPTrapz-.js → blockfrost-tx-submit-provider-CBWQ0wK9.js} +5 -157
- package/dist/{blockfrost-tx-submit-provider-BAIzV5o3.cjs → blockfrost-tx-submit-provider-CLNQ5ycR.cjs} +3 -167
- package/dist/bn-d3nSOIf7.cjs +2553 -0
- package/dist/browser-B1eMbDwh.js +7468 -0
- package/dist/bytes.vo-BB7_4JK6.js +23 -0
- package/dist/bytes.vo-BNRquqaO.cjs +34 -0
- package/dist/cardano-DfPwhwm-.js +3 -0
- package/dist/{cardano-network-id.vo-DSxrFk9S.cjs → cardano-network-id.vo-BEDPn6Li.cjs} +1 -1
- package/dist/{cardano-network-id.vo-CK1tNQDg.js → cardano-network-id.vo-Cfpvbod9.js} +1 -1
- package/dist/cardano.cjs +22 -18
- package/dist/cardano.d.ts +16962 -1716
- package/dist/cardano.js +16 -11
- package/dist/client-DXBLHk7K.cjs +808 -0
- package/dist/codecs-Cswkg7Tm.cjs +4051 -0
- package/dist/codecs-Dc1Krpbt.js +3903 -0
- package/dist/{const-C84qHkjp.js → const-BJfIK_G-.js} +4 -4
- package/dist/const-BhYOdznB.cjs +42 -0
- package/dist/const-BsnjG2_Q.cjs +32071 -0
- package/dist/const-CUnCl5U0.js +13 -0
- package/dist/{const-DXk2tFyv.js → const-CjmfjBP3.js} +1 -1
- package/dist/{const-BDEg2Trq.cjs → const-D-eZIS4n.cjs} +4 -4
- package/dist/const-D0CbQlo4.js +154 -0
- package/dist/{const-BY8B3_0_.cjs → const-iwzZEE_w.cjs} +1 -1
- package/dist/contract-1R86jhSw.js +171 -0
- package/dist/contract-MKLzYVkW.cjs +189 -0
- package/dist/create-add-accounts-Brqk84vF.js +102 -0
- package/dist/create-add-accounts-DzXIh7Ot.cjs +114 -0
- package/dist/{delegation-tx-builder-CRpLP6jH.cjs → delegation-tx-builder-Dof_0N_d.cjs} +6 -6
- package/dist/{delegation-tx-builder-CGVqlaFE.js → delegation-tx-builder-Dy3-2Auz.js} +5 -5
- package/dist/{deregistration-tx-builder-DZGwB4cz.cjs → deregistration-tx-builder-CcLwyFpj.cjs} +6 -6
- package/dist/{deregistration-tx-builder-B-CrUyX6.js → deregistration-tx-builder-QkWW_gWl.js} +5 -5
- package/dist/device-commitment-hex.vo-5wFtQvDS.js +26 -0
- package/dist/device-commitment-hex.vo-CT3RmAug.cjs +31 -0
- package/dist/device-readers-CUHYoYOH.js +145 -0
- package/dist/device-readers-CdxS2btd.cjs +168 -0
- package/dist/device-readers-D_JZeNL2.cjs +8 -0
- package/dist/device-readers-DwSNCGPP.js +4 -0
- package/dist/dist-BMi5ZjEq.cjs +43175 -0
- package/dist/dist-BtIq4XFn.cjs +535 -0
- package/dist/dist-C3SHC_Ho.cjs +1394 -0
- package/dist/dist-CykEjYEX.cjs +3814 -0
- package/dist/dist-Dcsxh3be.cjs +3452 -0
- package/dist/dist-DqJfSlTd.cjs +4413 -0
- package/dist/dist-nTZ70qj7.cjs +1306 -0
- package/dist/{earn-rewards-tx-builder-D5sUT5v8.cjs → earn-rewards-tx-builder-BP5JMIKS.cjs} +6 -6
- package/dist/{earn-rewards-tx-builder-BDbTDZmD.js → earn-rewards-tx-builder-Cku4BmNU.js} +5 -5
- package/dist/enc-key-circuits-B7BjgUL9.js +13 -0
- package/dist/enc-key-circuits-BLrZrBVI.cjs +24 -0
- package/dist/english-Byb9M0E_.cjs +2057 -0
- package/dist/envelopes-BGoO_v8m.js +1621 -0
- package/dist/envelopes-CH25R-DN.cjs +1722 -0
- package/dist/errors-BIftM8ZN.cjs +688 -0
- package/dist/errors-DSq5wUwt.js +466 -0
- package/dist/esm-HBSUQw3w.js +384 -0
- package/dist/esm-LZuaZjMf.cjs +389 -0
- package/dist/experimental.cjs +7349 -0
- package/dist/experimental.d.ts +86279 -0
- package/dist/experimental.js +7184 -0
- package/dist/gated-call-CDCVZIK-.cjs +5 -0
- package/dist/gated-call-D-tT7P_t.js +722 -0
- package/dist/gated-call-D_VT2quk.js +4 -0
- package/dist/gated-call-DgJm1Mi_.cjs +787 -0
- package/dist/grant-circuits-DswmW3nI.cjs +71 -0
- package/dist/grant-circuits-Jxb5y1HW.js +42 -0
- package/dist/grant-rules-By07_eDi.js +6824 -0
- package/dist/grant-rules-BzVTWXS7.cjs +7099 -0
- package/dist/grant-spend-B3Md9L0n.js +215 -0
- package/dist/grant-spend-oWmzRsjH.cjs +217 -0
- package/dist/grant-status-B2y49iIu.js +2688 -0
- package/dist/grant-status-DOr3t_u8.cjs +2820 -0
- package/dist/grants-2BZ-qEVQ.js +5 -0
- package/dist/grants-BPoLSiMt.cjs +18 -0
- package/dist/grants-BoI5uwSF.cjs +272 -0
- package/dist/grants-CtofFu-e.js +213 -0
- package/dist/{group-cardano-addresses-by-account-B533oVXR.cjs → group-cardano-addresses-by-account-Bp0g4wEY.cjs} +3 -39
- package/dist/{group-cardano-addresses-by-account-RHKoEskR.js → group-cardano-addresses-by-account-SR8MMrZf.js} +5 -35
- package/dist/{guarded-transaction-signer-Bxl6_XNd.cjs → guarded-transaction-signer-MFpPg98D.cjs} +17 -18
- package/dist/{guarded-transaction-signer-CpKLj8Kp.js → guarded-transaction-signer-P6Rp1faj.js} +8 -15
- package/dist/hex-D9ITYbwt.cjs +263 -0
- package/dist/hex-mkXcV3pN.js +191 -0
- package/dist/http-client-B3N-TMxu.cjs +167 -0
- package/dist/http-client-TRlhDZGh.js +155 -0
- package/dist/identity-BMLuufva.cjs +263 -0
- package/dist/identity-DII6f-h7.js +233 -0
- package/dist/in-memory-wallet-integration-B2xzxORj.cjs +20741 -0
- package/dist/in-memory-wallet-integration-CBRiPjLO.js +130 -0
- package/dist/in-memory-wallet-integration-CULUB5Tf.cjs +240 -0
- package/dist/{in-memory-wallet-integration-D-qn65Kx.js → in-memory-wallet-integration-ChIOirMW.js} +5 -2
- package/dist/{in-memory-wallet-integration-Croiuopx.js → in-memory-wallet-integration-CljprQQV.js} +7 -104
- package/dist/{in-memory-wallet-integration-DVh9sRXa.cjs → in-memory-wallet-integration-Cm6P8sk6.cjs} +3 -2
- package/dist/in-memory-wallet-integration-TM9bBphA.js +20738 -0
- package/dist/{in-memory-wallet-integration-CnLYeX4-.cjs → in-memory-wallet-integration-t9I00R_V.cjs} +17 -108
- package/dist/index.cjs +84 -47
- package/dist/index.d.ts +37505 -10036
- package/dist/index.js +52 -24
- package/dist/{init-CLHuAMB-.js → init-0zzs9aqU.js} +4 -4
- package/dist/{init-U8c9yHYx.cjs → init-5KcGcBb5.cjs} +1 -1
- package/dist/{init-CigestoM.js → init-B3-1ghyx.js} +2 -2
- package/dist/init-B8U3ABhS.cjs +107 -0
- package/dist/init-BJn-8_hf.js +141 -0
- package/dist/init-BPU3j8sT.cjs +6 -0
- package/dist/init-BRzH6xu-2.cjs +2797 -0
- package/dist/init-BmzfDaKL.js +1142 -0
- package/dist/{init-C-jErzp5.cjs → init-BopV9ed4.cjs} +2 -2
- package/dist/init-BpHTq2R5.js +105 -0
- package/dist/init-BpSITBfF.js +39 -0
- package/dist/{init-DX4WyB0R.cjs → init-BrdVzxei.cjs} +3 -3
- package/dist/{init-LfyMo-sS.cjs → init-BwkU0ruo.cjs} +2 -2
- package/dist/{init-CB__aLD7.cjs → init-C-G32J12.cjs} +2 -2
- package/dist/init-C00gw1zi.js +422 -0
- package/dist/{init-TkPq_Ny_.js → init-C2RgrfZe.js} +1 -1
- package/dist/init-C5mYyFTv.js +3584 -0
- package/dist/{init-DcYY6zMD.js → init-C8URA2OX.js} +1 -1
- package/dist/init-CDkRynJa.js +2796 -0
- package/dist/{init-Cg9XdAru.js → init-CNM5m7M2.js} +4 -4
- package/dist/init-CR7BfztQ.cjs +18 -0
- package/dist/{init-CSHwHnfg.cjs → init-CSDpdu0Q.cjs} +2 -2
- package/dist/{init-aJHl-7AO.js → init-CX0AMQUn.js} +2 -2
- package/dist/{init-FMGDET-9.js → init-CfTbSEKy.js} +259 -60
- package/dist/{init-CR6tpw1B.js → init-Cigr_tKx.js} +47 -43
- package/dist/init-Clu8pxwQ.cjs +1181 -0
- package/dist/{init-CFYsq82V.js → init-CyAY4Lzl.js} +1 -1
- package/dist/{init-BKhH6mVR.cjs → init-D6BxBs7e.cjs} +1 -1
- package/dist/init-D8OeObDF.cjs +1141 -0
- package/dist/init-D9g1HXYf.cjs +40 -0
- package/dist/{init-CNLGJJRx.js → init-DA7zmptx.js} +1 -1
- package/dist/{init-DkIc5nqF.cjs → init-DFMiP2ZH.cjs} +1 -1
- package/dist/{init-zSzCjoor.js → init-DFjT8YvT.js} +4 -4
- package/dist/init-DGjXwWs2.cjs +143 -0
- package/dist/init-DHrCbpkW.cjs +121 -0
- package/dist/init-DRzJR02G.cjs +3585 -0
- package/dist/{init-B64zCLxG.cjs → init-DUF4ar8P.cjs} +4 -4
- package/dist/init-DlqJuHhl.js +119 -0
- package/dist/{init-y2Ra0vZP.js → init-Dnsv155v.js} +3 -3
- package/dist/init-DuYENxci.js +17 -0
- package/dist/{init-D6DBUsD3.cjs → init-Dv3zKj0r.cjs} +4 -4
- package/dist/{init-BtzMZ7Pk.cjs → init-Dy-05ktr.cjs} +1 -1
- package/dist/{init-BsCBAGWf.cjs → init-EP0CUWNK.cjs} +2 -2
- package/dist/{init-BJVU54pI.cjs → init-EhzD7a8i.cjs} +1 -1
- package/dist/{init-w9GEs73W.js → init-Fw89ZmrR.js} +2 -2
- package/dist/init-GsT2AEa4.cjs +424 -0
- package/dist/{init-Rxohwpmu.js → init-NCjgwCZy.js} +2 -2
- package/dist/{init-DxUHsN53.cjs → init-NdhG_VrF.cjs} +6 -6
- package/dist/{init-DDdhguVC.js → init-SZ01tARX2.js} +2 -2
- package/dist/{init-BAJJzBza.js → init-Y3mkB4XS.js} +2 -2
- package/dist/init-c4l6r-o-.js +5 -0
- package/dist/{init-Dku4b2lG.js → init-kEfUTuG2.js} +1 -1
- package/dist/{init-C7IeJwQR.cjs → init-lzHt4Cli.cjs} +256 -59
- package/dist/init-qSEd_Spq.js +1182 -0
- package/dist/{init-anYu6XB7.cjs → init-rmt7-fQE.cjs} +2 -2
- package/dist/{init-C4Bkib9u.cjs → init-zU-_9Gsp.cjs} +67 -65
- package/dist/{is-retriable-error-BU0e3hVI.js → is-retriable-error-BUiVJDwH.js} +1 -1
- package/dist/{is-retriable-error-CeeuHqDa.cjs → is-retriable-error-Dpt860if.cjs} +1 -1
- package/dist/jubjub-authoriser-D7zDXu3V.js +86 -0
- package/dist/jubjub-authoriser-Dgu6o3Sv.cjs +87 -0
- package/dist/key-source-5oUBFiC7.cjs +583 -0
- package/dist/key-source-B08HukZg.js +2550 -0
- package/dist/keyDerivation-D3k9XyHg.js +4077 -0
- package/dist/keyDerivation-u0nBA93T.cjs +274 -0
- package/dist/{lace-context-CZcNHr4M.js → lace-context-BZciB9c7.js} +4 -4
- package/dist/{lace-context-fJTDghdp.cjs → lace-context-DgR6vLli.cjs} +4 -4
- package/dist/lib--iqvW4O_.js +2354 -0
- package/dist/lib-Yk6Upl5D.cjs +2359 -0
- package/dist/{libsodium-wrappers-UH0LaOUE.js → libsodium-wrappers-BhbOA8dQ.js} +3 -1647
- package/dist/midnight-account-id.vo-0x9X-r3l.cjs +10 -0
- package/dist/midnight-account-id.vo-DjCAGcqc.js +5 -0
- package/dist/midnight-engine-DpemplKO.js +5 -0
- package/dist/midnight-engine-xU1wotne.cjs +6 -0
- package/dist/midnight-wallet-DIsAlSn6.js +18 -0
- package/dist/midnight-wallet-XTZc2li7.cjs +24 -0
- package/dist/midnight.cjs +1408 -0
- package/dist/midnight.d.ts +28934 -0
- package/dist/midnight.js +1352 -0
- package/dist/modules-cardano-D9Gs2j60.cjs +1108 -0
- package/dist/modules-cardano-VIM8fKu-.js +995 -0
- package/dist/node-relay-DWe1U0w2.cjs +49 -0
- package/dist/node-relay-h4i5IlAQ.js +48 -0
- package/dist/outputs-Bd2yZVjx.js +720 -0
- package/dist/outputs-CJoQBIA2.cjs +990 -0
- package/dist/pbkdf2-CIW-oWrm.cjs +1337 -0
- package/dist/pending-operation-B0_P78Jo.cjs +26 -0
- package/dist/pending-operation-BIS6mpjB.js +21 -0
- package/dist/providers-FjhM47BH.cjs +388 -0
- package/dist/providers-WtiSuxFu.js +365 -0
- package/dist/redacted-BmE2aXqr.js +81 -0
- package/dist/redacted-CRZJLS3w.cjs +86 -0
- package/dist/{retry-config-DC5IMaH7.cjs → retry-config-BaCfVC1H.cjs} +1 -1
- package/dist/{retry-config-BcUmMS--.js → retry-config-Dmgt28wM.js} +1 -1
- package/dist/safe-buffer-B_vMqJWU.js +43 -0
- package/dist/safe-buffer-DYOwEfHB.cjs +48 -0
- package/dist/sdk-Cb-gZnS9.js +1241 -0
- package/dist/sdk-DffwmX8b.cjs +1439 -0
- package/dist/sdk-init-Bln9rFtn.js +4138 -0
- package/dist/sdk-init-CYViTJY_.cjs +3841 -0
- package/dist/{seam-cardano-CATqBEyK.js → seam-cardano-B_etH4F4.js} +1 -1
- package/dist/{bytes.vo-TgiwogWF.js → secret-box-DUR0ACYz.js} +3 -25
- package/dist/{bytes.vo-Ck5u40RA.cjs → secret-box-DrjLZuS1.cjs} +1 -35
- package/dist/send-proof-progress-C-ljq1x5.js +30 -0
- package/dist/send-proof-progress-vmsaSfbz.cjs +47 -0
- package/dist/side-effects-BnqYz7Nl.js +768 -0
- package/dist/side-effects-CngaeXi0.cjs +804 -0
- package/dist/sign-bitcoin-transaction-with-seed-D4z62-jV.js +147 -0
- package/dist/sign-bitcoin-transaction-with-seed-DsLYXnCY.cjs +158 -0
- package/dist/signer-3fk8lZtE.cjs +7 -0
- package/dist/signer-CsL28DrK.cjs +121 -0
- package/dist/signer-DGluibtn.js +92 -0
- package/dist/signer-RqB5pu3K.js +2 -0
- package/dist/signer-factory-BA7WFJVZ.js +282 -0
- package/dist/signer-factory-Cwd6o-lG.cjs +281 -0
- package/dist/{signer-factory-9URFliA5.js → signer-factory-DObB55D4.js} +6 -3
- package/dist/signer-factory-DhZiE03y.cjs +149 -0
- package/dist/{signer-factory-BWGUmnvm.cjs → signer-factory-Ds6G2AZk.cjs} +4 -3
- package/dist/signer-factory-hzSRaIw2.js +148 -0
- package/dist/{slice-CuHUaPZx.cjs → slice-7G2xxYKJ.cjs} +3 -3
- package/dist/{slice-DZmQJNV8.cjs → slice-B4CdYoPu.cjs} +2 -2
- package/dist/slice-BPNuHKfw.js +9091 -0
- package/dist/{slice-DGcNrbPR.cjs → slice-Bg6HEr3K.cjs} +4 -4
- package/dist/{slice-DtaO72qY.cjs → slice-Bs2aMERu.cjs} +3 -3
- package/dist/{slice-HeHCv3bl.cjs → slice-C34iOOUH.cjs} +7 -7
- package/dist/{slice-Do2R2CYW.cjs → slice-C9TT5KhY.cjs} +6 -6
- package/dist/{slice-eIwcwKHI.js → slice-CK07EBCo.js} +4 -4
- package/dist/{slice-CnyWevM9.js → slice-CU80pbiu.js} +3 -3
- package/dist/{slice-CobanYgn.js → slice-CwyYrh1H.js} +2 -2
- package/dist/slice-Czfp6t84.cjs +436 -0
- package/dist/{slice-d0p6-xj5.js → slice-D-9aPKG-.js} +6 -6
- package/dist/{slice-maaskdUn.js → slice-DBpJ2QGf.js} +6 -6
- package/dist/{slice-mxLQ_FeY.cjs → slice-DTZTiJle.cjs} +352 -39
- package/dist/{slice-zJ9XVYjZ.js → slice-Da426sf9.js} +1 -1
- package/dist/{slice-D11m2EKl.cjs → slice-DayJvMRD.cjs} +1 -1
- package/dist/slice-DnBWfA-k.cjs +9109 -0
- package/dist/{slice-oqm_r1cS.cjs → slice-DnG-yvpI.cjs} +2 -2
- package/dist/{slice-BNu73oBa.js → slice-DyNs7oWp.js} +2 -2
- package/dist/{slice-CB4SnzMm.js → slice-GwiiJRoq.js} +3 -3
- package/dist/slice-oWnc7YVD.js +412 -0
- package/dist/{slice-B2PhoWAg.js → slice-qt0uBExh.js} +325 -37
- package/dist/slice-t8Gzj55G2.cjs +106 -0
- package/dist/slice-t8Q1cHm-.js +88 -0
- package/dist/src-BDzYIksE.cjs +20637 -0
- package/dist/src-BFoefPv_.js +20755 -0
- package/dist/store-B1Lq3cEf.cjs +66 -0
- package/dist/store-DuBG8qh5.js +37 -0
- package/dist/submit-Bs77dPn_.cjs +413 -0
- package/dist/submit-DOv8Z0Vf.js +336 -0
- package/dist/submit-bitcoin-tx-D6oYgH5S.js +983 -0
- package/dist/submit-bitcoin-tx-goFuRL7K.cjs +1049 -0
- package/dist/{sync-operation-utils-BYXLO80m.js → sync-operation-utils-31iFLExW.js} +2 -38
- package/dist/{sync-operation-utils-SdPbwFoD.cjs → sync-operation-utils-COIZ66-I.cjs} +1 -67
- package/dist/token-id-mapper-Bnds3xKH.cjs +18 -0
- package/dist/{token-id-mapper-DsPAL6Nh.cjs → token-id-mapper-CVyQJUKY.cjs} +2 -2
- package/dist/token-id-mapper-CnKHQ8DV.js +16 -0
- package/dist/{token-id-mapper-B2ivlLv3.js → token-id-mapper-D29Ggv8h.js} +2 -2
- package/dist/tokens-Cevp7rdU.cjs +62 -0
- package/dist/tokens-Diw4MLRM.js +44 -0
- package/dist/types-B8uiJn-X.js +12 -0
- package/dist/types-BHC12eSa.js +33 -0
- package/dist/types-CJT6XF2c.js +10 -0
- package/dist/types-CLRUYpfe.cjs +23 -0
- package/dist/types-Cc3mC8u0.cjs +50 -0
- package/dist/types-DWbVZpnF.cjs +15 -0
- package/dist/unwrap-provider-result-BZSiwabU.js +32 -0
- package/dist/unwrap-provider-result-ZqfBsTkk.cjs +39 -0
- package/dist/{util-CGzqQ8IV.cjs → util-Bu4W5lF4.cjs} +1 -1
- package/dist/{util-BaLzwa32.js → util-Cp5cZkfK.js} +1 -1
- package/dist/{utils-o8aMjfln.js → utils-BfBEUvWA.js} +2 -2
- package/dist/utils-DFwzEvbv.js +65 -0
- package/dist/{utils-5JvjbqH3.cjs → utils-DsElZgCI.cjs} +7 -1
- package/dist/utils-IXxR-Djh.cjs +112 -0
- package/dist/v8Signatures-CO_Uloy7.cjs +71 -0
- package/dist/{vote-delegation-tx-builder-CmKv6GoG.js → vote-delegation-tx-builder-BsBSDmcX.js} +5 -5
- package/dist/{vote-delegation-tx-builder-BpEMSti4.cjs → vote-delegation-tx-builder-DSs8nybk.cjs} +6 -6
- package/dist/watch-CUEvcP-V.js +21997 -0
- package/dist/watch-DMF2s-II.cjs +52281 -0
- package/package.json +96 -4
- package/dist/account-guards.stable-B1DSSh9D.cjs +0 -10
- package/dist/account-guards.stable-JRQ5qx2V.js +0 -5
- package/dist/codecs-B7X9pAsK.cjs +0 -1945
- package/dist/codecs-CC1Xjntz.js +0 -1882
- package/dist/init-Bv53hpLM.js +0 -19
- package/dist/init-CRbjI7p1.js +0 -3494
- package/dist/init-DAna1KCg.cjs +0 -3495
- package/dist/init-DGe47B22.cjs +0 -364
- package/dist/init-DMtyvYfC.cjs +0 -21
- package/dist/init-TkPDD750.js +0 -363
- package/dist/modules-cardano-BDvuL4Xx.js +0 -5248
- package/dist/modules-cardano-D2G3De2P.cjs +0 -5432
- package/dist/slice-CGVHXHDt.cjs +0 -125
- package/dist/slice-DhvF7L6X.js +0 -107
- /package/dist/{account-id.vo-LvCBVn5r.cjs → account-id.vo-DwqFjK5u.cjs} +0 -0
- /package/dist/{account-id.vo-MYSI7YFm.js → account-id.vo-OPz2v-JZ.js} +0 -0
- /package/dist/{actions-DdGbj7c7.cjs → actions-B2BJ4RTy.cjs} +0 -0
- /package/dist/{actions-9QSQR-GB.js → actions-iLXdgL5Y.js} +0 -0
- /package/dist/{apply-vkey-witnesses-ClZbpk5w.js → apply-vkey-witnesses-BKx3lcs0.js} +0 -0
- /package/dist/{apply-vkey-witnesses-CLzVSWxl.cjs → apply-vkey-witnesses-ZnFS0jnJ.cjs} +0 -0
- /package/dist/{asyncoption-Cw07zPH7.js → asyncoption-CruEYOBI.js} +0 -0
- /package/dist/{asyncoption-DYoGuQfP.cjs → asyncoption-i0VbqVTq.cjs} +0 -0
- /package/dist/{bignum.vo-B0rK_PQ1.js → bignum.vo-CEXOIew0.js} +0 -0
- /package/dist/{bignum.vo-DsG3kNiZ.cjs → bignum.vo-hx2kuqlA.cjs} +0 -0
- /package/dist/{bip32ed25519-1ApqeAZk.cjs → bip32ed25519-B7Yat217.cjs} +0 -0
- /package/dist/{bip32ed25519-DetAdGwD.js → bip32ed25519-FQ8qvdcq.js} +0 -0
- /package/dist/{blake2b-DOEVc57D.js → blake2b-BiQTw3GC.js} +0 -0
- /package/dist/{blake2b-B9tftbvG.cjs → blake2b-DEeVUdKR.cjs} +0 -0
- /package/dist/{blockchain-network-id.vo-BXpZhvvQ.cjs → blockchain-network-id.vo-BAKEwGjG.cjs} +0 -0
- /package/dist/{blockchain-network-id.vo-DNRkuT5B.js → blockchain-network-id.vo-CiVykuqG.js} +0 -0
- /package/dist/{blockingWithLatestFrom-C5wp_uA-.js → blockingWithLatestFrom-Cd8c8EPG.js} +0 -0
- /package/dist/{blockingWithLatestFrom-DY8OPg0w.cjs → blockingWithLatestFrom-D8kBPBMX.cjs} +0 -0
- /package/dist/{cardano-network-id-to-network-type-CrZfUcyP.js → cardano-network-id-to-network-type-BWwzeEtM.js} +0 -0
- /package/dist/{cardano-network-id-to-network-type-BDTF-HmK.cjs → cardano-network-id-to-network-type-C0ufJOyE.cjs} +0 -0
- /package/dist/{cardano-tx-id.vo-BPhV-AmZ.cjs → cardano-tx-id.vo-TLjJZHCI.cjs} +0 -0
- /package/dist/{cardano-tx-id.vo-DF9NzZXk.js → cardano-tx-id.vo-eVnKuzlm.js} +0 -0
- /package/dist/{composite-signer-factory-_46QsNBz.js → composite-signer-factory-CR8YHA1y.js} +0 -0
- /package/dist/{composite-signer-factory-BpF1mIYA.cjs → composite-signer-factory-m5cVs9h_.cjs} +0 -0
- /package/dist/{error-CNIquqT5.cjs → error-Cb3EnD0u.cjs} +0 -0
- /package/dist/{error-BCp9NkPi.js → error-DIZOY2Lw.js} +0 -0
- /package/dist/{esm-browser-C93Q-EOI.js → esm-browser-MG97cre9.js} +0 -0
- /package/dist/{esm-browser-DTc9IK3D.cjs → esm-browser-bweqfBlL.cjs} +0 -0
- /package/dist/{feature-flag-key.vo-ofrB6ZVQ.js → feature-flag-key.vo-DN_-4-sG.js} +0 -0
- /package/dist/{feature-flag-key.vo-BPz-ZAp6.cjs → feature-flag-key.vo-RlfHL3hq.cjs} +0 -0
- /package/dist/{first-state-of-status-OROkXcRv.cjs → first-state-of-status-CbT7hPa4.cjs} +0 -0
- /package/dist/{first-state-of-status-DQnMT3ya.js → first-state-of-status-unPynOuM.js} +0 -0
- /package/dist/{init-Es3wHW7D.js → init-829HRYcz.js} +0 -0
- /package/dist/{init-CKipPE_c.js → init-A-VyGSNW2.js} +0 -0
- /package/dist/{init-DFQQ9dTW.cjs → init-Atisw4x2.cjs} +0 -0
- /package/dist/{init-C5CEZ1m0.cjs → init-BFcvPHL-.cjs} +0 -0
- /package/dist/{init-IAk_CkGa.cjs → init-BgNobbNq.cjs} +0 -0
- /package/dist/{init-cqN3uX2j.js → init-atCFur0v.js} +0 -0
- /package/dist/{is-redux-persist-state-CTn3WZVh.cjs → is-redux-persist-state-BCFnSm36.cjs} +0 -0
- /package/dist/{is-redux-persist-state-Cxcd0_bM.js → is-redux-persist-state-yBfq0h_E.js} +0 -0
- /package/dist/{key-value-store-8cMzeNyG.js → key-value-store--W3SrMaw.js} +0 -0
- /package/dist/{key-value-store-DUAepXQf.cjs → key-value-store-C2Xt5Emp.cjs} +0 -0
- /package/dist/{repo-slice-WxetRhMY.cjs → repo-slice-7X4AYYVm.cjs} +0 -0
- /package/dist/{repo-slice-DwyMhCR1.js → repo-slice-RxFm0zDZ.js} +0 -0
- /package/dist/{reselect-CRDqmQY9.cjs → reselect-Bd94u0K-.cjs} +0 -0
- /package/dist/{reselect-C06X06oX.js → reselect-CGoLzEPv.js} +0 -0
- /package/dist/{serializable-B8GahgE1.js → serializable-BHdKIgk3.js} +0 -0
- /package/dist/{serializable-CRdnFaLZ.cjs → serializable-BxHkoPdk.cjs} +0 -0
- /package/dist/{slice-D11FHQuQ.cjs → slice-BiRsDKOK.cjs} +0 -0
- /package/dist/{slice-Be7hj4Iy.js → slice-Bk0Sv05J.js} +0 -0
- /package/dist/{slice-FioKeHtA.cjs → slice-Dqw1ecum.cjs} +0 -0
- /package/dist/{slice-B87b52iM.js → slice-obCSLm1x.js} +0 -0
- /package/dist/{src-vq1wS9sZ.js → src-BlxEp6Mm.js} +0 -0
- /package/dist/{src-BTPIvlDI.cjs → src-Cqp0B2M_.cjs} +0 -0
- /package/dist/{time.vo-CQ8pSXz2.cjs → time.vo-D3wWRw9L.cjs} +0 -0
- /package/dist/{time.vo-DkYYGYp6.js → time.vo-tNheinXm.js} +0 -0
- /package/dist/{toEmpty-CgAl3097.js → toEmpty-8Zax1MPd.js} +0 -0
- /package/dist/{toEmpty-DAMmNB5r.cjs → toEmpty-CYAbupM4.cjs} +0 -0
- /package/dist/{token-id.vo-ClsroxHO.js → token-id.vo-Bvwhr3ZE.js} +0 -0
- /package/dist/{token-id.vo-BxG9TG0O.cjs → token-id.vo-DXv5uS9n.cjs} +0 -0
- /package/dist/{util-DxzlYNS5.js → util-C8a4fA9p.js} +0 -0
- /package/dist/{util-CmdAhheh.cjs → util-CzeB3hfa.cjs} +0 -0
- /package/dist/{util-selector-CcK-GAdE.js → util-selector-BSTsxgne.js} +0 -0
- /package/dist/{util-selector-BcAncU4L.cjs → util-selector-BWPH68_l.cjs} +0 -0
- /package/dist/{while-active-BpppWuCs.js → while-active-B0lWy_6l.js} +0 -0
- /package/dist/{while-active-Dhc2LwOm.cjs → while-active-Dsowp0Fi.cjs} +0 -0
|
@@ -0,0 +1,4413 @@
|
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-Br2OG8yv.cjs");
|
|
2
|
+
const require__polyfill_buffer_patch = require("./_polyfill-buffer-patch-CM8X7JiY.cjs");
|
|
3
|
+
require("./bn-d3nSOIf7.cjs");
|
|
4
|
+
require("./client-DXBLHk7K.cjs");
|
|
5
|
+
const require_dist = require("./dist-BMi5ZjEq.cjs");
|
|
6
|
+
const require_v8Signatures = require("./v8Signatures-CO_Uloy7.cjs");
|
|
7
|
+
let rxjs = require("rxjs");
|
|
8
|
+
rxjs = require_rolldown_runtime.__toESM(rxjs);
|
|
9
|
+
let _midnight_ntwrk_ledger_v8 = require("@midnight-ntwrk/ledger-v8");
|
|
10
|
+
_midnight_ntwrk_ledger_v8 = require_rolldown_runtime.__toESM(_midnight_ntwrk_ledger_v8);
|
|
11
|
+
let _midnightntwrk_ledger_v9 = require("@midnightntwrk/ledger-v9");
|
|
12
|
+
_midnightntwrk_ledger_v9 = require_rolldown_runtime.__toESM(_midnightntwrk_ledger_v9);
|
|
13
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/DustWalletAPI.js
|
|
14
|
+
var DustWalletState = class DustWalletState {
|
|
15
|
+
/**
|
|
16
|
+
* Wraps a state emission with the capabilities of the variant that produced it.
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* Call this inside a branch that has narrowed on the emission's `variantTag`, so `variant` and `state` are known to
|
|
20
|
+
* belong together. It is generic over the state type precisely so that pairing is checked.
|
|
21
|
+
*/
|
|
22
|
+
static fromVariant = (variant, state) => new DustWalletState(state.version, state.state, {
|
|
23
|
+
totalCoins: () => variant.coinsAndBalances.getTotalCoins(state.state),
|
|
24
|
+
availableCoins: () => variant.coinsAndBalances.getAvailableCoins(state.state),
|
|
25
|
+
pendingCoins: () => variant.coinsAndBalances.getPendingCoins(state.state),
|
|
26
|
+
publicKey: () => variant.keys.getPublicKey(state.state),
|
|
27
|
+
address: () => variant.keys.getAddress(state.state),
|
|
28
|
+
balance: (time) => variant.coinsAndBalances.getWalletBalance(state.state, time),
|
|
29
|
+
estimateDustGeneration: (nightUtxos, currentTime) => variant.coinsAndBalances.estimateDustGeneration(state.state, nightUtxos, currentTime),
|
|
30
|
+
splitNightUtxos: (nightUtxos) => variant.coinsAndBalances.splitNightUtxos(nightUtxos),
|
|
31
|
+
serialize: () => variant.serialization.serialize(state.state)
|
|
32
|
+
});
|
|
33
|
+
protocolVersion;
|
|
34
|
+
state;
|
|
35
|
+
#projections;
|
|
36
|
+
get totalCoins() {
|
|
37
|
+
return this.#projections.totalCoins();
|
|
38
|
+
}
|
|
39
|
+
get availableCoins() {
|
|
40
|
+
return this.#projections.availableCoins();
|
|
41
|
+
}
|
|
42
|
+
get pendingCoins() {
|
|
43
|
+
return this.#projections.pendingCoins();
|
|
44
|
+
}
|
|
45
|
+
get publicKey() {
|
|
46
|
+
return this.#projections.publicKey();
|
|
47
|
+
}
|
|
48
|
+
get address() {
|
|
49
|
+
return this.#projections.address();
|
|
50
|
+
}
|
|
51
|
+
get progress() {
|
|
52
|
+
return this.state.progress;
|
|
53
|
+
}
|
|
54
|
+
constructor(protocolVersion, state, projections) {
|
|
55
|
+
this.protocolVersion = protocolVersion;
|
|
56
|
+
this.state = state;
|
|
57
|
+
this.#projections = projections;
|
|
58
|
+
}
|
|
59
|
+
balance(time) {
|
|
60
|
+
return this.#projections.balance(time);
|
|
61
|
+
}
|
|
62
|
+
estimateDustGeneration(nightUtxos, currentTime) {
|
|
63
|
+
return this.#projections.estimateDustGeneration(nightUtxos, currentTime);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Splits Night UTxOs into the ones a registration puts in its guaranteed and fallible sections.
|
|
67
|
+
*
|
|
68
|
+
* @remarks
|
|
69
|
+
* Projected here rather than reached for through the capability set, so a reader of this state never has to know
|
|
70
|
+
* which variant produced it. The split itself is plain arithmetic over plain data — no ledger object crosses it —
|
|
71
|
+
* which is why both variants answer it identically.
|
|
72
|
+
* @param nightUtxos The UTxOs to split, with their dust generation readings.
|
|
73
|
+
* @returns The guaranteed and fallible halves.
|
|
74
|
+
*/
|
|
75
|
+
splitNightUtxos(nightUtxos) {
|
|
76
|
+
return this.#projections.splitNightUtxos(nightUtxos);
|
|
77
|
+
}
|
|
78
|
+
serialize() {
|
|
79
|
+
return this.#projections.serialize();
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* The largest fee payment a registration over `nightUtxos` could claim for itself, right now.
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* What {@link DustWalletAPI.waitForGeneratedDust} waits to reach the fee, and the reading behind it. Two things shape
|
|
87
|
+
* it. Only Night that does not yet generate Dust earns the retroactive Dust a registration may spend on its own fee —
|
|
88
|
+
* claiming it for Night that already generates is an overspend the node rejects — and whether a UTxO is one of those
|
|
89
|
+
* is its `registeredForDustGeneration` flag, which the indexer reports as of the chain's current Dust epoch. And the
|
|
90
|
+
* allowance is capped at the _single_ highest-generation UTxO, because `splitNightUtxos` puts exactly one in the
|
|
91
|
+
* registration's guaranteed slot; summing across UTxOs would resolve the wait optimistically and the registration
|
|
92
|
+
* would still fail the fee check on-chain.
|
|
93
|
+
* @param state The dust wallet state to read.
|
|
94
|
+
* @param nightUtxos The Night UTxOs the registration would carry.
|
|
95
|
+
* @param currentTime The time to project generation to.
|
|
96
|
+
* @returns The claimable fee payment, in Specks. `0n` when every UTxO is already registered for Dust generation.
|
|
97
|
+
*/
|
|
98
|
+
const claimableFeePayment = (state, nightUtxos, currentTime) => state.estimateDustGeneration(nightUtxos, currentTime).filter((estimate) => !estimate.utxo.registeredForDustGeneration).reduce((max, estimate) => estimate.dust.generatedNow > max ? estimate.dust.generatedNow : max, 0n);
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/WalletError.js
|
|
101
|
+
require__polyfill_buffer_patch.init__polyfill_buffer_patch();
|
|
102
|
+
var OtherWalletError$1 = class extends require_dist.TaggedError("Wallet.Other") {};
|
|
103
|
+
var SyncWalletError$1 = class extends require_dist.TaggedError("Wallet.Sync") {};
|
|
104
|
+
var TransactingError$1 = class extends require_dist.TaggedError("Wallet.Transacting") {};
|
|
105
|
+
var InsufficientFundsError$1 = class extends require_dist.TaggedError("Wallet.InsufficientFunds") {};
|
|
106
|
+
var TransactionHistoryError$1 = class extends require_dist.TaggedError("Wallet.TransactionHistory") {};
|
|
107
|
+
/**
|
|
108
|
+
* A batch of dust ledger events was not in ascending id order: an event arrived at or below the one before it, or at or
|
|
109
|
+
* below the applied cursor.
|
|
110
|
+
*
|
|
111
|
+
* @remarks
|
|
112
|
+
* Order is all the wallet can check: dust events share one id sequence with zswap and contract events in the indexer,
|
|
113
|
+
* so gaps in the stream are normal and a skipped event is only ever caught by the ledger's own insertion check. The
|
|
114
|
+
* whole batch is refused, nothing is applied and the cursor stays, so the running variant retries from the same
|
|
115
|
+
* place.
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* if (error._tag === 'Wallet.OutOfOrderSyncUpdate') console.warn(`expected above ${error.expected}, got ${error.received}`);
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
var OutOfOrderSyncUpdateError$1 = class extends require_dist.TaggedError("Wallet.OutOfOrderSyncUpdate") {};
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/Serialization.js
|
|
124
|
+
const StateSchema$1 = require_dist.declare((input) => input instanceof _midnightntwrk_ledger_v9.DustLocalState).annotations({ identifier: "ledger.DustLocalState" });
|
|
125
|
+
const Uint8ArraySchema$1 = require_dist.declare((input) => input instanceof Uint8Array).annotations({ identifier: "Uint8Array" });
|
|
126
|
+
const StateFromUInt8Array$1 = require_dist.asSchema(require_dist.transformOrFail(Uint8ArraySchema$1, StateSchema$1, {
|
|
127
|
+
encode: (state) => {
|
|
128
|
+
return require_dist.try_({
|
|
129
|
+
try: () => {
|
|
130
|
+
return state.serialize();
|
|
131
|
+
},
|
|
132
|
+
catch: (err) => {
|
|
133
|
+
return new require_dist.Unexpected(err, "Could not serialize local state");
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
decode: (bytes) => require_dist.try_({
|
|
138
|
+
try: () => _midnightntwrk_ledger_v9.DustLocalState.deserialize(bytes),
|
|
139
|
+
catch: (err) => {
|
|
140
|
+
return new require_dist.Unexpected(err, "Could not deserialize local state");
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
}));
|
|
144
|
+
const HexedState$1 = require_dist.pipe(require_dist.Uint8ArrayFromHex, require_dist.compose(StateFromUInt8Array$1));
|
|
145
|
+
const SnapshotSchema$1 = require_dist.Struct({
|
|
146
|
+
publicKey: require_dist.Struct({ publicKey: require_dist.BigInt$ }),
|
|
147
|
+
state: HexedState$1,
|
|
148
|
+
protocolVersion: require_dist.BigInt$,
|
|
149
|
+
networkId: require_dist.String$,
|
|
150
|
+
offset: require_dist.optional(require_dist.BigInt$)
|
|
151
|
+
});
|
|
152
|
+
const makeDefaultV2SerializationCapability = () => {
|
|
153
|
+
return {
|
|
154
|
+
serialize: (wallet) => {
|
|
155
|
+
const buildSnapshot = (w) => ({
|
|
156
|
+
publicKey: w.publicKey,
|
|
157
|
+
state: w.state,
|
|
158
|
+
protocolVersion: w.protocolVersion,
|
|
159
|
+
networkId: w.networkId,
|
|
160
|
+
offset: w.progress?.appliedIndex
|
|
161
|
+
});
|
|
162
|
+
return require_dist.pipe(wallet, buildSnapshot, require_dist.encodeSync(SnapshotSchema$1), JSON.stringify);
|
|
163
|
+
},
|
|
164
|
+
deserialize: (aux, serialized) => {
|
|
165
|
+
return require_dist.pipe(serialized, require_dist.decodeUnknownEither(require_dist.parseJson(SnapshotSchema$1)), require_dist.mapLeft((err) => new OtherWalletError$1({
|
|
166
|
+
message: "Error while deserializing snapshot",
|
|
167
|
+
cause: err
|
|
168
|
+
})), require_dist.flatMap$4((snapshot) => require_dist.try_$1({
|
|
169
|
+
try: () => CoreWallet$1.restore(snapshot.state, snapshot.publicKey, [], {
|
|
170
|
+
appliedIndex: snapshot.offset ?? 0n,
|
|
171
|
+
highestRelevantWalletIndex: 0n,
|
|
172
|
+
highestIndex: 0n,
|
|
173
|
+
highestRelevantIndex: 0n
|
|
174
|
+
}, snapshot.protocolVersion, snapshot.networkId),
|
|
175
|
+
catch: (err) => new OtherWalletError$1({
|
|
176
|
+
message: "Error while restoring core wallet",
|
|
177
|
+
cause: err
|
|
178
|
+
})
|
|
179
|
+
})));
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/SyncSchema.js
|
|
185
|
+
const DustStateMerkleTreeCollapsedUpdateSchema = require_dist.declare((input) => input instanceof _midnightntwrk_ledger_v9.DustStateMerkleTreeCollapsedUpdate).annotations({ identifier: "DustStateMerkleTreeCollapsedUpdate" });
|
|
186
|
+
const DustStateMerkleTreeCollapsedUpdateFromUInt8Array = require_dist.asSchema(require_dist.transformOrFail(Uint8ArraySchema$1, DustStateMerkleTreeCollapsedUpdateSchema, {
|
|
187
|
+
encode: (value) => {
|
|
188
|
+
return require_dist.try_({
|
|
189
|
+
try: () => {
|
|
190
|
+
return value.serialize();
|
|
191
|
+
},
|
|
192
|
+
catch: (err) => {
|
|
193
|
+
return new require_dist.Unexpected(err, "Could not serialize DustStateMerkleTreeCollapsedUpdate");
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
decode: (bytes) => require_dist.try_({
|
|
198
|
+
try: () => _midnightntwrk_ledger_v9.DustStateMerkleTreeCollapsedUpdate.deserialize(bytes),
|
|
199
|
+
catch: (err) => {
|
|
200
|
+
return new require_dist.Unexpected(err, "Could not deserialize DustStateMerkleTreeCollapsedUpdate");
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
}));
|
|
204
|
+
const HexedDustStateMerkleTreeCollapsedUpdate = require_dist.pipe(require_dist.Uint8ArrayFromHex, require_dist.compose(DustStateMerkleTreeCollapsedUpdateFromUInt8Array));
|
|
205
|
+
/**
|
|
206
|
+
* A collapsed Merkle tree update as the indexer served it, still encoded.
|
|
207
|
+
*
|
|
208
|
+
* @remarks
|
|
209
|
+
* The update travels as bytes rather than as a `DustStateMerkleTreeCollapsedUpdate`, because whether this ledger
|
|
210
|
+
* version can read it is not the subscription's question to answer — and a subscription that answered it would answer
|
|
211
|
+
* for the whole batch at once. One item this wallet was never going to apply would fail the fetch it arrived in, and
|
|
212
|
+
* the stream would retry the same fetch forever. See {@link readCollapsedUpdate}.
|
|
213
|
+
*/
|
|
214
|
+
const CollapsedMerkleTreeSchema = require_dist.Struct({
|
|
215
|
+
startIndex: require_dist.Number$,
|
|
216
|
+
endIndex: require_dist.Number$,
|
|
217
|
+
update: require_dist.String$,
|
|
218
|
+
protocolVersion: require_dist.Number$
|
|
219
|
+
});
|
|
220
|
+
/**
|
|
221
|
+
* Reads a collapsed Merkle tree update this wallet is about to apply.
|
|
222
|
+
*
|
|
223
|
+
* @param tree The update as the indexer served it.
|
|
224
|
+
* @returns The decoded update.
|
|
225
|
+
* @throws ParseError if the bytes are not an update this ledger version can deserialize.
|
|
226
|
+
*/
|
|
227
|
+
const readCollapsedUpdate = (tree) => require_dist.decodeSync(HexedDustStateMerkleTreeCollapsedUpdate)(tree.update);
|
|
228
|
+
const WireDustGenerationsUpdateSchema = require_dist.Struct({
|
|
229
|
+
__typename: require_dist.Literal("DustGenerationsItem"),
|
|
230
|
+
commitmentMtIndex: require_dist.Number$,
|
|
231
|
+
generationMtIndex: require_dist.Number$,
|
|
232
|
+
owner: require_dist.String$,
|
|
233
|
+
value: require_dist.String$,
|
|
234
|
+
initialValue: require_dist.String$,
|
|
235
|
+
backingNight: require_dist.String$,
|
|
236
|
+
ctime: require_dist.Number$,
|
|
237
|
+
transactionId: require_dist.Number$,
|
|
238
|
+
transactionHash: require_dist.String$,
|
|
239
|
+
collapsedMerkleTree: require_dist.Union(CollapsedMerkleTreeSchema, require_dist.Null)
|
|
240
|
+
});
|
|
241
|
+
const DustGenerationsUpdateSchema = require_dist.transform(WireDustGenerationsUpdateSchema, require_dist.typeSchema(require_dist.Struct({
|
|
242
|
+
__typename: require_dist.Literal("DustGenerationsItem"),
|
|
243
|
+
commitmentMtIndex: require_dist.Number$,
|
|
244
|
+
generationMtIndex: require_dist.Number$,
|
|
245
|
+
owner: require_dist.String$,
|
|
246
|
+
value: require_dist.String$,
|
|
247
|
+
initialValue: require_dist.String$,
|
|
248
|
+
backingNight: require_dist.String$,
|
|
249
|
+
ctime: require_dist.DateFromSelf,
|
|
250
|
+
transactionId: require_dist.Number$,
|
|
251
|
+
transactionHash: require_dist.String$,
|
|
252
|
+
collapsedMerkleTree: require_dist.Union(CollapsedMerkleTreeSchema, require_dist.Null)
|
|
253
|
+
})), {
|
|
254
|
+
strict: true,
|
|
255
|
+
decode: (wire) => ({
|
|
256
|
+
...wire,
|
|
257
|
+
ctime: /* @__PURE__ */ new Date(wire.ctime * 1e3)
|
|
258
|
+
}),
|
|
259
|
+
encode: (domain) => ({
|
|
260
|
+
...domain,
|
|
261
|
+
ctime: Math.floor(domain.ctime.getTime() / 1e3)
|
|
262
|
+
})
|
|
263
|
+
});
|
|
264
|
+
const ProgressSchema = require_dist.Struct({
|
|
265
|
+
__typename: require_dist.Literal("DustGenerationsProgress"),
|
|
266
|
+
highestIndex: require_dist.Number$,
|
|
267
|
+
collapsedMerkleTree: require_dist.Union(CollapsedMerkleTreeSchema, require_dist.Null)
|
|
268
|
+
});
|
|
269
|
+
const DustGenerationTreeInsertionPathSchema = require_dist.declare((input) => input instanceof _midnightntwrk_ledger_v9.DustGenerationTreeInsertionPath).annotations({ identifier: "DustGenerationTreeInsertionPath" });
|
|
270
|
+
const DustGenerationTreeInsertionPathFromUInt8Array = require_dist.asSchema(require_dist.transformOrFail(Uint8ArraySchema$1, DustGenerationTreeInsertionPathSchema, {
|
|
271
|
+
encode: (value) => {
|
|
272
|
+
return require_dist.try_({
|
|
273
|
+
try: () => {
|
|
274
|
+
return value.serialize();
|
|
275
|
+
},
|
|
276
|
+
catch: (err) => {
|
|
277
|
+
return new require_dist.Unexpected(err, "Could not serialize DustGenerationTreeInsertionPath");
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
},
|
|
281
|
+
decode: (bytes) => require_dist.try_({
|
|
282
|
+
try: () => _midnightntwrk_ledger_v9.DustGenerationTreeInsertionPath.deserialize(bytes),
|
|
283
|
+
catch: (err) => {
|
|
284
|
+
return new require_dist.Unexpected(err, "Could not deserialize DustGenerationTreeInsertionPath");
|
|
285
|
+
}
|
|
286
|
+
})
|
|
287
|
+
}));
|
|
288
|
+
const HexedDustGenerationTreeInsertionPath = require_dist.pipe(require_dist.Uint8ArrayFromHex, require_dist.compose(DustGenerationTreeInsertionPathFromUInt8Array));
|
|
289
|
+
/**
|
|
290
|
+
* Reads a generation-tree insertion path this wallet is about to apply.
|
|
291
|
+
*
|
|
292
|
+
* @param treeInsertionPath The path as the indexer served it.
|
|
293
|
+
* @returns The decoded path.
|
|
294
|
+
* @throws ParseError if the bytes are not a path this ledger version can deserialize.
|
|
295
|
+
*/
|
|
296
|
+
const readGenerationTreeInsertionPath = (treeInsertionPath) => require_dist.decodeSync(HexedDustGenerationTreeInsertionPath)(treeInsertionPath);
|
|
297
|
+
/**
|
|
298
|
+
* A dtime update as the indexer served it, its insertion path still encoded.
|
|
299
|
+
*
|
|
300
|
+
* @remarks
|
|
301
|
+
* Structural only, for the same reason as {@link CollapsedMerkleTreeSchema}: a subscription that deserialized on arrival
|
|
302
|
+
* would decide for the whole batch whether this ledger version can read an item, and fail all of it on the first one
|
|
303
|
+
* it cannot.
|
|
304
|
+
*/
|
|
305
|
+
const DustGenerationDtimeUpdateItemSchema = require_dist.transform(require_dist.Struct({
|
|
306
|
+
__typename: require_dist.Literal("DustGenerationDtimeUpdateItem"),
|
|
307
|
+
generationMtIndex: require_dist.Number$,
|
|
308
|
+
nightUtxoHash: require_dist.String$,
|
|
309
|
+
newDtime: require_dist.Number$,
|
|
310
|
+
treeInsertionPath: require_dist.String$
|
|
311
|
+
}), require_dist.typeSchema(require_dist.Struct({
|
|
312
|
+
__typename: require_dist.Literal("DustGenerationDtimeUpdateItem"),
|
|
313
|
+
generationMtIndex: require_dist.Number$,
|
|
314
|
+
nightUtxoHash: require_dist.String$,
|
|
315
|
+
newDtime: require_dist.DateFromSelf,
|
|
316
|
+
treeInsertionPath: require_dist.String$
|
|
317
|
+
})), {
|
|
318
|
+
strict: true,
|
|
319
|
+
decode: (wire) => ({
|
|
320
|
+
...wire,
|
|
321
|
+
newDtime: /* @__PURE__ */ new Date(wire.newDtime * 1e3)
|
|
322
|
+
}),
|
|
323
|
+
encode: (domain) => ({
|
|
324
|
+
...domain,
|
|
325
|
+
newDtime: Math.floor(domain.newDtime.getTime() / 1e3)
|
|
326
|
+
})
|
|
327
|
+
});
|
|
328
|
+
const DustGenerationsSubscriptionSchema = require_dist.Union(DustGenerationsUpdateSchema, ProgressSchema, DustGenerationDtimeUpdateItemSchema);
|
|
329
|
+
const LedgerParametersSchema = require_dist.declare((input) => input instanceof _midnightntwrk_ledger_v9.LedgerParameters).annotations({ identifier: "ledger.Parameters" });
|
|
330
|
+
const LedgerParametersFromUint8Array = require_dist.asSchema(require_dist.transformOrFail(Uint8ArraySchema$1, LedgerParametersSchema, {
|
|
331
|
+
encode: (e) => {
|
|
332
|
+
return require_dist.try_({
|
|
333
|
+
try: () => e.serialize(),
|
|
334
|
+
catch: (err) => {
|
|
335
|
+
return new require_dist.Unexpected(err, "Could not serialize Ledger Parameters");
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
},
|
|
339
|
+
decode: (bytes) => require_dist.try_({
|
|
340
|
+
try: () => _midnightntwrk_ledger_v9.LedgerParameters.deserialize(bytes),
|
|
341
|
+
catch: (err) => {
|
|
342
|
+
return new require_dist.Unexpected(err, "Could not deserialize Ledger Parameters");
|
|
343
|
+
}
|
|
344
|
+
})
|
|
345
|
+
}));
|
|
346
|
+
const HexedLedgerParameters = require_dist.pipe(require_dist.Uint8ArrayFromHex, require_dist.compose(LedgerParametersFromUint8Array));
|
|
347
|
+
const LedgerEventSchema$1 = require_dist.declare((input) => input instanceof _midnightntwrk_ledger_v9.Event).annotations({ identifier: "ledger.Event" });
|
|
348
|
+
const LedgerEventFromUInt8Array$1 = require_dist.asSchema(require_dist.transformOrFail(Uint8ArraySchema$1, LedgerEventSchema$1, {
|
|
349
|
+
encode: (e) => {
|
|
350
|
+
return require_dist.try_({
|
|
351
|
+
try: () => e.serialize(),
|
|
352
|
+
catch: (err) => {
|
|
353
|
+
return new require_dist.Unexpected(err, "Could not serialize Ledger Event");
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
},
|
|
357
|
+
decode: (bytes) => require_dist.try_({
|
|
358
|
+
try: () => _midnightntwrk_ledger_v9.Event.deserialize(bytes),
|
|
359
|
+
catch: (err) => {
|
|
360
|
+
return new require_dist.Unexpected(err, "Could not deserialize Ledger Event");
|
|
361
|
+
}
|
|
362
|
+
})
|
|
363
|
+
}));
|
|
364
|
+
const HexedEvent$1 = require_dist.pipe(require_dist.Uint8ArrayFromHex, require_dist.compose(LedgerEventFromUInt8Array$1));
|
|
365
|
+
/**
|
|
366
|
+
* One event of a matched transaction, still encoded.
|
|
367
|
+
*
|
|
368
|
+
* @remarks
|
|
369
|
+
* The nullifier lookup this arrives through searches from block zero and matches on a nullifier _prefix_ — deliberately
|
|
370
|
+
* over-fetching, for anonymity — so most of what it returns belongs to other parties, and on a chain that has forked
|
|
371
|
+
* some of it belongs to the previous ledger version. Deserializing on arrival would let either of those fail the
|
|
372
|
+
* whole lookup, and with it every dust spend this wallet ever made. See {@link readEvent}.
|
|
373
|
+
*/
|
|
374
|
+
const TransactionEvent = require_dist.Struct({
|
|
375
|
+
id: require_dist.Number$,
|
|
376
|
+
raw: require_dist.String$,
|
|
377
|
+
maxId: require_dist.Number$,
|
|
378
|
+
protocolVersion: require_dist.Number$
|
|
379
|
+
});
|
|
380
|
+
/**
|
|
381
|
+
* The block a matched transaction sits in, its ledger parameters still encoded.
|
|
382
|
+
*
|
|
383
|
+
* @remarks
|
|
384
|
+
* `protocolVersion` says which ledger version wrote those parameters, and is therefore what chooses the codec that
|
|
385
|
+
* reads them — see {@link readNullifierBlockParameters}. Reading them on arrival would mean picking a ledger version
|
|
386
|
+
* before consulting the one field that says which to pick, which is how a ledger-v8 block takes down the whole
|
|
387
|
+
* lookup.
|
|
388
|
+
*/
|
|
389
|
+
const NullifierBlockInfoSchema = require_dist.Struct({
|
|
390
|
+
protocolVersion: require_dist.Number$,
|
|
391
|
+
ledgerParameters: require_dist.String$
|
|
392
|
+
});
|
|
393
|
+
/**
|
|
394
|
+
* Reads the ledger parameters of a block holding a spend this wallet owns.
|
|
395
|
+
*
|
|
396
|
+
* @param block The block as the indexer served it.
|
|
397
|
+
* @param codecs The ledger parameters codecs this variant is willing to read with.
|
|
398
|
+
* @returns The decoded parameters, or the codec registry's refusal when no codec claims the block's version.
|
|
399
|
+
*/
|
|
400
|
+
const readNullifierBlockParameters = (block, codecs) => require_dist.decode(codecs, require_dist.ProtocolVersion(BigInt(block.protocolVersion)), block.ledgerParameters);
|
|
401
|
+
const NullifierNonRegularTransactionSchema = require_dist.Struct({
|
|
402
|
+
__typename: require_dist.Literal("SystemTransaction", "BridgeClaimTransaction"),
|
|
403
|
+
block: NullifierBlockInfoSchema
|
|
404
|
+
});
|
|
405
|
+
const NullifierRegularTransactionSchema = require_dist.Struct({
|
|
406
|
+
__typename: require_dist.Literal("RegularTransaction"),
|
|
407
|
+
block: NullifierBlockInfoSchema,
|
|
408
|
+
id: require_dist.Number$,
|
|
409
|
+
hash: require_dist.String$,
|
|
410
|
+
dustLedgerEvents: require_dist.Array$(TransactionEvent),
|
|
411
|
+
zswapLedgerEvents: require_dist.Array$(TransactionEvent)
|
|
412
|
+
});
|
|
413
|
+
const NullifierTransactionSchema = require_dist.Union(NullifierNonRegularTransactionSchema, NullifierRegularTransactionSchema);
|
|
414
|
+
const DustNullifierTransactionSubscriptionSchema = require_dist.Struct({
|
|
415
|
+
nullifierLeBytes: require_dist.String$,
|
|
416
|
+
commitmentLeBytes: require_dist.String$,
|
|
417
|
+
transactionId: require_dist.Number$,
|
|
418
|
+
transactionHash: require_dist.String$,
|
|
419
|
+
blockHeight: require_dist.Number$,
|
|
420
|
+
blockHash: require_dist.String$,
|
|
421
|
+
transaction: NullifierTransactionSchema
|
|
422
|
+
});
|
|
423
|
+
const DustGenerationsSyncUpdate = { create: (rawUpdates, secretKey, publicKey, lastSyncedGenerationIndex) => {
|
|
424
|
+
const { publicKey: dustPublicKey } = publicKey;
|
|
425
|
+
const dustAddressHex = new require_dist.DustAddress(dustPublicKey).hexString;
|
|
426
|
+
return {
|
|
427
|
+
rawUpdates,
|
|
428
|
+
newGenerations: rawUpdates.filter((u) => u.__typename === "DustGenerationsItem").filter((u) => u.owner === dustAddressHex && u.generationMtIndex > lastSyncedGenerationIndex).toSorted((u1, u2) => u1.generationMtIndex - u2.generationMtIndex).map((u) => {
|
|
429
|
+
const qdo = {
|
|
430
|
+
initialValue: BigInt(u.initialValue),
|
|
431
|
+
owner: dustPublicKey,
|
|
432
|
+
nonce: (0, _midnightntwrk_ledger_v9.dustFirstNonce)(u.backingNight, dustPublicKey),
|
|
433
|
+
seq: 0,
|
|
434
|
+
ctime: u.ctime,
|
|
435
|
+
backingNight: u.backingNight,
|
|
436
|
+
mtIndex: BigInt(u.commitmentMtIndex)
|
|
437
|
+
};
|
|
438
|
+
return {
|
|
439
|
+
dustNullifier: (0, _midnightntwrk_ledger_v9.dustNullifier)(qdo, secretKey),
|
|
440
|
+
genInfo: {
|
|
441
|
+
value: BigInt(u.value),
|
|
442
|
+
owner: dustPublicKey,
|
|
443
|
+
nonce: u.backingNight,
|
|
444
|
+
dtime: void 0
|
|
445
|
+
},
|
|
446
|
+
generationMtIndex: u.generationMtIndex,
|
|
447
|
+
qdo,
|
|
448
|
+
transactionId: u.transactionId,
|
|
449
|
+
transactionHash: u.transactionHash
|
|
450
|
+
};
|
|
451
|
+
}),
|
|
452
|
+
generationDtimeUpdates: rawUpdates.filter((u) => u.__typename === "DustGenerationDtimeUpdateItem").toSorted((u1, u2) => u1.generationMtIndex - u2.generationMtIndex).map(({ __typename, ...rest }) => rest)
|
|
453
|
+
};
|
|
454
|
+
} };
|
|
455
|
+
const SyncEventsUpdateSchema$1 = require_dist.Struct({
|
|
456
|
+
id: require_dist.Number$,
|
|
457
|
+
raw: require_dist.String$,
|
|
458
|
+
maxId: require_dist.Number$,
|
|
459
|
+
protocolVersion: require_dist.optional(require_dist.Number$)
|
|
460
|
+
});
|
|
461
|
+
/**
|
|
462
|
+
* Reads an event this variant is going to apply.
|
|
463
|
+
*
|
|
464
|
+
* @remarks
|
|
465
|
+
* The counterpart of the sync schemas carrying their events encoded: a capability calls this on the batch prefix it
|
|
466
|
+
* owns, and never on what it defers. Failure here is a genuine one — an event this variant claimed and cannot read —
|
|
467
|
+
* and is raised rather than returned, because `SyncCapability.applyUpdate` is total in its own domain and the variant
|
|
468
|
+
* already turns a throw from it into a typed synchronization error.
|
|
469
|
+
* @param event The event-carrying item to read.
|
|
470
|
+
* @returns The event it carries.
|
|
471
|
+
* @throws ParseError if the bytes are not an event this ledger version can deserialize.
|
|
472
|
+
*/
|
|
473
|
+
const readEvent$1 = (event) => require_dist.decodeSync(HexedEvent$1)(event.raw);
|
|
474
|
+
/**
|
|
475
|
+
* Reads an event this variant only might be interested in.
|
|
476
|
+
*
|
|
477
|
+
* @remarks
|
|
478
|
+
* For sources that over-deliver by design rather than by accident — the nullifier lookup matches on a nullifier
|
|
479
|
+
* _prefix_ and searches from block zero, so it returns other parties' transactions and, on a chain that has forked,
|
|
480
|
+
* the previous ledger version's. An event this version cannot read is by construction not one of this wallet's own
|
|
481
|
+
* spends, so it is skipped rather than raised. Use {@link readEvent} wherever the variant has already claimed the
|
|
482
|
+
* event.
|
|
483
|
+
* @param event The event-carrying item to read.
|
|
484
|
+
* @returns The event, or `Option.none()` when these bytes are not an event this ledger version reads.
|
|
485
|
+
*/
|
|
486
|
+
const tryReadEvent = (event) => require_dist.decodeOption(HexedEvent$1)(event.raw);
|
|
487
|
+
const VersionSignalSyncUpdate$1 = { create: (version, highestEventId) => {
|
|
488
|
+
return {
|
|
489
|
+
_tag: "VersionSignal",
|
|
490
|
+
version,
|
|
491
|
+
highestEventId
|
|
492
|
+
};
|
|
493
|
+
} };
|
|
494
|
+
const WalletSyncUpdate$1 = { create: (updates, secretKey, timestamp) => {
|
|
495
|
+
return {
|
|
496
|
+
_tag: "Events",
|
|
497
|
+
updates,
|
|
498
|
+
secretKey,
|
|
499
|
+
timestamp
|
|
500
|
+
};
|
|
501
|
+
} };
|
|
502
|
+
const DustUtxoMap = { create: (generations) => require_dist.fromIterable(generations.map((u) => [u.dustNullifier, {
|
|
503
|
+
qdo: u.qdo,
|
|
504
|
+
transactionId: u.transactionId,
|
|
505
|
+
transactionHash: u.transactionHash,
|
|
506
|
+
genInfo: u.genInfo
|
|
507
|
+
}])) };
|
|
508
|
+
const DustProjectionsUpdate = require_dist.taggedEnum();
|
|
509
|
+
const isProgressUpdate = DustProjectionsUpdate.$is("ProgressUpdate");
|
|
510
|
+
const { $match: match, StateUpdate, ProgressUpdate } = DustProjectionsUpdate;
|
|
511
|
+
/**
|
|
512
|
+
* The block as the indexer sends it: `ledgerParameters` is still hex, and `protocolVersion` says which ledger version
|
|
513
|
+
* produced that hex.
|
|
514
|
+
*
|
|
515
|
+
* @remarks
|
|
516
|
+
* The parameters deliberately stay undecoded here, the same way the shielded event payload keeps its `raw` string.
|
|
517
|
+
* Decoding on arrival means picking a ledger version before reading the one field that says which version to pick,
|
|
518
|
+
* which is how a block from the other side of a fork takes down the whole fetch.
|
|
519
|
+
*/
|
|
520
|
+
const WireBlockDataSchema = require_dist.Struct({
|
|
521
|
+
height: require_dist.Number$,
|
|
522
|
+
hash: require_dist.String$,
|
|
523
|
+
protocolVersion: require_dist.Number$,
|
|
524
|
+
ledgerParameters: require_dist.String$,
|
|
525
|
+
timestamp: require_dist.Number$,
|
|
526
|
+
zswapEndIndex: require_dist.Number$,
|
|
527
|
+
dustCommitmentEndIndex: require_dist.Number$,
|
|
528
|
+
dustGenerationEndIndex: require_dist.Number$,
|
|
529
|
+
dustCommitmentMerkleTreeRoot: require_dist.NullOr(require_dist.String$),
|
|
530
|
+
dustGenerationMerkleTreeRoot: require_dist.NullOr(require_dist.String$)
|
|
531
|
+
});
|
|
532
|
+
const BlockDataStructSchema = require_dist.typeSchema(require_dist.Struct({
|
|
533
|
+
height: require_dist.Number$,
|
|
534
|
+
hash: require_dist.String$,
|
|
535
|
+
protocolVersion: require_dist.Number$,
|
|
536
|
+
ledgerParameters: HexedLedgerParameters,
|
|
537
|
+
timestamp: require_dist.DateFromSelf,
|
|
538
|
+
zswapEndIndex: require_dist.Number$,
|
|
539
|
+
dustCommitmentEndIndex: require_dist.Number$,
|
|
540
|
+
dustGenerationEndIndex: require_dist.Number$,
|
|
541
|
+
dustCommitmentMerkleTreeRoot: require_dist.String$,
|
|
542
|
+
dustGenerationMerkleTreeRoot: require_dist.String$
|
|
543
|
+
}));
|
|
544
|
+
/**
|
|
545
|
+
* The ledger parameters codecs this variant reads blocks with, unless it is told otherwise.
|
|
546
|
+
*
|
|
547
|
+
* @remarks
|
|
548
|
+
* Open-ended from the minimum supported version, so a wallet whose variant has not been given a narrower range keeps
|
|
549
|
+
* reading every block exactly as it did before this became routable. A two-variant dust wallet replaces this with a
|
|
550
|
+
* registry bounded by the range its variant is active over, and then a block from the other side of the boundary is
|
|
551
|
+
* refused by name instead of being deserialized.
|
|
552
|
+
*/
|
|
553
|
+
const defaultLedgerParametersCodecs$1 = require_dist.getOrThrow$1(require_dist.makeCodecs([{
|
|
554
|
+
sinceVersion: require_dist.MinSupportedVersion,
|
|
555
|
+
codec: require_dist.fromDeserializer((bytes) => _midnightntwrk_ledger_v9.LedgerParameters.deserialize(bytes))
|
|
556
|
+
}]));
|
|
557
|
+
/**
|
|
558
|
+
* Builds the block-data schema that reads a block's ledger parameters with whichever codec claims the protocol version
|
|
559
|
+
* the block was reported under.
|
|
560
|
+
*
|
|
561
|
+
* @param codecs The ledger parameters codecs this variant is willing to read with.
|
|
562
|
+
* @returns A schema decoding the indexer's block into {@link BlockData}.
|
|
563
|
+
*/
|
|
564
|
+
const makeBlockDataSchema = (codecs) => require_dist.asSchema(require_dist.transformOrFail(WireBlockDataSchema, BlockDataStructSchema, {
|
|
565
|
+
strict: true,
|
|
566
|
+
decode: (wire, _options, ast) => require_dist.pipe(require_dist.decode(codecs, require_dist.ProtocolVersion(BigInt(wire.protocolVersion)), wire.ledgerParameters), require_dist.mapBoth({
|
|
567
|
+
onLeft: (error) => new require_dist.Type(ast, wire, error.message),
|
|
568
|
+
onRight: (ledgerParameters) => ({
|
|
569
|
+
height: wire.height,
|
|
570
|
+
hash: wire.hash,
|
|
571
|
+
protocolVersion: wire.protocolVersion,
|
|
572
|
+
ledgerParameters,
|
|
573
|
+
timestamp: new Date(wire.timestamp),
|
|
574
|
+
zswapEndIndex: wire.zswapEndIndex,
|
|
575
|
+
dustCommitmentEndIndex: wire.dustCommitmentEndIndex,
|
|
576
|
+
dustGenerationEndIndex: wire.dustGenerationEndIndex,
|
|
577
|
+
dustCommitmentMerkleTreeRoot: wire.dustCommitmentMerkleTreeRoot ?? "",
|
|
578
|
+
dustGenerationMerkleTreeRoot: wire.dustGenerationMerkleTreeRoot ?? ""
|
|
579
|
+
})
|
|
580
|
+
})),
|
|
581
|
+
encode: (domain, _options, ast) => require_dist.try_({
|
|
582
|
+
try: () => ({
|
|
583
|
+
height: domain.height,
|
|
584
|
+
hash: domain.hash,
|
|
585
|
+
protocolVersion: domain.protocolVersion,
|
|
586
|
+
ledgerParameters: require__polyfill_buffer_patch.import_buffer.Buffer.from(domain.ledgerParameters.serialize()).toString("hex"),
|
|
587
|
+
timestamp: domain.timestamp.getTime(),
|
|
588
|
+
zswapEndIndex: domain.zswapEndIndex,
|
|
589
|
+
dustCommitmentEndIndex: domain.dustCommitmentEndIndex,
|
|
590
|
+
dustGenerationEndIndex: domain.dustGenerationEndIndex,
|
|
591
|
+
dustCommitmentMerkleTreeRoot: domain.dustCommitmentMerkleTreeRoot === "" ? null : domain.dustCommitmentMerkleTreeRoot,
|
|
592
|
+
dustGenerationMerkleTreeRoot: domain.dustGenerationMerkleTreeRoot === "" ? null : domain.dustGenerationMerkleTreeRoot
|
|
593
|
+
}),
|
|
594
|
+
catch: (err) => new require_dist.Type(ast, domain, `Could not serialize Ledger Parameters: ${String(err)}`)
|
|
595
|
+
})
|
|
596
|
+
}));
|
|
597
|
+
makeBlockDataSchema(defaultLedgerParametersCodecs$1);
|
|
598
|
+
//#endregion
|
|
599
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/CoreWallet.js
|
|
600
|
+
const PublicKey$1 = { fromSecretKey: (secretKey) => {
|
|
601
|
+
return { publicKey: secretKey.publicKey };
|
|
602
|
+
} };
|
|
603
|
+
const CoreWallet$1 = {
|
|
604
|
+
init(localState, secretKey, networkId) {
|
|
605
|
+
return CoreWallet$1.empty(localState, PublicKey$1.fromSecretKey(secretKey), networkId);
|
|
606
|
+
},
|
|
607
|
+
initEmpty(dustParameters, secretKey, networkId) {
|
|
608
|
+
return CoreWallet$1.empty(new _midnightntwrk_ledger_v9.DustLocalState(dustParameters), PublicKey$1.fromSecretKey(secretKey), networkId);
|
|
609
|
+
},
|
|
610
|
+
empty(localState, publicKey, networkId) {
|
|
611
|
+
return {
|
|
612
|
+
state: localState,
|
|
613
|
+
publicKey,
|
|
614
|
+
networkId,
|
|
615
|
+
pendingDust: [],
|
|
616
|
+
progress: require_dist.createSyncProgress(),
|
|
617
|
+
protocolVersion: require_dist.MinSupportedVersion
|
|
618
|
+
};
|
|
619
|
+
},
|
|
620
|
+
restore(localState, publicKey, pendingTokens, syncProgress, protocolVersion, networkId) {
|
|
621
|
+
return {
|
|
622
|
+
state: localState,
|
|
623
|
+
publicKey,
|
|
624
|
+
networkId,
|
|
625
|
+
pendingDust: pendingTokens,
|
|
626
|
+
progress: require_dist.createSyncProgress(syncProgress),
|
|
627
|
+
protocolVersion: require_dist.ProtocolVersion(protocolVersion)
|
|
628
|
+
};
|
|
629
|
+
},
|
|
630
|
+
withProtocolVersion(wallet, version) {
|
|
631
|
+
return version > wallet.protocolVersion ? {
|
|
632
|
+
...wallet,
|
|
633
|
+
protocolVersion: version
|
|
634
|
+
} : wallet;
|
|
635
|
+
},
|
|
636
|
+
fromPreviousVersion(previous) {
|
|
637
|
+
return {
|
|
638
|
+
state: new _midnightntwrk_ledger_v9.DustLocalState(previous.dustParameters),
|
|
639
|
+
publicKey: previous.publicKey,
|
|
640
|
+
networkId: previous.networkId,
|
|
641
|
+
pendingDust: [],
|
|
642
|
+
progress: require_dist.createSyncProgress({
|
|
643
|
+
...previous.progress,
|
|
644
|
+
isConnected: false
|
|
645
|
+
}),
|
|
646
|
+
protocolVersion: require_dist.ProtocolVersion(previous.protocolVersion)
|
|
647
|
+
};
|
|
648
|
+
},
|
|
649
|
+
applyEventsWithChanges(wallet, secretKey, events, currentTime) {
|
|
650
|
+
const stateWithChanges = wallet.state.replayEventsWithChanges(secretKey, events);
|
|
651
|
+
const updatedState = stateWithChanges.state.processTtls(currentTime);
|
|
652
|
+
const availableNonces = updatedState.utxos.map((utxo) => utxo.nonce);
|
|
653
|
+
return [{
|
|
654
|
+
...wallet,
|
|
655
|
+
state: updatedState,
|
|
656
|
+
pendingDust: wallet.pendingDust.filter((t) => availableNonces.includes(t.nonce))
|
|
657
|
+
}, stateWithChanges.changes];
|
|
658
|
+
},
|
|
659
|
+
applyDustGenerations(wallet, dustCollapsedGenTreeSnapshot, newGenerations, generationDtimeUpdates) {
|
|
660
|
+
const applySnapshotGap = (state, lastIndex, nextGenerationIndex) => dustCollapsedGenTreeSnapshot.filter(({ startIndex, endIndex }) => startIndex > lastIndex && (nextGenerationIndex === void 0 || endIndex < nextGenerationIndex)).reduce((current, update) => current.applyGenerationCollapsedUpdate(readCollapsedUpdate(update)), state);
|
|
661
|
+
const { state: stateWithGenerations, lastIndex } = newGenerations.reduce((acc, { generationMtIndex, genInfo, qdo }) => ({
|
|
662
|
+
state: applySnapshotGap(acc.state, acc.lastIndex, generationMtIndex).insertGenerationInfo(BigInt(generationMtIndex), genInfo, qdo.backingNight),
|
|
663
|
+
lastIndex: generationMtIndex
|
|
664
|
+
}), {
|
|
665
|
+
state: wallet.state,
|
|
666
|
+
lastIndex: -1
|
|
667
|
+
});
|
|
668
|
+
const updatedState = generationDtimeUpdates.reduce((state, update) => state.updateGenerationTreeFromEvidence(readGenerationTreeInsertionPath(update.treeInsertionPath)), applySnapshotGap(stateWithGenerations, lastIndex));
|
|
669
|
+
return {
|
|
670
|
+
...wallet,
|
|
671
|
+
state: updatedState
|
|
672
|
+
};
|
|
673
|
+
},
|
|
674
|
+
applyNewDustUtxos(wallet, newDustUtxos) {
|
|
675
|
+
const updatedState = [...newDustUtxos].toSorted((a, b) => Number(a[1].qdo.mtIndex - b[1].qdo.mtIndex)).reduce((state, [dustNullifier, utxoInfo]) => state.addUtxo(dustNullifier, utxoInfo.qdo), wallet.state);
|
|
676
|
+
return {
|
|
677
|
+
...wallet,
|
|
678
|
+
state: updatedState
|
|
679
|
+
};
|
|
680
|
+
},
|
|
681
|
+
applyDustCommitments(wallet, newDustUtxos, collapsedCommitments) {
|
|
682
|
+
const newUtxos = [...require_dist.values(newDustUtxos)].toSorted((a, b) => Number(a.qdo.mtIndex - b.qdo.mtIndex));
|
|
683
|
+
const insertCommitments = (state, utxos) => utxos.reduce((current, utxoInfo) => current.insertCommitment(utxoInfo.qdo.mtIndex, utxoInfo.qdo, true), state);
|
|
684
|
+
const stateAfterCollapsed = collapsedCommitments.reduce((state, collapsed) => {
|
|
685
|
+
return insertCommitments(state, newUtxos.filter((utxoInfo) => Number(utxoInfo.qdo.mtIndex) < collapsed.startIndex && utxoInfo.qdo.mtIndex >= state.commitmentTreeFirstFree)).applyCommitmentCollapsedUpdate(readCollapsedUpdate(collapsed));
|
|
686
|
+
}, wallet.state);
|
|
687
|
+
const lastCollapsedIndex = collapsedCommitments.at(-1);
|
|
688
|
+
const updatedState = insertCommitments(stateAfterCollapsed, lastCollapsedIndex !== void 0 ? newUtxos.filter((utxoInfo) => Number(utxoInfo.qdo.mtIndex) > lastCollapsedIndex.endIndex) : newUtxos);
|
|
689
|
+
return {
|
|
690
|
+
...wallet,
|
|
691
|
+
state: updatedState
|
|
692
|
+
};
|
|
693
|
+
},
|
|
694
|
+
applySpentNullifiers(wallet, spentNullifiers) {
|
|
695
|
+
const updatedState = spentNullifiers.reduce((state, nullifier) => state.removeUtxo(nullifier), wallet.state);
|
|
696
|
+
return {
|
|
697
|
+
...wallet,
|
|
698
|
+
pendingDust: wallet.pendingDust.filter((d) => !spentNullifiers.includes(d.nullifier)),
|
|
699
|
+
state: updatedState
|
|
700
|
+
};
|
|
701
|
+
},
|
|
702
|
+
applyFailed(wallet, tx) {
|
|
703
|
+
const pendingSpendsMap = CoreWallet$1.pendingDustToMap(wallet.pendingDust);
|
|
704
|
+
const [updatedState, removedNullifiers] = require_dist.pipe(require_dist.pipe([...tx.intents?.values() ?? []], require_dist.flatMap$2((intent) => {
|
|
705
|
+
const spendTime = intent.dustActions?.ctime;
|
|
706
|
+
return (intent.dustActions?.spends ?? []).map((spend) => ({
|
|
707
|
+
spend,
|
|
708
|
+
spendTime
|
|
709
|
+
}));
|
|
710
|
+
}), require_dist.filterMap$1(({ spend, spendTime }) => require_dist.pipe(require_dist.fromNullable(pendingSpendsMap.get(spend.oldNullifier)), require_dist.map$5(() => ({
|
|
711
|
+
spend,
|
|
712
|
+
spendTime
|
|
713
|
+
}))))), require_dist.reduce([wallet.state, []], ([state, removed], { spend, spendTime }) => [state.processTtls(require_dist.addSeconds(spendTime, wallet.state.params.dustGracePeriodSeconds)), require_dist.append(removed, spend.oldNullifier)]));
|
|
714
|
+
return {
|
|
715
|
+
...wallet,
|
|
716
|
+
state: updatedState,
|
|
717
|
+
pendingDust: wallet.pendingDust.filter((coin) => !removedNullifiers.includes(coin.nullifier))
|
|
718
|
+
};
|
|
719
|
+
},
|
|
720
|
+
revertTransaction(wallet, tx) {
|
|
721
|
+
return CoreWallet$1.applyFailed(wallet, tx);
|
|
722
|
+
},
|
|
723
|
+
updateProgress(wallet, { appliedIndex, highestRelevantWalletIndex, highestIndex, highestRelevantIndex, isConnected }) {
|
|
724
|
+
const updatedProgress = require_dist.createSyncProgress({
|
|
725
|
+
appliedIndex: appliedIndex ?? wallet.progress.appliedIndex,
|
|
726
|
+
highestRelevantWalletIndex: highestRelevantWalletIndex ?? wallet.progress.highestRelevantWalletIndex,
|
|
727
|
+
highestIndex: highestIndex ?? wallet.progress.highestIndex,
|
|
728
|
+
highestRelevantIndex: highestRelevantIndex ?? wallet.progress.highestRelevantIndex,
|
|
729
|
+
isConnected: isConnected ?? wallet.progress.isConnected
|
|
730
|
+
});
|
|
731
|
+
return {
|
|
732
|
+
...wallet,
|
|
733
|
+
progress: updatedProgress
|
|
734
|
+
};
|
|
735
|
+
},
|
|
736
|
+
spendCoins(wallet, secretKey, coins, currentTime) {
|
|
737
|
+
const [output, newState, newPending] = require_dist.pipe(coins, require_dist.reduce([
|
|
738
|
+
[],
|
|
739
|
+
wallet.state,
|
|
740
|
+
wallet.pendingDust
|
|
741
|
+
], ([spends, localState, pending], { token: coinToSpend, value: takeFee }) => {
|
|
742
|
+
const [newState, dustSpend] = localState.spend(secretKey, coinToSpend, takeFee, currentTime);
|
|
743
|
+
const newPending = [...pending, {
|
|
744
|
+
...coinToSpend,
|
|
745
|
+
nullifier: dustSpend.oldNullifier
|
|
746
|
+
}];
|
|
747
|
+
return [
|
|
748
|
+
require_dist.append(spends, dustSpend),
|
|
749
|
+
newState,
|
|
750
|
+
newPending
|
|
751
|
+
];
|
|
752
|
+
}));
|
|
753
|
+
return [output, {
|
|
754
|
+
...wallet,
|
|
755
|
+
state: newState,
|
|
756
|
+
pendingDust: newPending
|
|
757
|
+
}];
|
|
758
|
+
},
|
|
759
|
+
pendingDustToMap(coins) {
|
|
760
|
+
return new Map(coins.map(({ nullifier, ...coins }) => [nullifier, coins]));
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
//#endregion
|
|
764
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/Utils.js
|
|
765
|
+
require__polyfill_buffer_patch.init__polyfill_buffer_patch();
|
|
766
|
+
const SignatureMarker$1 = {
|
|
767
|
+
signature: "signature",
|
|
768
|
+
signatureErased: "signature-erased"
|
|
769
|
+
};
|
|
770
|
+
const ProofMarker$1 = {
|
|
771
|
+
proof: "proof",
|
|
772
|
+
preProof: "pre-proof",
|
|
773
|
+
noProof: "no-proof"
|
|
774
|
+
};
|
|
775
|
+
const BindingMarker$1 = {
|
|
776
|
+
binding: "binding",
|
|
777
|
+
preBinding: "pre-binding",
|
|
778
|
+
noBinding: "no-binding"
|
|
779
|
+
};
|
|
780
|
+
const hashMapGroupBy = (arr, keyFn) => arr.reduce((map, v) => {
|
|
781
|
+
const key = keyFn(v);
|
|
782
|
+
return require_dist.set$1(map, key, require_dist.match$1(require_dist.get$2(map, key), {
|
|
783
|
+
onNone: () => [v],
|
|
784
|
+
onSome: (existing) => existing.concat(v)
|
|
785
|
+
}));
|
|
786
|
+
}, require_dist.empty$1());
|
|
787
|
+
const leBigintToHex = (n, dropLengthPrefix = false) => {
|
|
788
|
+
const encoded = require__polyfill_buffer_patch.import_buffer.Buffer.from(require_dist.ScaleBigInt.encode(n));
|
|
789
|
+
return (dropLengthPrefix ? encoded.subarray(1) : encoded).toString("hex");
|
|
790
|
+
};
|
|
791
|
+
const bigintToLeHex = (n, byteLength) => Array.from({ length: byteLength }, (_, i) => Number(n >> BigInt(8 * i) & 255n).toString(16).padStart(2, "0")).join("");
|
|
792
|
+
const uniqueArray = (arr) => Array.from(require_dist.fromIterable$1(arr));
|
|
793
|
+
/**
|
|
794
|
+
* Length (in HEX CHARACTERS) of the nullifier prefix to query the indexer with so it returns an anonymity set of
|
|
795
|
+
* ~2^anonymityLevel out of a population of `totalItems` commitments, per the ledger dust.md "Wallet recovery" math: a
|
|
796
|
+
* prefix of (log2(N) - anonymityLevel) BITS leaves a set of 2^anonymityLevel.
|
|
797
|
+
*
|
|
798
|
+
* BIT -> BYTE -> HEX-CHAR conversion: the indexer decodes each prefix with const_hex::decode, which accepts WHOLE BYTES
|
|
799
|
+
* only (8 bits/step, 4 bits per hex char, so 2 hex chars per byte). The returned value is consumed as `.substring(0,
|
|
800
|
+
* n)` on a hex string, hence it is a hex-char count and must be even.
|
|
801
|
+
*
|
|
802
|
+
* Rounding favours privacy: floor(log2(N)) under-estimates the population's entropy and floor(prefixBits/8) truncates
|
|
803
|
+
* the byte count DOWN, so the realized prefix is never LONGER than ideal — a shorter prefix yields a LARGER anonymity
|
|
804
|
+
* set, never dropping below 2^anonymityLevel.
|
|
805
|
+
*
|
|
806
|
+
* BYTE-GRANULARITY LIMITATION: because prefixes must be whole bytes and non-empty (min 1 byte = 2 hex chars), the exact
|
|
807
|
+
* 2^anonymityLevel target cannot always be hit. Where the min-1-byte floor is binding (small or low-entropy
|
|
808
|
+
* populations) it forces an 8-bit prefix that can make the realized set SMALLER than 2^anonymityLevel (e.g. N=2^14,
|
|
809
|
+
* n=7: ideal 7 bits, floor forces 8 bits -> set 2^6=64 < 128). This is an unavoidable protocol constraint (the indexer
|
|
810
|
+
* rejects empty prefixes) and is accepted.
|
|
811
|
+
*/
|
|
812
|
+
const calculatePrefixLength = (anonymityLevel, totalItems, maxLength) => {
|
|
813
|
+
const populationBits = totalItems <= 1 ? 0 : Math.floor(Math.log2(totalItems));
|
|
814
|
+
const prefixBits = Math.max(0, populationBits - anonymityLevel);
|
|
815
|
+
const idealHexChars = Math.floor(prefixBits / 8) * 2;
|
|
816
|
+
return Math.min(maxLength, Math.max(2, idealHexChars));
|
|
817
|
+
};
|
|
818
|
+
const gapRanges = (lastAppliedIndex, maxIndex, skipIndexes) => [lastAppliedIndex, ...skipIndexes].map((boundary, i) => ({
|
|
819
|
+
start: boundary + 1,
|
|
820
|
+
end: (skipIndexes.at(i) ?? maxIndex + 1) - 1
|
|
821
|
+
})).filter(({ start, end }) => start <= end);
|
|
822
|
+
//#endregion
|
|
823
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/Sync.js
|
|
824
|
+
/**
|
|
825
|
+
* Constructors and matchers for {@link BackgroundRepeat}.
|
|
826
|
+
*
|
|
827
|
+
* @example
|
|
828
|
+
* ```ts
|
|
829
|
+
* const service: SyncService<CoreWallet, DustSecretKey, WalletSyncUpdate> = {
|
|
830
|
+
* backgroundRepeat: BackgroundRepeat.Once(),
|
|
831
|
+
* updates: (state, secretKey) => subscribe(state, secretKey),
|
|
832
|
+
* blockData: () => latestBlock(),
|
|
833
|
+
* };
|
|
834
|
+
* ```;
|
|
835
|
+
*/
|
|
836
|
+
const BackgroundRepeat = require_dist.taggedEnum();
|
|
837
|
+
/**
|
|
838
|
+
* Splits a batch of version-tagged items at the end of a variant's activation range.
|
|
839
|
+
*
|
|
840
|
+
* @remarks
|
|
841
|
+
* The split is positional, not a filter: everything from the first out-of-range item onwards is deferred, even if a
|
|
842
|
+
* later item reports an in-range version again. A batch is a contiguous slice of one timeline, so applying past a
|
|
843
|
+
* boundary and then resuming behind it would leave a hole no cursor can describe.
|
|
844
|
+
*
|
|
845
|
+
* An item whose version is `undefined` is treated as in-range and contributes no annotation: an absent value means "the
|
|
846
|
+
* indexer did not say", which must keep the un-versioned behaviour exactly, rather than being read as version zero
|
|
847
|
+
* and dragging the recorded version down.
|
|
848
|
+
*
|
|
849
|
+
* This is the one place the boundary rule lives; the indexer capability (per event) and the simulator capability (per
|
|
850
|
+
* block) both go through it, so they cannot drift apart.
|
|
851
|
+
* @param items The batch, in source order.
|
|
852
|
+
* @param versionOf Reads the protocol version an item was reported at, or `undefined` if it carries none.
|
|
853
|
+
* @param activeRange The variant's half-open activation range.
|
|
854
|
+
* @returns The applied/deferred split and the version to record.
|
|
855
|
+
*/
|
|
856
|
+
const splitAtVersionBoundary = (items, versionOf, activeRange) => {
|
|
857
|
+
const [, end] = activeRange;
|
|
858
|
+
const boundary = items.findIndex((item) => {
|
|
859
|
+
const version = versionOf(item);
|
|
860
|
+
return version !== void 0 && BigInt(version) >= end;
|
|
861
|
+
});
|
|
862
|
+
const [applied, deferred] = boundary < 0 ? [items, []] : [items.slice(0, boundary), items.slice(boundary)];
|
|
863
|
+
const signalling = deferred.at(0) ?? [...applied].reverse().find((item) => versionOf(item) !== void 0);
|
|
864
|
+
const signalledVersion = signalling === void 0 ? void 0 : versionOf(signalling);
|
|
865
|
+
return {
|
|
866
|
+
applied,
|
|
867
|
+
deferred,
|
|
868
|
+
observedVersion: signalledVersion === void 0 ? require_dist.none() : require_dist.some(require_dist.ProtocolVersion(BigInt(signalledVersion)))
|
|
869
|
+
};
|
|
870
|
+
};
|
|
871
|
+
/** Records a batch's observed protocol version on the state, monotonically. A batch that observed none is a no-op. */
|
|
872
|
+
const annotateVersion = (state, observedVersion) => require_dist.match$1(observedVersion, {
|
|
873
|
+
onNone: () => state,
|
|
874
|
+
onSome: (version) => CoreWallet$1.withProtocolVersion(state, version)
|
|
875
|
+
});
|
|
876
|
+
/** How often the chain is asked its version when the configuration does not say. */
|
|
877
|
+
const DEFAULT_VERSION_WATCH_INTERVAL_MS$1 = 3e4;
|
|
878
|
+
/**
|
|
879
|
+
* How long one event-id probe is given to produce its single answer.
|
|
880
|
+
*
|
|
881
|
+
* @remarks
|
|
882
|
+
* Both a stall guard and, on a chain with no dust history at all, the ordinary way the tick ends. A wallet with a
|
|
883
|
+
* cursor subscribes at an event that provably exists, so there the answer arrives at once or the transport is broken;
|
|
884
|
+
* a wallet on a chain that has never produced a dust event subscribes to a timeline the indexer will keep open and
|
|
885
|
+
* never write to. Without a bound, either would leave the poll loop parked on a tick that never completes and the
|
|
886
|
+
* wallet would stop asking altogether. A bound turns both into a skipped tick.
|
|
887
|
+
*/
|
|
888
|
+
const EVENT_TIP_PROBE_TIMEOUT$1 = require_dist.seconds(10);
|
|
889
|
+
/**
|
|
890
|
+
* Asks the source how far its dust event timeline goes.
|
|
891
|
+
*
|
|
892
|
+
* @remarks
|
|
893
|
+
* Over the event subscription rather than a query, because the schema has no query that reaches a dust ledger event:
|
|
894
|
+
* `block`/`transactions` reach one only through a block that happens to contain dust events, which on a quiet chain
|
|
895
|
+
* is precisely the block that does not. `maxId` is a property of the whole dust timeline — the indexer computes it as
|
|
896
|
+
* the maximum id within the dust grouping — so any single event answers it: the first one delivered is taken and the
|
|
897
|
+
* subscription closed.
|
|
898
|
+
*
|
|
899
|
+
* The cursor is the wallet's own. The event it last applied provably exists, so the source answers immediately and has
|
|
900
|
+
* the least backfill to abandon; a wallet that has applied nothing asks from the start, where the first event is —
|
|
901
|
+
* or, on a chain with no dust event at all, where nothing is, and the tick times out into silence.
|
|
902
|
+
* @param config The sync configuration, carrying the keep-alive the source's subscriptions use.
|
|
903
|
+
* @param resumeFrom The wallet's cursor; below zero means "from the very start".
|
|
904
|
+
* @returns The highest dust event id, or nothing if the source did not answer.
|
|
905
|
+
*/
|
|
906
|
+
const highestEventId$1 = (config, resumeFrom) => require_dist.pipe(require_dist.DustLedgerEventTip.run({ id: resumeFrom < 0n ? null : Number(resumeFrom) }), require_dist.runHead, require_dist.map$2(require_dist.map$5((answer) => answer.dustLedgerEvents.maxId)), require_dist.scoped, require_dist.timeout(EVENT_TIP_PROBE_TIMEOUT$1));
|
|
907
|
+
/**
|
|
908
|
+
* One check of the chain's protocol version, gated on the wallet being caught up on the source's dust event ids.
|
|
909
|
+
*
|
|
910
|
+
* @remarks
|
|
911
|
+
* The order of the two questions is load-bearing. The tip is read **first**: a tip reported at a version means the
|
|
912
|
+
* source has indexed through the block that carries it, so every event below it is already counted in the `maxId`
|
|
913
|
+
* read afterwards. Asked the other way round, an event indexed between the two answers could be one of the version
|
|
914
|
+
* that preceded the tip — unread, uncounted, and exactly what the gate exists to catch.
|
|
915
|
+
*
|
|
916
|
+
* The one short-circuit is an answer rather than a shortcut: a tip at or below the version the wallet already held is a
|
|
917
|
+
* signal that could only be a no-op, so no probe is opened and nothing is emitted — which is what keeps a settled
|
|
918
|
+
* wallet from polling a subscription for the rest of its life. There is deliberately no second short-circuit for a
|
|
919
|
+
* chain that provably holds no dust event, because no such proof is available from the tip; see
|
|
920
|
+
* {@link VersionSignalSyncUpdate}.
|
|
921
|
+
*
|
|
922
|
+
* Everything else is swallowed. A tick that fails says nothing about the chain, so it must neither reach the state nor
|
|
923
|
+
* take the sync stream down with it; the next tick is the retry, and costs nothing to wait for.
|
|
924
|
+
* @param config The sync configuration, for the indexer to ask.
|
|
925
|
+
* @param resumeFrom The wallet's cursor, for the probe.
|
|
926
|
+
* @param knownVersion The version the wallet already held when this stream opened — a lower bound on what it holds now.
|
|
927
|
+
* @returns The signal, or nothing when there is nothing to say or nobody said it.
|
|
928
|
+
*/
|
|
929
|
+
const readVersionSignal$1 = (config, resumeFrom, knownVersion) => require_dist.pipe(require_dist.BlockHash.run({ offset: null }), require_dist.provide(require_dist.layer$1({ url: config.indexerClientConnection.indexerHttpUrl })), require_dist.scoped, require_dist.flatMap$1((answer) => require_dist.match$1(require_dist.fromNullable(answer.block), {
|
|
930
|
+
onNone: () => require_dist.succeedNone,
|
|
931
|
+
onSome: (tip) => BigInt(tip.protocolVersion) <= knownVersion ? require_dist.succeedNone : require_dist.pipe(highestEventId$1(config, resumeFrom), require_dist.map$2(require_dist.map$5((maxId) => VersionSignalSyncUpdate$1.create(tip.protocolVersion, maxId))))
|
|
932
|
+
})), require_dist.catchAll(() => require_dist.succeedNone));
|
|
933
|
+
/**
|
|
934
|
+
* The chain's version, re-asked on a timer for as long as sync runs.
|
|
935
|
+
*
|
|
936
|
+
* @remarks
|
|
937
|
+
* Deliberately silent about ticks that say nothing: a tick that finds the chain where the wallet left it, or that
|
|
938
|
+
* cannot reach the chain at all, emits no element rather than an empty one, so nothing downstream has to know that
|
|
939
|
+
* polling is how the answer was arrived at.
|
|
940
|
+
* @param config The sync configuration, carrying the interval.
|
|
941
|
+
* @param resumeFrom The wallet's cursor, for the probe.
|
|
942
|
+
* @param knownVersion The version the wallet held when this stream opened.
|
|
943
|
+
* @returns The signals, or an empty stream when watching is turned off.
|
|
944
|
+
*/
|
|
945
|
+
const versionWatch$1 = (config, resumeFrom, knownVersion) => {
|
|
946
|
+
const intervalMs = config.versionWatch?.intervalMs ?? DEFAULT_VERSION_WATCH_INTERVAL_MS$1;
|
|
947
|
+
return intervalMs <= 0 ? require_dist.empty : require_dist.pipe(require_dist.fromSchedule(require_dist.spaced(require_dist.millis(intervalMs))), require_dist.mapEffect(() => readVersionSignal$1(config, resumeFrom, knownVersion)), require_dist.filterMap(require_dist.identity));
|
|
948
|
+
};
|
|
949
|
+
const SecretKeysResource = { create: (secretKey) => {
|
|
950
|
+
return (cb) => {
|
|
951
|
+
const result = cb(secretKey);
|
|
952
|
+
secretKey.clear();
|
|
953
|
+
return result;
|
|
954
|
+
};
|
|
955
|
+
} };
|
|
956
|
+
const makeDefaultSyncService = (config) => {
|
|
957
|
+
const indexerSyncService = makeIndexerSyncService(config);
|
|
958
|
+
return {
|
|
959
|
+
backgroundRepeat: BackgroundRepeat.Once(),
|
|
960
|
+
updates: (state, secretKey) => {
|
|
961
|
+
const batchSize = config.batchUpdates?.size ?? 10;
|
|
962
|
+
const batchTimeout = require_dist.millis(config.batchUpdates?.timeout ?? 1);
|
|
963
|
+
const batchSpacing = config.batchUpdates?.spacing ?? 4;
|
|
964
|
+
const timeline = require_dist.pipe(indexerSyncService.subscribeWallet(state), require_dist.groupedWithin(batchSize, batchTimeout), require_dist.map(require_dist.toArray), require_dist.map((data) => WalletSyncUpdate$1.create(data, secretKey, /* @__PURE__ */ new Date())), batchSpacing > 0 ? require_dist.schedule(require_dist.spaced(require_dist.millis(batchSpacing))) : (eventsStream) => eventsStream);
|
|
965
|
+
const resumeFrom = state.progress.appliedIndex - 1n;
|
|
966
|
+
return require_dist.pipe(require_dist.merge(timeline, versionWatch$1(config, resumeFrom, state.protocolVersion), { haltStrategy: "left" }), require_dist.provideSomeLayer(indexerSyncService.connectionLayer()));
|
|
967
|
+
},
|
|
968
|
+
blockData: (height) => {
|
|
969
|
+
return require_dist.pipe(indexerSyncService.blockData(height), require_dist.provide(indexerSyncService.queryClient()), require_dist.scoped);
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
};
|
|
973
|
+
const accumulateUtxoUpdates = (updates, initialUtxos, initialSpentUtxos) => updates.reduce(({ nextUtxos, nextSpentUtxos }, update) => {
|
|
974
|
+
const entry = {
|
|
975
|
+
qdo: update.qdo,
|
|
976
|
+
transactionId: update.transactionId,
|
|
977
|
+
transactionHash: update.transactionHash,
|
|
978
|
+
genInfo: update.genInfo
|
|
979
|
+
};
|
|
980
|
+
return update.isSpent ? {
|
|
981
|
+
nextUtxos,
|
|
982
|
+
nextSpentUtxos: require_dist.set$1(nextSpentUtxos, update.dustNullifier, entry)
|
|
983
|
+
} : {
|
|
984
|
+
nextUtxos: require_dist.set$1(nextUtxos, update.dustNullifier, entry),
|
|
985
|
+
nextSpentUtxos
|
|
986
|
+
};
|
|
987
|
+
}, {
|
|
988
|
+
nextUtxos: initialUtxos,
|
|
989
|
+
nextSpentUtxos: initialSpentUtxos
|
|
990
|
+
});
|
|
991
|
+
const loadCollapsedCommitments = (lastAppliedIndex, maxIndex, newUtxos, indexerSyncService) => {
|
|
992
|
+
if (maxIndex < 0 || lastAppliedIndex === maxIndex) return require_dist.succeed([]);
|
|
993
|
+
return require_dist.pipe(gapRanges(lastAppliedIndex, maxIndex, [...newUtxos].toSorted((a, b) => Number(a[1].qdo.mtIndex - b[1].qdo.mtIndex)).map(([_, u]) => Number(u.qdo.mtIndex))).map(({ start, end }) => indexerSyncService.dustCommitmentMerkleTreeUpdate(start, end)), require_dist.all);
|
|
994
|
+
};
|
|
995
|
+
const NULLIFIER_BYTE_LENGTH = 32;
|
|
996
|
+
const NULLIFIER_LENGTH = NULLIFIER_BYTE_LENGTH * 2;
|
|
997
|
+
const nullifierPhaseProgress = (mtIndicesSum, totalNullifiers, freshCount, maxCommitmentEndIndex) => Math.min(Number(mtIndicesSum) + (totalNullifiers - freshCount) * maxCommitmentEndIndex, totalNullifiers * maxCommitmentEndIndex);
|
|
998
|
+
/**
|
|
999
|
+
* The applied index a mid-phase nullifier report carries, on the same basis as every other report in the pass.
|
|
1000
|
+
*
|
|
1001
|
+
* @remarks
|
|
1002
|
+
* The nullifier term is the larger of two true statements about the same work. {@link nullifierPhaseProgress} measures
|
|
1003
|
+
* this phase from zero, while the report that opened the phase already credited the nullifiers the wallet arrived
|
|
1004
|
+
* holding; early in the phase the credit is the further along of the two, and reporting the measurement alone would
|
|
1005
|
+
* take progress backwards.
|
|
1006
|
+
* @param basis The two terms this phase does not advance: commitment work, and nullifier work already credited.
|
|
1007
|
+
* @param generationWork The generation term, which is complete by the time this phase runs.
|
|
1008
|
+
* @param phaseProgress What {@link nullifierPhaseProgress} has measured so far.
|
|
1009
|
+
* @returns The applied index to report.
|
|
1010
|
+
*/
|
|
1011
|
+
const nullifierPhaseAppliedIndex = (basis, generationWork, phaseProgress) => generationWork + basis.commitmentWork + Math.max(basis.creditedNullifierWork, phaseProgress);
|
|
1012
|
+
const resolveNullifierSpends = (initialNullifiers, initialNewUtxos, pendingDust, dustState, secretKey, latestBlock, dustGenerationUpdates, indexerSyncService, anonymityLevel, ledgerParametersCodecs, progressBasis, emit) => {
|
|
1013
|
+
const maxCommitmentEndIndex = latestBlock.dustCommitmentEndIndex - 1;
|
|
1014
|
+
const initialSpentUtxos = require_dist.empty$1();
|
|
1015
|
+
return require_dist.pipe(require_dist.unfoldEffect([
|
|
1016
|
+
initialNullifiers,
|
|
1017
|
+
initialNewUtxos,
|
|
1018
|
+
initialSpentUtxos
|
|
1019
|
+
], ([nullifiersToCheck, newUtxos, spentUtxos]) => {
|
|
1020
|
+
if (nullifiersToCheck.length === 0) return require_dist.succeed(require_dist.none());
|
|
1021
|
+
return require_dist.gen(function* () {
|
|
1022
|
+
const prefixLength = calculatePrefixLength(anonymityLevel, maxCommitmentEndIndex, NULLIFIER_LENGTH);
|
|
1023
|
+
const dustUtxoUpdates = yield* createDustUtxoUpdates(dustState, matchedDustSpends(yield* require_dist.pipe(indexerSyncService.subscribeDustNullifierTransactions(nullifiersToCheck, latestBlock.height, prefixLength), require_dist.runCollect, require_dist.map$2(require_dist.toArray))), secretKey, newUtxos, pendingDust, dustGenerationUpdates.generationDtimeUpdates, ledgerParametersCodecs);
|
|
1024
|
+
const freshUtxos = dustUtxoUpdates.filter((u) => !u.isSpent);
|
|
1025
|
+
if (freshUtxos.length > 0) {
|
|
1026
|
+
const mtIndicesSum = freshUtxos.reduce((partialSum, a) => partialSum + a.qdo.mtIndex, 0n);
|
|
1027
|
+
const generationEndIndex = latestBlock.dustGenerationEndIndex - 1;
|
|
1028
|
+
const progress = nullifierPhaseProgress(mtIndicesSum, initialNullifiers.length, freshUtxos.length, maxCommitmentEndIndex);
|
|
1029
|
+
yield* require_dist.promise(() => emit.single(ProgressUpdate({ appliedIndex: nullifierPhaseAppliedIndex(progressBasis, generationEndIndex, progress) })));
|
|
1030
|
+
}
|
|
1031
|
+
const { nextUtxos, nextSpentUtxos } = accumulateUtxoUpdates(dustUtxoUpdates, newUtxos, spentUtxos);
|
|
1032
|
+
const nextNullifiersToCheck = dustUtxoUpdates.filter((u) => !u.isSpent).map((u) => u.dustNullifier);
|
|
1033
|
+
return require_dist.some([{
|
|
1034
|
+
nextUtxos,
|
|
1035
|
+
nextSpentUtxos
|
|
1036
|
+
}, [
|
|
1037
|
+
nextNullifiersToCheck,
|
|
1038
|
+
nextUtxos,
|
|
1039
|
+
nextSpentUtxos
|
|
1040
|
+
]]);
|
|
1041
|
+
});
|
|
1042
|
+
}), require_dist.runCollect, require_dist.map$2(require_dist.toArray), require_dist.map$2((results) => require_dist.pipe(require_dist.last(results), require_dist.getOrElse(() => ({
|
|
1043
|
+
nextUtxos: initialNewUtxos,
|
|
1044
|
+
nextSpentUtxos: require_dist.empty$1()
|
|
1045
|
+
})))));
|
|
1046
|
+
};
|
|
1047
|
+
const doEventlessSync = (state, secretKey, anonymityLevel, indexerSyncService, ledgerParametersCodecs = defaultLedgerParametersCodecs$1) => {
|
|
1048
|
+
return require_dist.asyncEffect((emit) => require_dist.gen(function* () {
|
|
1049
|
+
const latestBlock = yield* indexerSyncService.blockData();
|
|
1050
|
+
const maxCommitmentTreeIndex = latestBlock.dustCommitmentEndIndex - 1;
|
|
1051
|
+
const maxGeneratingTreeIndex = latestBlock.dustGenerationEndIndex - 1;
|
|
1052
|
+
const lastSyncedCommitmentIndex = state.state.commitmentTreeFirstFree - 1n;
|
|
1053
|
+
const lastSyncedGenerationIndex = state.state.generatingTreeFirstFree - 1n;
|
|
1054
|
+
const lastSyncedBlockHeight = state.progress.highestIndex;
|
|
1055
|
+
const commitmentWork = Number(lastSyncedCommitmentIndex);
|
|
1056
|
+
const creditedNullifierWork = state.state.nullifiers.size * maxCommitmentTreeIndex;
|
|
1057
|
+
const highestInitialIndex = maxGeneratingTreeIndex + maxCommitmentTreeIndex + creditedNullifierWork;
|
|
1058
|
+
const initialAppliedIndex = Number(lastSyncedGenerationIndex) + commitmentWork + creditedNullifierWork;
|
|
1059
|
+
yield* require_dist.logDebug(`Projections sync resuming from block height ${lastSyncedBlockHeight}, generation index ${lastSyncedGenerationIndex}, commitment index ${lastSyncedCommitmentIndex}; chain at block ${latestBlock.height} with generation index ${maxGeneratingTreeIndex} and commitment index ${maxCommitmentTreeIndex}`);
|
|
1060
|
+
yield* require_dist.promise(() => emit.single(ProgressUpdate({
|
|
1061
|
+
highestRelevantIndex: highestInitialIndex,
|
|
1062
|
+
appliedIndex: initialAppliedIndex
|
|
1063
|
+
})));
|
|
1064
|
+
const rawGenerations = yield* require_dist.pipe(indexerSyncService.subscribeDustGenerations(require_dist.DustAddress.encodePublicKey(state.networkId, secretKey.publicKey), Number(lastSyncedBlockHeight), maxGeneratingTreeIndex, latestBlock), require_dist.runCollect, require_dist.map$2(require_dist.toArray));
|
|
1065
|
+
const dustGenerationUpdates = DustGenerationsSyncUpdate.create(rawGenerations, secretKey, state.publicKey, lastSyncedGenerationIndex);
|
|
1066
|
+
const allNullifiers = dustGenerationUpdates.newGenerations.map((n) => n.dustNullifier).concat([...state.state.nullifiers.keys(), ...state.pendingDust.map((d) => d.nullifier)]);
|
|
1067
|
+
const highestRelevantIndex = maxGeneratingTreeIndex + maxCommitmentTreeIndex + allNullifiers.length * maxCommitmentTreeIndex;
|
|
1068
|
+
yield* require_dist.promise(() => emit.single(ProgressUpdate({
|
|
1069
|
+
highestRelevantIndex,
|
|
1070
|
+
appliedIndex: maxGeneratingTreeIndex + commitmentWork + creditedNullifierWork
|
|
1071
|
+
})));
|
|
1072
|
+
const { nextUtxos: finalUtxos, nextSpentUtxos: finalSpentUtxos } = yield* resolveNullifierSpends(allNullifiers, DustUtxoMap.create(dustGenerationUpdates.newGenerations), CoreWallet$1.pendingDustToMap(state.pendingDust), state.state, secretKey, latestBlock, dustGenerationUpdates, indexerSyncService, anonymityLevel, ledgerParametersCodecs, {
|
|
1073
|
+
commitmentWork,
|
|
1074
|
+
creditedNullifierWork
|
|
1075
|
+
}, emit);
|
|
1076
|
+
yield* require_dist.promise(() => emit.single(ProgressUpdate({ appliedIndex: maxGeneratingTreeIndex + commitmentWork + allNullifiers.length * maxCommitmentTreeIndex })));
|
|
1077
|
+
const collapsedCommitments = yield* loadCollapsedCommitments(Number(lastSyncedCommitmentIndex), maxCommitmentTreeIndex, finalUtxos, indexerSyncService);
|
|
1078
|
+
yield* require_dist.promise(() => emit.single(StateUpdate({
|
|
1079
|
+
dustGenerations: dustGenerationUpdates,
|
|
1080
|
+
spentUtxos: finalSpentUtxos,
|
|
1081
|
+
newUtxos: finalUtxos,
|
|
1082
|
+
collapsedCommitments,
|
|
1083
|
+
latestBlock
|
|
1084
|
+
})));
|
|
1085
|
+
yield* require_dist.promise(() => emit.single(ProgressUpdate({ appliedIndex: highestRelevantIndex })));
|
|
1086
|
+
yield* require_dist.promise(() => emit.end());
|
|
1087
|
+
}), "unbounded");
|
|
1088
|
+
};
|
|
1089
|
+
const makeEventLessSyncService = (config) => {
|
|
1090
|
+
const defaultSyncService = makeDefaultSyncService(config);
|
|
1091
|
+
const indexerSyncService = makeIndexerSyncService(config);
|
|
1092
|
+
const anonymityLevel = config.anonymityLevel ?? 7;
|
|
1093
|
+
return {
|
|
1094
|
+
backgroundRepeat: BackgroundRepeat.WithDelay({ delay: require_dist.millis(config.backgroundSyncInterval ?? 5e3) }),
|
|
1095
|
+
updates: (state, secretKey) => require_dist.pipe(doEventlessSync(state, secretKey, anonymityLevel, indexerSyncService, config.ledgerParametersCodecs ?? defaultLedgerParametersCodecs$1), require_dist.provideSomeLayer(require_dist.merge$1(indexerSyncService.connectionLayer(), indexerSyncService.queryClient()))),
|
|
1096
|
+
blockData: defaultSyncService.blockData
|
|
1097
|
+
};
|
|
1098
|
+
};
|
|
1099
|
+
const makeIndexerSyncService = (config) => {
|
|
1100
|
+
return {
|
|
1101
|
+
queryClient() {
|
|
1102
|
+
return require_dist.pipe(require_dist.layer$1({ url: config.indexerClientConnection.indexerHttpUrl }), require_dist.mapError$1((error) => new OtherWalletError$1(error)));
|
|
1103
|
+
},
|
|
1104
|
+
connectionLayer() {
|
|
1105
|
+
const { indexerClientConnection } = config;
|
|
1106
|
+
return require_dist.createWebSocketUrl(indexerClientConnection.indexerHttpUrl, indexerClientConnection.indexerWsUrl).pipe(require_dist.flatMap$4((url) => require_dist.make(url)), require_dist.match$2({
|
|
1107
|
+
onLeft: (error) => require_dist.fail$1(error),
|
|
1108
|
+
onRight: (url) => require_dist.layer({
|
|
1109
|
+
url,
|
|
1110
|
+
keepAlive: indexerClientConnection.keepAlive
|
|
1111
|
+
})
|
|
1112
|
+
}), require_dist.mapError$1((e) => new SyncWalletError$1({
|
|
1113
|
+
message: "Failed to obtain correct indexer URLs",
|
|
1114
|
+
cause: e
|
|
1115
|
+
})));
|
|
1116
|
+
},
|
|
1117
|
+
subscribeWallet(state) {
|
|
1118
|
+
const { appliedIndex } = state.progress;
|
|
1119
|
+
const bufferSize = config.indexerClientConnection.bufferSize ?? 1e4;
|
|
1120
|
+
const resumeThreshold = config.indexerClientConnection.resumeThreshold ?? 100;
|
|
1121
|
+
const resumeFrom = appliedIndex - 1n;
|
|
1122
|
+
return require_dist.pipe(require_dist.DustLedgerEvents.runWithBackpressure({
|
|
1123
|
+
bufferSize,
|
|
1124
|
+
resumeThreshold,
|
|
1125
|
+
from: resumeFrom,
|
|
1126
|
+
variables: (cursor) => ({ id: cursor < 0n ? null : Number(cursor) }),
|
|
1127
|
+
key: (r) => BigInt(r.dustLedgerEvents.id)
|
|
1128
|
+
}), require_dist.mapEffect((subscription) => require_dist.pipe(require_dist.decodeUnknownEither(SyncEventsUpdateSchema$1)(subscription.dustLedgerEvents), require_dist.mapLeft((err) => new SyncWalletError$1(err)), require_dist.toEffect)), require_dist.mapError((error) => new SyncWalletError$1(error)));
|
|
1129
|
+
},
|
|
1130
|
+
subscribeDustGenerations(dustAddress, lastSyncedBlockHeight, maxGeneratingTreeIndex, latestBlock) {
|
|
1131
|
+
if (maxGeneratingTreeIndex < 0 || latestBlock.height === lastSyncedBlockHeight && lastSyncedBlockHeight !== 0) return require_dist.empty;
|
|
1132
|
+
return require_dist.pipe(require_dist.DustGenerationEvents.run({
|
|
1133
|
+
dustAddress,
|
|
1134
|
+
blockHash: latestBlock.hash,
|
|
1135
|
+
dtimeCutoffHeight: lastSyncedBlockHeight
|
|
1136
|
+
}), require_dist.mapEffect((subscription) => {
|
|
1137
|
+
return require_dist.pipe(require_dist.decodeUnknownEither(DustGenerationsSubscriptionSchema)(subscription.dustGenerations), require_dist.mapLeft((err) => new SyncWalletError$1(err)), require_dist.toEffect);
|
|
1138
|
+
}), require_dist.mapError((error) => new SyncWalletError$1(error)));
|
|
1139
|
+
},
|
|
1140
|
+
subscribeDustNullifierTransactions(dustNullifiers, toBlock, prefixLength) {
|
|
1141
|
+
const hexedNullifiers = require_dist.fromIterable$1(dustNullifiers.map((n) => bigintToLeHex(n, NULLIFIER_BYTE_LENGTH)));
|
|
1142
|
+
return require_dist.pipe(require_dist.DustNullifierTransactions.run({
|
|
1143
|
+
nullifierLeBytesPrefixes: uniqueArray([...hexedNullifiers].map((n) => n.substring(0, prefixLength))),
|
|
1144
|
+
fromBlock: 0,
|
|
1145
|
+
toBlock
|
|
1146
|
+
}), require_dist.filter((subscription) => require_dist.has$1(hexedNullifiers, subscription.dustNullifierTransactions.nullifierLeBytes)), require_dist.mapEffect((subscription) => {
|
|
1147
|
+
return require_dist.pipe(require_dist.decodeUnknownEither(DustNullifierTransactionSubscriptionSchema)(subscription.dustNullifierTransactions), require_dist.mapLeft((err) => new SyncWalletError$1(err)), require_dist.toEffect);
|
|
1148
|
+
}), require_dist.mapError((error) => new SyncWalletError$1(error)));
|
|
1149
|
+
},
|
|
1150
|
+
dustCommitmentMerkleTreeUpdate(startIndex, endIndex) {
|
|
1151
|
+
return require_dist.pipe(require_dist.DustCommitmentMerkleTreeUpdate.run({
|
|
1152
|
+
startIndex,
|
|
1153
|
+
endIndex
|
|
1154
|
+
}), require_dist.flatMap$1((result) => {
|
|
1155
|
+
return require_dist.pipe(require_dist.decodeUnknownEither(CollapsedMerkleTreeSchema)(result.dustCommitmentMerkleTreeUpdate), require_dist.mapLeft((err) => new SyncWalletError$1(err)), require_dist.toEffect);
|
|
1156
|
+
}), require_dist.catchAll((err) => require_dist.fail$2(new OtherWalletError$1({
|
|
1157
|
+
message: `Encountered unexpected error: ${err.message}`,
|
|
1158
|
+
cause: err
|
|
1159
|
+
}))));
|
|
1160
|
+
},
|
|
1161
|
+
blockData: (height) => {
|
|
1162
|
+
return require_dist.pipe(require_dist.BlockHash.run({ offset: height !== void 0 ? { height } : null }), require_dist.mapError$2((err) => new OtherWalletError$1({
|
|
1163
|
+
message: `Encountered unexpected error: ${err.message}`,
|
|
1164
|
+
cause: err
|
|
1165
|
+
})), require_dist.flatMap$1((result) => {
|
|
1166
|
+
if (!result.block) return require_dist.fail$2(new OtherWalletError$1({ message: "Unable to fetch block data" }));
|
|
1167
|
+
return require_dist.pipe(require_dist.decodeUnknownEither(makeBlockDataSchema(config.ledgerParametersCodecs ?? defaultLedgerParametersCodecs$1))(result.block), require_dist.mapLeft((err) => new SyncWalletError$1(err)), require_dist.toEffect);
|
|
1168
|
+
}));
|
|
1169
|
+
}
|
|
1170
|
+
};
|
|
1171
|
+
};
|
|
1172
|
+
/** The result of an update that observed nothing of the chain. */
|
|
1173
|
+
const noChanges$1 = (state) => ({
|
|
1174
|
+
changes: [],
|
|
1175
|
+
protocolVersion: Number(state.protocolVersion)
|
|
1176
|
+
});
|
|
1177
|
+
/**
|
|
1178
|
+
* Folds what the chain said about its own version into the wallet state.
|
|
1179
|
+
*
|
|
1180
|
+
* @remarks
|
|
1181
|
+
* The same recording the event path makes through {@link annotateVersion}, and nothing else: no cursor moves, no dust
|
|
1182
|
+
* changes hands, no tree grows. A signal is an observation about the chain, not a piece of it.
|
|
1183
|
+
*
|
|
1184
|
+
* One situation makes the observation unsafe to record, and it leaves the state exactly as it was: unread events below
|
|
1185
|
+
* the source's tip mean the hand-over would park the cursor in front of history the next variant cannot read — and
|
|
1186
|
+
* those events carry the version themselves, so nothing is lost by waiting for them. That is not an error: the next
|
|
1187
|
+
* tick asks again.
|
|
1188
|
+
*
|
|
1189
|
+
* A version at or below the one already recorded needs no guard of its own — {@link annotateVersion} never goes
|
|
1190
|
+
* backwards — so a source briefly answering from a lagging replica cannot drag a wallet back over a boundary.
|
|
1191
|
+
* @param state The wallet to record on.
|
|
1192
|
+
* @param update What the chain said, and how far its dust event timeline goes.
|
|
1193
|
+
* @returns The wallet, annotated or untouched, and an empty result.
|
|
1194
|
+
*/
|
|
1195
|
+
const applyVersionSignal$1 = (state, update) => [BigInt(update.highestEventId) > state.progress.appliedIndex ? state : annotateVersion(state, require_dist.some(require_dist.ProtocolVersion(BigInt(update.version)))), noChanges$1(state)];
|
|
1196
|
+
/**
|
|
1197
|
+
* Checks that freshly delivered events arrive in strictly ascending id order.
|
|
1198
|
+
*
|
|
1199
|
+
* @remarks
|
|
1200
|
+
* Order is all that can be checked, never contiguity: dust events share one id sequence with zswap and contract events
|
|
1201
|
+
* in the indexer, so gaps in a dust stream are normal. A skipped commitment-inserting event is caught by the ledger's
|
|
1202
|
+
* own insertion check instead. An empty batch is trivially ordered.
|
|
1203
|
+
* @param fresh The events left after the cursor filter, in source order.
|
|
1204
|
+
* @param appliedIndex The highest event id already applied; the first fresh id must exceed it.
|
|
1205
|
+
* @returns The batch unchanged, or the first id that fails to exceed its predecessor as an
|
|
1206
|
+
* {@link OutOfOrderSyncUpdateError}.
|
|
1207
|
+
*/
|
|
1208
|
+
const expectAscending$1 = (fresh, appliedIndex) => require_dist.pipe(require_dist.zipWith(fresh, require_dist.prepend(require_dist.map$3(fresh, (item) => BigInt(item.id)), appliedIndex), (item, previous) => ({
|
|
1209
|
+
item,
|
|
1210
|
+
previous
|
|
1211
|
+
})), require_dist.findFirst(({ item, previous }) => BigInt(item.id) <= previous), require_dist.match$1({
|
|
1212
|
+
onNone: () => require_dist.right(fresh),
|
|
1213
|
+
onSome: ({ item, previous }) => require_dist.left(new OutOfOrderSyncUpdateError$1({
|
|
1214
|
+
message: `Dust event ${item.id} delivered at or below its predecessor ${previous}; batch refused, applied index stays at ${appliedIndex}`,
|
|
1215
|
+
expected: previous,
|
|
1216
|
+
received: BigInt(item.id)
|
|
1217
|
+
}))
|
|
1218
|
+
}));
|
|
1219
|
+
const makeDefaultSyncCapability = () => {
|
|
1220
|
+
return { applyUpdate(state, wrappedUpdate, activeRange) {
|
|
1221
|
+
if (wrappedUpdate._tag === "VersionSignal") return applyVersionSignal$1(state, wrappedUpdate);
|
|
1222
|
+
const { updates, secretKey } = wrappedUpdate;
|
|
1223
|
+
if (updates.length === 0) return [state, {
|
|
1224
|
+
changes: [],
|
|
1225
|
+
protocolVersion: Number(state.protocolVersion)
|
|
1226
|
+
}];
|
|
1227
|
+
const appliedIndex = state.progress.appliedIndex;
|
|
1228
|
+
const freshUpdates = updates.filter((u) => BigInt(u.id) > appliedIndex);
|
|
1229
|
+
const highestRelevantWalletIndex = BigInt(updates.at(-1).maxId);
|
|
1230
|
+
const { applied, observedVersion } = splitAtVersionBoundary(require_dist.getOrThrowWith(expectAscending$1(freshUpdates, appliedIndex), require_dist.identity), (update) => update.protocolVersion, activeRange);
|
|
1231
|
+
const [newState, changes] = applied.length === 0 ? [state, []] : CoreWallet$1.applyEventsWithChanges(state, secretKey, applied.map(readEvent$1), wrappedUpdate.timestamp);
|
|
1232
|
+
return [CoreWallet$1.updateProgress(annotateVersion(newState, observedVersion), {
|
|
1233
|
+
appliedIndex: applied.length === 0 ? appliedIndex : BigInt(applied.at(-1).id),
|
|
1234
|
+
highestRelevantWalletIndex,
|
|
1235
|
+
isConnected: true
|
|
1236
|
+
}), {
|
|
1237
|
+
changes,
|
|
1238
|
+
protocolVersion: [...applied].reverse().find((u) => u.protocolVersion !== void 0)?.protocolVersion ?? Number(state.protocolVersion)
|
|
1239
|
+
}];
|
|
1240
|
+
} };
|
|
1241
|
+
};
|
|
1242
|
+
/**
|
|
1243
|
+
* The projections-based fast-sync capability.
|
|
1244
|
+
*
|
|
1245
|
+
* @remarks
|
|
1246
|
+
* **This path does not implement the fork boundary, and cannot yet.** It takes `activeRange` for signature parity with
|
|
1247
|
+
* the other capabilities and deliberately ignores it: a projections update is a folded snapshot of dust state —
|
|
1248
|
+
* Merkle tree updates, new and spent UTXOs, a block header — not a sequence of version-tagged timeline items, so
|
|
1249
|
+
* there is nothing in it to split and nothing that reports the protocol version a piece of it belongs to. `BlockData`
|
|
1250
|
+
* carries height, hash, timestamp and ledger parameters, but no version.
|
|
1251
|
+
*
|
|
1252
|
+
* A wallet syncing through this path therefore never annotates a version and never hands over. Closing that needs a
|
|
1253
|
+
* version on the projections wire format, which is the same deferred indexer question as the one on
|
|
1254
|
+
* `SyncEventsUpdateSchema` — recorded here rather than papered over with a boundary check that would silently do
|
|
1255
|
+
* nothing.
|
|
1256
|
+
*
|
|
1257
|
+
* The version watcher {@link makeDefaultSyncService} carries does not close it either, and is deliberately not fitted to
|
|
1258
|
+
* {@link makeEventLessSyncService}: the watcher's gate is "the wallet is level with the source's dust event ids", and
|
|
1259
|
+
* this path keeps no such cursor — its `appliedIndex` counts Merkle indices and nullifier scans, not events — so
|
|
1260
|
+
* there is nothing here for the gate to compare against.
|
|
1261
|
+
*/
|
|
1262
|
+
const makeEventLessSyncCapability = () => {
|
|
1263
|
+
return { applyUpdate(state, update, _activeRange) {
|
|
1264
|
+
if (isProgressUpdate(update)) return [CoreWallet$1.updateProgress(state, {
|
|
1265
|
+
appliedIndex: BigInt(update.appliedIndex ?? state.progress.appliedIndex),
|
|
1266
|
+
highestRelevantWalletIndex: BigInt(update.highestRelevantIndex ?? state.progress.highestRelevantWalletIndex),
|
|
1267
|
+
isConnected: true
|
|
1268
|
+
}), {
|
|
1269
|
+
changes: [],
|
|
1270
|
+
protocolVersion: Number(state.protocolVersion)
|
|
1271
|
+
}];
|
|
1272
|
+
const { dustGenerations, spentUtxos, newUtxos, collapsedCommitments, latestBlock } = update;
|
|
1273
|
+
const dustGenTreeUpdates = dustGenerations.rawUpdates.filter((u) => u.__typename === "DustGenerationsItem" || u.__typename === "DustGenerationsProgress").map((u) => u.collapsedMerkleTree).filter((update) => update !== null).toSorted((u1, u2) => u1.startIndex - u2.startIndex);
|
|
1274
|
+
const walletWithAppliedUpdates = require_dist.pipe(CoreWallet$1.applyDustGenerations(state, dustGenTreeUpdates, dustGenerations.newGenerations, dustGenerations.generationDtimeUpdates), (wallet) => CoreWallet$1.applyNewDustUtxos(wallet, newUtxos), (wallet) => CoreWallet$1.applyDustCommitments(wallet, newUtxos, collapsedCommitments), (wallet) => CoreWallet$1.applySpentNullifiers(wallet, [...require_dist.keys(spentUtxos)]));
|
|
1275
|
+
const groupedNewUtxos = hashMapGroupBy([...require_dist.values(newUtxos)], (u) => u.transactionId);
|
|
1276
|
+
const groupedSpentUtxos = hashMapGroupBy([...require_dist.values(spentUtxos)], (u) => u.transactionId);
|
|
1277
|
+
const changes = uniqueArray([...require_dist.keys(groupedNewUtxos), ...require_dist.keys(groupedSpentUtxos)]).toSorted().map((txId) => {
|
|
1278
|
+
const received = require_dist.getOrElse(require_dist.get$2(groupedNewUtxos, txId), () => []);
|
|
1279
|
+
const spent = require_dist.getOrElse(require_dist.get$2(groupedSpentUtxos, txId), () => []);
|
|
1280
|
+
return new _midnightntwrk_ledger_v9.DustStateChanges(received.at(0)?.transactionHash || spent.at(0)?.transactionHash, received.map(({ qdo }) => qdo), spent.map(({ qdo }) => qdo));
|
|
1281
|
+
});
|
|
1282
|
+
const updatedDustState = walletWithAppliedUpdates.state.processTtls(latestBlock.timestamp);
|
|
1283
|
+
updatedDustState.syncTime = latestBlock.timestamp;
|
|
1284
|
+
const walletAtLatestBlock = {
|
|
1285
|
+
...walletWithAppliedUpdates,
|
|
1286
|
+
state: updatedDustState
|
|
1287
|
+
};
|
|
1288
|
+
const newCommitmentTreeRoot = walletAtLatestBlock.state.commitmentTreeRoot() !== void 0 ? leBigintToHex(walletAtLatestBlock.state.commitmentTreeRoot()) : "";
|
|
1289
|
+
const newGeneratingTreeRoot = walletAtLatestBlock.state.generatingTreeRoot() !== void 0 ? leBigintToHex(walletAtLatestBlock.state.generatingTreeRoot()) : "";
|
|
1290
|
+
if (newCommitmentTreeRoot !== update.latestBlock.dustCommitmentMerkleTreeRoot || newGeneratingTreeRoot !== update.latestBlock.dustGenerationMerkleTreeRoot) throw new OtherWalletError$1({ message: "Root hashes don`t match" });
|
|
1291
|
+
return [CoreWallet$1.updateProgress(walletAtLatestBlock, { highestIndex: BigInt(update.latestBlock.height) }), {
|
|
1292
|
+
changes,
|
|
1293
|
+
protocolVersion: Number(state.protocolVersion)
|
|
1294
|
+
}];
|
|
1295
|
+
} };
|
|
1296
|
+
};
|
|
1297
|
+
const createUtxoUpdatesFromSpend = (dustState, secretKey, knownUtxos, pendingDust, generationDtimeUpdates, transaction, dustSpend, ledgerParametersCodecs) => require_dist.gen(function* () {
|
|
1298
|
+
const { nullifier, vFee, commitmentIndex, declaredTime } = dustSpend;
|
|
1299
|
+
const knownUtxo = require_dist.getOrUndefined(require_dist.get$2(knownUtxos, nullifier));
|
|
1300
|
+
const qdo = knownUtxo?.qdo ?? pendingDust.get(nullifier) ?? dustState.findUtxoByNullifier(nullifier);
|
|
1301
|
+
if (!qdo) {
|
|
1302
|
+
yield* require_dist.logDebug(`Skipping dust spend of a nullifier not owned by this wallet: ${nullifier}`);
|
|
1303
|
+
return require_dist.none();
|
|
1304
|
+
}
|
|
1305
|
+
const genInfo = knownUtxo?.genInfo ?? dustState.generationInfo(qdo);
|
|
1306
|
+
if (!genInfo) return yield* new SyncWalletError$1({ message: `Failed to find generation info for: ${qdo.backingNight}` });
|
|
1307
|
+
const dtimeUpdate = generationDtimeUpdates.find((upd) => upd.nightUtxoHash === genInfo.nonce);
|
|
1308
|
+
const updatedGenInfo = dtimeUpdate !== void 0 ? {
|
|
1309
|
+
...genInfo,
|
|
1310
|
+
dtime: dtimeUpdate.newDtime
|
|
1311
|
+
} : genInfo;
|
|
1312
|
+
const txMeta = {
|
|
1313
|
+
transactionId: transaction.id,
|
|
1314
|
+
transactionHash: transaction.hash,
|
|
1315
|
+
genInfo: updatedGenInfo
|
|
1316
|
+
};
|
|
1317
|
+
const spentUtxoUpdate = {
|
|
1318
|
+
dustNullifier: nullifier,
|
|
1319
|
+
qdo,
|
|
1320
|
+
isSpent: true,
|
|
1321
|
+
...txMeta
|
|
1322
|
+
};
|
|
1323
|
+
const successorUtxo = (0, _midnightntwrk_ledger_v9.successorDustUtxo)(qdo, declaredTime, vFee, commitmentIndex, updatedGenInfo, secretKey, (yield* require_dist.pipe(readNullifierBlockParameters(transaction.block, ledgerParametersCodecs), require_dist.mapLeft((error) => new SyncWalletError$1({
|
|
1324
|
+
message: error.message,
|
|
1325
|
+
cause: error
|
|
1326
|
+
})), require_dist.toEffect)).dust);
|
|
1327
|
+
const newUtxoUpdate = {
|
|
1328
|
+
dustNullifier: (0, _midnightntwrk_ledger_v9.dustNullifier)(successorUtxo, secretKey),
|
|
1329
|
+
qdo: successorUtxo,
|
|
1330
|
+
isSpent: false,
|
|
1331
|
+
...txMeta
|
|
1332
|
+
};
|
|
1333
|
+
return require_dist.some([spentUtxoUpdate, newUtxoUpdate]);
|
|
1334
|
+
});
|
|
1335
|
+
/**
|
|
1336
|
+
* Reads the dust spends out of the transactions a nullifier lookup matched.
|
|
1337
|
+
*
|
|
1338
|
+
* @remarks
|
|
1339
|
+
* Separate from resolving them, because this is the step that touches bytes. The lookup matches on a nullifier _prefix_
|
|
1340
|
+
* and searches from block zero, so it deliberately over-delivers: most of what it returns belongs to other parties,
|
|
1341
|
+
* and on a chain that has forked some of it belongs to the previous ledger version. An event this ledger version
|
|
1342
|
+
* cannot read is therefore by construction not one of this wallet's spends, and is skipped rather than failing the
|
|
1343
|
+
* whole lookup — which would take every dust spend this wallet ever made down with it.
|
|
1344
|
+
* @param nullifierTransactions The transactions the lookup matched.
|
|
1345
|
+
* @returns The dust spends among them, in source order.
|
|
1346
|
+
*/
|
|
1347
|
+
const matchedDustSpends = (nullifierTransactions) => require_dist.pipe(nullifierTransactions, require_dist.filterMap$1(({ transaction }) => transaction.__typename === "RegularTransaction" ? require_dist.some(transaction) : require_dist.none()), require_dist.dedupeAdjacentWith((a, b) => a.id === b.id), require_dist.flatMap$2((transaction) => require_dist.filterMap$1(transaction.dustLedgerEvents, (event) => require_dist.pipe(tryReadEvent(event), require_dist.flatMap$3((decoded) => decoded.content.tag === "dustSpendProcessed" ? require_dist.some({
|
|
1348
|
+
transaction,
|
|
1349
|
+
dustSpend: decoded.content
|
|
1350
|
+
}) : require_dist.none())))));
|
|
1351
|
+
const createDustUtxoUpdates = (dustState, spends, secretKey, knownUtxos, pendingDust, generationDtimeUpdates, ledgerParametersCodecs = defaultLedgerParametersCodecs$1) => require_dist.pipe(spends, require_dist.map$3(({ transaction, dustSpend }) => createUtxoUpdatesFromSpend(dustState, secretKey, knownUtxos, pendingDust, generationDtimeUpdates, transaction, dustSpend, ledgerParametersCodecs)), require_dist.all, require_dist.map$2(require_dist.getSomes), require_dist.map$2(require_dist.flatten));
|
|
1352
|
+
const makeSimulatorSyncService = (config) => {
|
|
1353
|
+
return {
|
|
1354
|
+
backgroundRepeat: BackgroundRepeat.Once(),
|
|
1355
|
+
updates: (_state, secretKey) => {
|
|
1356
|
+
let lastSeenBlockNumber;
|
|
1357
|
+
return require_dist.pipe(require_dist.fromEffect(config.simulator.getLatestState()), require_dist.concat(config.simulator.state$), require_dist.filter((state) => {
|
|
1358
|
+
const lastBlock = require_dist.getLastBlock(state);
|
|
1359
|
+
if (lastBlock === void 0) return false;
|
|
1360
|
+
const blockNumber = lastBlock.number;
|
|
1361
|
+
if (lastSeenBlockNumber !== void 0 && blockNumber <= lastSeenBlockNumber) return false;
|
|
1362
|
+
lastSeenBlockNumber = blockNumber;
|
|
1363
|
+
return true;
|
|
1364
|
+
}), require_dist.map((state) => ({
|
|
1365
|
+
update: state,
|
|
1366
|
+
secretKey
|
|
1367
|
+
})));
|
|
1368
|
+
},
|
|
1369
|
+
blockData: () => {
|
|
1370
|
+
return require_dist.gen(function* () {
|
|
1371
|
+
const state = yield* config.simulator.getLatestState();
|
|
1372
|
+
const lastBlock = require_dist.getLastBlock(state);
|
|
1373
|
+
return {
|
|
1374
|
+
hash: lastBlock.hash,
|
|
1375
|
+
height: Number(lastBlock.number),
|
|
1376
|
+
protocolVersion: Number(lastBlock.protocolVersion),
|
|
1377
|
+
ledgerParameters: state.ledger.parameters,
|
|
1378
|
+
timestamp: state.currentTime,
|
|
1379
|
+
zswapEndIndex: 1,
|
|
1380
|
+
dustCommitmentEndIndex: 1,
|
|
1381
|
+
dustGenerationEndIndex: 1,
|
|
1382
|
+
dustCommitmentMerkleTreeRoot: "",
|
|
1383
|
+
dustGenerationMerkleTreeRoot: ""
|
|
1384
|
+
};
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
};
|
|
1388
|
+
};
|
|
1389
|
+
const makeSimulatorSyncCapability = () => {
|
|
1390
|
+
return { applyUpdate: (state, update, activeRange) => {
|
|
1391
|
+
if (require_dist.getLastBlock(update.update) === void 0) return [state, {
|
|
1392
|
+
changes: [],
|
|
1393
|
+
protocolVersion: Number(state.protocolVersion)
|
|
1394
|
+
}];
|
|
1395
|
+
const { applied, observedVersion } = splitAtVersionBoundary(update.update.blocks.filter((block) => block.number >= state.progress.appliedIndex), (block) => Number(block.protocolVersion), activeRange);
|
|
1396
|
+
const events = applied.flatMap((block) => block.transactions.flatMap((tx) => tx.result.events));
|
|
1397
|
+
const lastAppliedBlock = applied.at(-1);
|
|
1398
|
+
const [newState, changes] = applied.length === 0 ? [state, []] : CoreWallet$1.applyEventsWithChanges(state, update.secretKey, events, lastAppliedBlock.timestamp);
|
|
1399
|
+
return [CoreWallet$1.updateProgress(annotateVersion(newState, observedVersion), { appliedIndex: lastAppliedBlock === void 0 ? state.progress.appliedIndex : lastAppliedBlock.number + 1n }), {
|
|
1400
|
+
changes,
|
|
1401
|
+
protocolVersion: lastAppliedBlock === void 0 ? Number(state.protocolVersion) : Number(lastAppliedBlock.protocolVersion)
|
|
1402
|
+
}];
|
|
1403
|
+
} };
|
|
1404
|
+
};
|
|
1405
|
+
//#endregion
|
|
1406
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/RunningV2Variant.js
|
|
1407
|
+
const progress$1 = (state) => {
|
|
1408
|
+
const appliedIndex = state.progress?.appliedIndex ?? 0n;
|
|
1409
|
+
const highestRelevantWalletIndex = state.progress?.highestRelevantWalletIndex ?? 0n;
|
|
1410
|
+
const sourceGap = (state.progress?.highestIndex ?? 0n) - (state.progress?.highestRelevantIndex ?? 0n);
|
|
1411
|
+
const applyGap = highestRelevantWalletIndex - appliedIndex;
|
|
1412
|
+
return [require_dist.ProgressUpdate({
|
|
1413
|
+
sourceGap,
|
|
1414
|
+
applyGap
|
|
1415
|
+
})];
|
|
1416
|
+
};
|
|
1417
|
+
/**
|
|
1418
|
+
* The version signals this variant puts on its state stream.
|
|
1419
|
+
*
|
|
1420
|
+
* @remarks
|
|
1421
|
+
* Two of them, for two different situations. A transition is the ordinary one: the state moved to a version the variant
|
|
1422
|
+
* may or may not own, and the runtime decides. The healing emission covers restore: a snapshot taken between the
|
|
1423
|
+
* moment sync annotated an out-of-range version and the moment the runtime acted on it comes back with a version this
|
|
1424
|
+
* variant does not own and no transition to announce it, so it would sit there forever. Announcing it on the first
|
|
1425
|
+
* observation is what forward-migrates such a snapshot.
|
|
1426
|
+
*/
|
|
1427
|
+
const protocolVersionChange$1 = (previous, current, isInitial, activationRange) => {
|
|
1428
|
+
const transitioned = previous.protocolVersion != current.protocolVersion;
|
|
1429
|
+
const strandedOutsideRange = isInitial && !require_dist.withinRange(current.protocolVersion, activationRange);
|
|
1430
|
+
return transitioned || strandedOutsideRange ? [require_dist.VersionChange({ change: require_dist.Version({ version: require_dist.ProtocolVersion(current.protocolVersion) }) })] : [];
|
|
1431
|
+
};
|
|
1432
|
+
const V2Tag = Symbol("V2");
|
|
1433
|
+
/**
|
|
1434
|
+
* How a failing synchronization pass is retried.
|
|
1435
|
+
*
|
|
1436
|
+
* @remarks
|
|
1437
|
+
* Exported so the delays it actually produces can be asserted. A schedule reads as though its combinators apply to the
|
|
1438
|
+
* delay, and for some of them they do not — which is worth pinning in a test rather than trusting by eye.
|
|
1439
|
+
*/
|
|
1440
|
+
const syncRetrySchedule$1 = require_dist.pipe(require_dist.exponential(require_dist.seconds(1), 2), require_dist.jittered, require_dist.union(require_dist.spaced(require_dist.minutes(2))));
|
|
1441
|
+
var RunningV2Variant = class {
|
|
1442
|
+
__polyTag__ = V2Tag;
|
|
1443
|
+
#scope;
|
|
1444
|
+
#context;
|
|
1445
|
+
#v2Context;
|
|
1446
|
+
#txHistoryPermits = require_dist.makeSemaphore(8).pipe(require_dist.runSync);
|
|
1447
|
+
state;
|
|
1448
|
+
#syncLock;
|
|
1449
|
+
/**
|
|
1450
|
+
* Whether a background synchronization worker is already running.
|
|
1451
|
+
*
|
|
1452
|
+
* @remarks
|
|
1453
|
+
* Distinct from {@link #syncLock}, which is released at the end of every pass and so says nothing about the worker
|
|
1454
|
+
* that runs them. Held for the worker's whole lifetime — polling delays and retries included — and released as it
|
|
1455
|
+
* exits, so a wallet started again while it is already synchronizing keeps the worker it has instead of gaining a
|
|
1456
|
+
* second one that polls alongside it until the wallet stops.
|
|
1457
|
+
*
|
|
1458
|
+
* The guard asks only whether a worker is running, not what it was started with, so a second start is ignored even
|
|
1459
|
+
* when it carries different key material. Starting a running wallet on a second key is not a supported way to
|
|
1460
|
+
* change keys: stop it first. Two workers would be no better — they would apply two keys' updates to one state.
|
|
1461
|
+
*/
|
|
1462
|
+
#backgroundWorkerLock;
|
|
1463
|
+
constructor(scope, context, v2Context) {
|
|
1464
|
+
this.#scope = scope;
|
|
1465
|
+
this.#context = context;
|
|
1466
|
+
this.#v2Context = v2Context;
|
|
1467
|
+
this.#syncLock = require_dist.runSync(require_dist.make$2(false));
|
|
1468
|
+
this.#backgroundWorkerLock = require_dist.runSync(require_dist.make$2(false));
|
|
1469
|
+
this.state = require_dist.fromEffect(context.stateRef.get).pipe(require_dist.flatMap((initialState) => context.stateRef.changes.pipe(require_dist.mapAccum({
|
|
1470
|
+
previous: initialState,
|
|
1471
|
+
isInitial: true
|
|
1472
|
+
}, (seen, current) => [{
|
|
1473
|
+
previous: current,
|
|
1474
|
+
isInitial: false
|
|
1475
|
+
}, [
|
|
1476
|
+
seen.previous,
|
|
1477
|
+
current,
|
|
1478
|
+
seen.isInitial
|
|
1479
|
+
]]))), require_dist.mapConcat(([previous, current, isInitial]) => {
|
|
1480
|
+
return [
|
|
1481
|
+
require_dist.State({ state: current }),
|
|
1482
|
+
...progress$1(current),
|
|
1483
|
+
...protocolVersionChange$1(previous, current, isInitial, context.activationRange)
|
|
1484
|
+
];
|
|
1485
|
+
}));
|
|
1486
|
+
}
|
|
1487
|
+
startSyncInBackground(startAux) {
|
|
1488
|
+
const attempt = this.startSync(startAux).pipe(require_dist.runScoped(require_dist.drain), require_dist.scoped).pipe(require_dist.retry$1(syncRetrySchedule$1));
|
|
1489
|
+
const worker = BackgroundRepeat.$match(this.#v2Context.syncService.backgroundRepeat, {
|
|
1490
|
+
Once: () => attempt,
|
|
1491
|
+
WithDelay: ({ delay }) => require_dist.repeat(attempt, require_dist.spaced(delay)).pipe(require_dist.asVoid)
|
|
1492
|
+
});
|
|
1493
|
+
return require_dist.modify(this.#backgroundWorkerLock, (isRunning) => [!isRunning, true]).pipe(require_dist.flatMap$1((acquired) => acquired ? worker.pipe(require_dist.ensuring$1(require_dist.set(this.#backgroundWorkerLock, false)), require_dist.forkScoped, require_dist.asVoid) : require_dist._void), require_dist.provideService(require_dist.Scope, this.#scope));
|
|
1494
|
+
}
|
|
1495
|
+
sync(startAux) {
|
|
1496
|
+
return this.startSync(startAux).pipe(require_dist.runScoped(require_dist.drain), require_dist.scoped);
|
|
1497
|
+
}
|
|
1498
|
+
startSync(startAux) {
|
|
1499
|
+
return require_dist.pipe(require_dist.modify(this.#syncLock, (isLocked) => [!isLocked, true]), require_dist.fromEffect, require_dist.flatMap((acquired) => {
|
|
1500
|
+
if (!acquired) return require_dist.empty;
|
|
1501
|
+
return require_dist.pipe(require_dist.get(this.#context.stateRef), require_dist.fromEffect, require_dist.flatMap((state) => this.#v2Context.syncService.updates(state, startAux)), require_dist.mapEffect((update) => require_dist.modifyEffect(this.#context.stateRef, (state) => require_dist.try_({
|
|
1502
|
+
try: () => {
|
|
1503
|
+
const [newState, changesResult] = this.#v2Context.syncCapability.applyUpdate(state, update, this.#context.activationRange);
|
|
1504
|
+
return [changesResult, newState];
|
|
1505
|
+
},
|
|
1506
|
+
catch: (err) => new OtherWalletError$1({
|
|
1507
|
+
message: "Error while applying sync update",
|
|
1508
|
+
cause: err
|
|
1509
|
+
})
|
|
1510
|
+
})).pipe(require_dist.flatMap$1(({ changes, protocolVersion }) => changes.length === 0 ? require_dist._void : require_dist.pipe(require_dist.forEach(changes, (change) => require_dist.pipe(this.#txHistoryPermits.withPermits(1)(require_dist.pipe(this.#v2Context.transactionHistoryService.getTransactionDetails(change.source), require_dist.flatMap$1((metadata) => this.#v2Context.transactionHistoryService.put(change, metadata, protocolVersion)))), require_dist.catchAllCause((cause) => require_dist.logError(cause, `Failed to record dust tx-history section for ${change.source}`))), {
|
|
1511
|
+
discard: true,
|
|
1512
|
+
concurrency: 8
|
|
1513
|
+
}), require_dist.forkScoped)), require_dist.provideService(require_dist.Scope, this.#scope))), require_dist.tapError((error$2) => require_dist.error(error$2)), require_dist.ensuring(require_dist.set(this.#syncLock, false)));
|
|
1514
|
+
}));
|
|
1515
|
+
}
|
|
1516
|
+
createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress) {
|
|
1517
|
+
if (nightUtxos.some((utxo) => utxo.type !== require_dist.Token.night)) return require_dist.fail$2(new OtherWalletError$1({ message: "Token of a non-Night type received" }));
|
|
1518
|
+
return require_dist.Do.pipe(require_dist.bind("currentState", () => require_dist.get(this.#context.stateRef)), require_dist.bind("blockData", () => this.#v2Context.syncService.blockData()), require_dist.let_("resolvedTime", ({ blockData }) => currentTime ?? blockData.timestamp), require_dist.let_("utxosWithDustValue", ({ currentState, resolvedTime }) => {
|
|
1519
|
+
return this.#v2Context.coinsAndBalancesCapability.estimateDustGeneration(currentState, nightUtxos, resolvedTime);
|
|
1520
|
+
}), require_dist.flatMap$1(({ utxosWithDustValue, resolvedTime }) => {
|
|
1521
|
+
return this.#v2Context.transactingCapability.createDustGenerationTransaction(resolvedTime, ttl, utxosWithDustValue, nightVerifyingKey, dustReceiverAddress).pipe(require_dist.toEffect);
|
|
1522
|
+
}));
|
|
1523
|
+
}
|
|
1524
|
+
splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration) {
|
|
1525
|
+
if (nightUtxos.some((utxo) => utxo.type !== require_dist.Token.night)) return require_dist.fail$2(new OtherWalletError$1({ message: "Token of a non-Night type received" }));
|
|
1526
|
+
return require_dist.gen(this, function* () {
|
|
1527
|
+
const currentState = yield* require_dist.get(this.#context.stateRef);
|
|
1528
|
+
const utxosWithDustValue = this.#v2Context.coinsAndBalancesCapability.estimateDustGeneration(currentState, nightUtxos, currentTime);
|
|
1529
|
+
return this.#v2Context.transactingCapability.splitNightUtxosForDustRegistration(utxosWithDustValue, isRegistration);
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
1533
|
+
return this.#v2Context.transactingCapability.attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment).pipe(require_dist.toEffect);
|
|
1534
|
+
}
|
|
1535
|
+
addDustGenerationSignature(transaction, signature) {
|
|
1536
|
+
return this.#v2Context.transactingCapability.addDustGenerationSignature(transaction, signature).pipe(require_dist.toEffect);
|
|
1537
|
+
}
|
|
1538
|
+
addDustRegistrationSignature(transaction, signature) {
|
|
1539
|
+
return this.#v2Context.transactingCapability.addDustRegistrationSignature(transaction, signature).pipe(require_dist.toEffect);
|
|
1540
|
+
}
|
|
1541
|
+
calculateFee(transactions) {
|
|
1542
|
+
return require_dist.pipe(this.#v2Context.syncService.blockData(), require_dist.map$2((blockData) => require_dist.pipe(transactions, require_dist.map$3((transaction) => this.#v2Context.transactingCapability.calculateFee(transaction, blockData.ledgerParameters)), require_dist.sumBigInt)));
|
|
1543
|
+
}
|
|
1544
|
+
estimateFee(secretKey, transactions, ttl, currentTime) {
|
|
1545
|
+
return require_dist.pipe(require_dist.all([require_dist.get(this.#context.stateRef), this.#v2Context.syncService.blockData()]), require_dist.flatMap$1(([state, blockData]) => require_dist.pipe(this.#v2Context.transactingCapability.estimateFee(secretKey, state, transactions, ttl, currentTime ?? blockData.timestamp, blockData.ledgerParameters), require_dist.toEffect)));
|
|
1546
|
+
}
|
|
1547
|
+
balanceTransactions(secretKey, transactions, ttl, currentTime) {
|
|
1548
|
+
return require_dist.pipe(this.#v2Context.syncService.blockData(), require_dist.flatMap$1((blockData) => require_dist.pipe(require_dist.modifyEffect(this.#context.stateRef, (state) => this.#v2Context.transactingCapability.balanceTransactions(secretKey, state, transactions, ttl, currentTime ?? blockData.timestamp, blockData.ledgerParameters)), require_dist.map$2((transaction) => ({
|
|
1549
|
+
transaction,
|
|
1550
|
+
blockData
|
|
1551
|
+
})))));
|
|
1552
|
+
}
|
|
1553
|
+
revertTransaction(transaction) {
|
|
1554
|
+
return require_dist.updateEffect(this.#context.stateRef, (state) => {
|
|
1555
|
+
return require_dist.pipe(this.#v2Context.transactingCapability.revertTransaction(state, transaction), require_dist.toEffect);
|
|
1556
|
+
});
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1559
|
+
//#endregion
|
|
1560
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/SingleVariantDustWallet.js
|
|
1561
|
+
/**
|
|
1562
|
+
* A dust wallet composed from a single variant, which answers for the whole protocol timeline.
|
|
1563
|
+
*
|
|
1564
|
+
* @remarks
|
|
1565
|
+
* The building block for a composition the package's default does not ship: a variant builder of the caller's own — a
|
|
1566
|
+
* simulator sync in tests, or the projections-based fast sync, which exists on ledger-v9 only and would defeat its
|
|
1567
|
+
* own purpose behind a V1 variant. Its one variant is registered from the minimum supported version, so it stamps
|
|
1568
|
+
* every transaction at that floor and accepts one of any version; the price is that it cannot cross a protocol
|
|
1569
|
+
* boundary. The wallet that can is `DustWallet`, in `DustWallet.ts`.
|
|
1570
|
+
*/
|
|
1571
|
+
function CustomDustWallet(configuration, builder) {
|
|
1572
|
+
const buildArgs = [configuration];
|
|
1573
|
+
const BaseWallet = require_dist.WalletBuilder.init().withVariant(require_dist.MinSupportedVersion, builder).build(...buildArgs);
|
|
1574
|
+
/** The whole of the protocol timeline: one variant answers for every version this wallet will ever see. */
|
|
1575
|
+
const wholeTimeline = require_dist.epochOf(require_dist.MinSupportedVersion, require_dist.MinSupportedVersion);
|
|
1576
|
+
/** Seals a transaction this wallet built, at the version its one variant answers from. */
|
|
1577
|
+
const seal = (transaction) => require_dist.WalletTransaction.adopt("Unproven", transaction, require_dist.MinSupportedVersion);
|
|
1578
|
+
/** Reads a transaction a caller handed in, which a single-variant wallet accepts at any version. */
|
|
1579
|
+
const carried = (handle) => require_dist.toEffect(require_dist.WalletTransaction.unwrapWithin(handle, wholeTimeline));
|
|
1580
|
+
return class CustomDustWalletImplementation extends BaseWallet {
|
|
1581
|
+
static startWithSeed(seed, dustParameters = _midnightntwrk_ledger_v9.LedgerParameters.initialParameters().dust) {
|
|
1582
|
+
const dustSecretKey = _midnightntwrk_ledger_v9.DustSecretKey.fromSeed(seed);
|
|
1583
|
+
return CustomDustWalletImplementation.startFirst(CustomDustWalletImplementation, CoreWallet$1.initEmpty(dustParameters, dustSecretKey, CustomDustWalletImplementation.configuration.networkId));
|
|
1584
|
+
}
|
|
1585
|
+
static startWithSecretKey(secretKey, dustParameters = _midnightntwrk_ledger_v9.LedgerParameters.initialParameters().dust) {
|
|
1586
|
+
return CustomDustWalletImplementation.startFirst(CustomDustWalletImplementation, CoreWallet$1.initEmpty(dustParameters, secretKey, CustomDustWalletImplementation.configuration.networkId));
|
|
1587
|
+
}
|
|
1588
|
+
static restore(serializedState) {
|
|
1589
|
+
const deserialized = CustomDustWalletImplementation.allVariantsRecord()[V2Tag].variant.deserializeState(serializedState).pipe(require_dist.getOrThrow$1);
|
|
1590
|
+
return CustomDustWalletImplementation.startFirst(CustomDustWalletImplementation, deserialized);
|
|
1591
|
+
}
|
|
1592
|
+
state;
|
|
1593
|
+
/**
|
|
1594
|
+
* The start-aux the wallet was last started with.
|
|
1595
|
+
*
|
|
1596
|
+
* @remarks
|
|
1597
|
+
* Sync needs the dust secret key, and a migration starts a fresh variant whose sync has never been started. The key
|
|
1598
|
+
* cannot come from the state — it is deliberately absent from anything serialized — and it does not exist yet
|
|
1599
|
+
* when the wallet is first constructed, so it is held here, in memory, for the lifetime of the wallet. Cleared by
|
|
1600
|
+
* {@link stop} so a stopped wallet cannot be silently resurrected by a late activation.
|
|
1601
|
+
*/
|
|
1602
|
+
#retainedAux = require_dist.unsafeMake(require_dist.none());
|
|
1603
|
+
/**
|
|
1604
|
+
* Whether the activation watcher has been registered.
|
|
1605
|
+
*
|
|
1606
|
+
* @remarks
|
|
1607
|
+
* Registration is per wallet, not per `start`: watchers accumulate, so registering on every call would restart sync
|
|
1608
|
+
* once per historical `start` on the next activation. Flipped with `getAndSet` so concurrent `start` calls cannot
|
|
1609
|
+
* both observe it unset.
|
|
1610
|
+
*/
|
|
1611
|
+
#watcherRegistered = require_dist.unsafeMake(false);
|
|
1612
|
+
constructor(runtime, scope) {
|
|
1613
|
+
super(runtime, scope);
|
|
1614
|
+
this.state = this.rawState.pipe(rxjs.map((emission) => DustWalletState.fromVariant(CustomDustWalletImplementation.allVariantsRecord()[V2Tag].variant, emission)), rxjs.shareReplay({
|
|
1615
|
+
refCount: true,
|
|
1616
|
+
bufferSize: 1
|
|
1617
|
+
}));
|
|
1618
|
+
}
|
|
1619
|
+
start(secretKey) {
|
|
1620
|
+
return require_dist.gen(this, function* () {
|
|
1621
|
+
yield* require_dist.set(this.#retainedAux, require_dist.some(secretKey));
|
|
1622
|
+
if (!(yield* require_dist.getAndSet(this.#watcherRegistered, true))) yield* this.runtime.onVariantActivation({ [V2Tag]: (v2) => require_dist.get$1(this.#retainedAux).pipe(require_dist.flatMap$1(require_dist.match$1({
|
|
1623
|
+
onNone: () => require_dist._void,
|
|
1624
|
+
onSome: (retained) => v2.startSyncInBackground(retained)
|
|
1625
|
+
}))) });
|
|
1626
|
+
yield* this.runtime.dispatch({ [V2Tag]: (v2) => v2.startSyncInBackground(secretKey) });
|
|
1627
|
+
}).pipe(require_dist.runPromise$1);
|
|
1628
|
+
}
|
|
1629
|
+
async stop() {
|
|
1630
|
+
require_dist.set(this.#retainedAux, require_dist.none()).pipe(require_dist.runSync);
|
|
1631
|
+
await super.stop();
|
|
1632
|
+
}
|
|
1633
|
+
stepSync(secretKey) {
|
|
1634
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => v2.sync(secretKey) }).pipe(require_dist.runPromise$1);
|
|
1635
|
+
}
|
|
1636
|
+
/**
|
|
1637
|
+
* The key material this wallet's one variant uses, from what it was started with.
|
|
1638
|
+
*
|
|
1639
|
+
* @remarks
|
|
1640
|
+
* Fee payment selects dust the wallet owns, so it needs the same secret synchronization does.
|
|
1641
|
+
*/
|
|
1642
|
+
#requireAux() {
|
|
1643
|
+
return require_dist.get$1(this.#retainedAux).pipe(require_dist.flatMap$1(require_dist.match$1({
|
|
1644
|
+
onNone: () => require_dist.fail$2(new require_dist.MissingStartAuxError({
|
|
1645
|
+
message: "This wallet holds no key material: it has not been started, or it has been stopped. Start it before asking it to pay a fee.",
|
|
1646
|
+
variantTag: V2Tag
|
|
1647
|
+
})),
|
|
1648
|
+
onSome: (aux) => require_dist.succeed(aux)
|
|
1649
|
+
})));
|
|
1650
|
+
}
|
|
1651
|
+
async createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress) {
|
|
1652
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => v2.createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress).pipe(require_dist.map$2(seal)) }).pipe(require_dist.runPromise$1);
|
|
1653
|
+
}
|
|
1654
|
+
async splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration) {
|
|
1655
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => v2.splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration) }).pipe(require_dist.runPromise$1);
|
|
1656
|
+
}
|
|
1657
|
+
async attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
1658
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => carried(transaction).pipe(require_dist.flatMap$1((tx) => v2.attachDustRegistration(tx, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment)), require_dist.map$2(seal)) }).pipe(require_dist.runPromise$1);
|
|
1659
|
+
}
|
|
1660
|
+
addDustGenerationSignature(transaction, signature) {
|
|
1661
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => carried(transaction).pipe(require_dist.flatMap$1((tx) => v2.addDustGenerationSignature(tx, signature)), require_dist.map$2(seal)) }).pipe(require_dist.runPromise$1);
|
|
1662
|
+
}
|
|
1663
|
+
addDustRegistrationSignature(transaction, signature) {
|
|
1664
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => carried(transaction).pipe(require_dist.flatMap$1((tx) => v2.addDustRegistrationSignature(tx, signature)), require_dist.map$2(seal)) }).pipe(require_dist.runPromise$1);
|
|
1665
|
+
}
|
|
1666
|
+
calculateFee(transactions) {
|
|
1667
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => require_dist.forEach(transactions, carried).pipe(require_dist.flatMap$1((txs) => v2.calculateFee(txs))) }).pipe(require_dist.runPromise$1);
|
|
1668
|
+
}
|
|
1669
|
+
estimateFee(transactions, ttl, currentTime) {
|
|
1670
|
+
const effectiveTtl = ttl ?? new Date(Date.now() + 3600 * 1e3);
|
|
1671
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => require_dist.all([this.#requireAux(), require_dist.forEach(transactions, carried)]).pipe(require_dist.flatMap$1(([key, txs]) => v2.estimateFee(key, txs, effectiveTtl, currentTime))) }).pipe(require_dist.runPromise$1);
|
|
1672
|
+
}
|
|
1673
|
+
balanceTransactions(transactions, ttl, currentTime) {
|
|
1674
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => require_dist.all([this.#requireAux(), require_dist.forEach(transactions, carried)]).pipe(require_dist.flatMap$1(([key, txs]) => v2.balanceTransactions(key, txs, ttl, currentTime)), require_dist.map$2(({ transaction, blockData }) => ({
|
|
1675
|
+
transaction: seal(transaction),
|
|
1676
|
+
blockData
|
|
1677
|
+
}))) }).pipe(require_dist.runPromise$1);
|
|
1678
|
+
}
|
|
1679
|
+
revertTransaction(transaction) {
|
|
1680
|
+
return this.runtime.dispatch({ [V2Tag]: (v2) => require_dist.match$2(require_dist.WalletTransaction.unwrapWithin(transaction, wholeTimeline), {
|
|
1681
|
+
onLeft: () => require_dist._void,
|
|
1682
|
+
onRight: (tx) => v2.revertTransaction(tx)
|
|
1683
|
+
}) }).pipe(require_dist.runPromise$1);
|
|
1684
|
+
}
|
|
1685
|
+
waitForSyncedState(allowedGap = 0n) {
|
|
1686
|
+
return rxjs.firstValueFrom(this.state.pipe(rxjs.filter((state) => state.state.progress.isCompleteWithin(allowedGap))));
|
|
1687
|
+
}
|
|
1688
|
+
async waitForGeneratedDust(nightUtxos, requiredAmount, clock, opts) {
|
|
1689
|
+
if (nightUtxos.length === 0) throw Error("At least one Night UTXO is required.");
|
|
1690
|
+
if (requiredAmount <= 0n) return;
|
|
1691
|
+
const timeoutMs = opts?.timeoutMs ?? 3e5;
|
|
1692
|
+
await rxjs.firstValueFrom(rxjs.combineLatest([this.state, rxjs.timer(0, 1e3)]).pipe(rxjs.filter(([dustState]) => claimableFeePayment(dustState, nightUtxos, clock.now()) >= requiredAmount), rxjs.timeout({ first: timeoutMs })));
|
|
1693
|
+
}
|
|
1694
|
+
serializeState() {
|
|
1695
|
+
return rxjs.firstValueFrom(this.state).then((state) => state.serialize());
|
|
1696
|
+
}
|
|
1697
|
+
getAddress() {
|
|
1698
|
+
return rxjs.firstValueFrom(this.state).then((state) => state.address);
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
//#endregion
|
|
1703
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/Restore.js
|
|
1704
|
+
/**
|
|
1705
|
+
* Raised when a snapshot declares a protocol version that no registered variant is able to read.
|
|
1706
|
+
*
|
|
1707
|
+
* @remarks
|
|
1708
|
+
* A wallet built for one range of protocol versions cannot invent a reader for a snapshot written outside it, and
|
|
1709
|
+
* guessing — handing the bytes to whichever variant happens to be registered — would decode them with the wrong
|
|
1710
|
+
* ledger. The version is carried on the error so an application can say which one it was.
|
|
1711
|
+
*/
|
|
1712
|
+
var UnsupportedSnapshotVersionError = class extends require_dist.TaggedError("@midnightntwrk/wallet-sdk-dust-wallet/Restore/UnsupportedSnapshotVersionError") {};
|
|
1713
|
+
/**
|
|
1714
|
+
* The envelope the peek reads.
|
|
1715
|
+
*
|
|
1716
|
+
* @remarks
|
|
1717
|
+
* Deliberately the smallest possible description of a snapshot: one optional field, every other ignored. It has to read
|
|
1718
|
+
* snapshots written by _any_ variant, including ones whose full schema this build does not have, so it must not
|
|
1719
|
+
* assert anything it does not need. Everything it cannot make sense of is reported as "no version declared", leaving
|
|
1720
|
+
* the real diagnosis to the deserializer that eventually reads the whole thing.
|
|
1721
|
+
*/
|
|
1722
|
+
const EnvelopeSchema = require_dist.Struct({ protocolVersion: require_dist.optional(require_dist.ProtocolVersionSchema) });
|
|
1723
|
+
/**
|
|
1724
|
+
* Reads the protocol version a serialized dust wallet snapshot declares.
|
|
1725
|
+
*
|
|
1726
|
+
* @param serialized The serialized wallet state.
|
|
1727
|
+
* @returns The declared version, or `Option.none()` when the snapshot declares none or cannot be read at all.
|
|
1728
|
+
*/
|
|
1729
|
+
const peekProtocolVersion = (serialized) => require_dist.decodeUnknownOption(require_dist.parseJson(EnvelopeSchema))(serialized).pipe(require_dist.flatMap$3((envelope) => require_dist.fromNullable(envelope.protocolVersion)));
|
|
1730
|
+
/**
|
|
1731
|
+
* Chooses the variant that should read a serialized dust wallet snapshot.
|
|
1732
|
+
*
|
|
1733
|
+
* @remarks
|
|
1734
|
+
* A snapshot that declares no version predates snapshots declaring one, and can only have been written by the variant
|
|
1735
|
+
* that shipped before the question arose — the head variant. The same fallback covers an envelope this function
|
|
1736
|
+
* cannot read at all: refusing it here would replace the deserializer's precise error with a vaguer one.
|
|
1737
|
+
* @param serialized The serialized wallet state.
|
|
1738
|
+
* @param variantFor Resolves the variant registered for a protocol version.
|
|
1739
|
+
* @param headVariant The variant a snapshot with no declared version is restored into.
|
|
1740
|
+
* @returns The variant to restore with, or {@link UnsupportedSnapshotVersionError} when the declared version is one no
|
|
1741
|
+
* registered variant owns.
|
|
1742
|
+
*/
|
|
1743
|
+
const variantForSnapshot = (serialized, variantFor, headVariant) => require_dist.match$1(peekProtocolVersion(serialized), {
|
|
1744
|
+
onNone: () => require_dist.right(headVariant),
|
|
1745
|
+
onSome: (protocolVersion) => require_dist.fromOption(variantFor(protocolVersion), () => new UnsupportedSnapshotVersionError({
|
|
1746
|
+
message: `No registered variant reads dust wallet snapshots of protocol version ${protocolVersion}.`,
|
|
1747
|
+
protocolVersion
|
|
1748
|
+
}))
|
|
1749
|
+
});
|
|
1750
|
+
//#endregion
|
|
1751
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/CoreWallet.js
|
|
1752
|
+
const PublicKey = { fromSecretKey: (secretKey) => {
|
|
1753
|
+
return { publicKey: secretKey.publicKey };
|
|
1754
|
+
} };
|
|
1755
|
+
const CoreWallet = {
|
|
1756
|
+
init(localState, secretKey, networkId) {
|
|
1757
|
+
return CoreWallet.empty(localState, PublicKey.fromSecretKey(secretKey), networkId);
|
|
1758
|
+
},
|
|
1759
|
+
initEmpty(dustParameters, secretKey, networkId) {
|
|
1760
|
+
return CoreWallet.empty(new _midnight_ntwrk_ledger_v8.DustLocalState(dustParameters), PublicKey.fromSecretKey(secretKey), networkId);
|
|
1761
|
+
},
|
|
1762
|
+
empty(localState, publicKey, networkId) {
|
|
1763
|
+
return {
|
|
1764
|
+
state: localState,
|
|
1765
|
+
publicKey,
|
|
1766
|
+
networkId,
|
|
1767
|
+
pendingDust: [],
|
|
1768
|
+
progress: require_dist.createSyncProgress(),
|
|
1769
|
+
protocolVersion: require_dist.MinSupportedVersion
|
|
1770
|
+
};
|
|
1771
|
+
},
|
|
1772
|
+
restore(localState, publicKey, pendingTokens, syncProgress, protocolVersion, networkId) {
|
|
1773
|
+
return {
|
|
1774
|
+
state: localState,
|
|
1775
|
+
publicKey,
|
|
1776
|
+
networkId,
|
|
1777
|
+
pendingDust: pendingTokens,
|
|
1778
|
+
progress: require_dist.createSyncProgress(syncProgress),
|
|
1779
|
+
protocolVersion: require_dist.ProtocolVersion(protocolVersion)
|
|
1780
|
+
};
|
|
1781
|
+
},
|
|
1782
|
+
withProtocolVersion(wallet, version) {
|
|
1783
|
+
return version > wallet.protocolVersion ? {
|
|
1784
|
+
...wallet,
|
|
1785
|
+
protocolVersion: version
|
|
1786
|
+
} : wallet;
|
|
1787
|
+
},
|
|
1788
|
+
fromPreviousVersion(previous) {
|
|
1789
|
+
return {
|
|
1790
|
+
state: new _midnight_ntwrk_ledger_v8.DustLocalState(previous.dustParameters),
|
|
1791
|
+
publicKey: previous.publicKey,
|
|
1792
|
+
networkId: previous.networkId,
|
|
1793
|
+
pendingDust: [],
|
|
1794
|
+
progress: require_dist.createSyncProgress({
|
|
1795
|
+
...previous.progress,
|
|
1796
|
+
isConnected: false
|
|
1797
|
+
}),
|
|
1798
|
+
protocolVersion: require_dist.ProtocolVersion(previous.protocolVersion)
|
|
1799
|
+
};
|
|
1800
|
+
},
|
|
1801
|
+
applyEventsWithChanges(wallet, secretKey, events, currentTime) {
|
|
1802
|
+
const stateWithChanges = wallet.state.replayEventsWithChanges(secretKey, events);
|
|
1803
|
+
const updatedState = stateWithChanges.state.processTtls(currentTime);
|
|
1804
|
+
const availableNonces = updatedState.utxos.map((utxo) => utxo.nonce);
|
|
1805
|
+
return [{
|
|
1806
|
+
...wallet,
|
|
1807
|
+
state: updatedState,
|
|
1808
|
+
pendingDust: wallet.pendingDust.filter((t) => availableNonces.includes(t.nonce))
|
|
1809
|
+
}, stateWithChanges.changes];
|
|
1810
|
+
},
|
|
1811
|
+
applyFailed(wallet, tx) {
|
|
1812
|
+
const pendingSpendsMap = CoreWallet.pendingDustToMap(wallet.pendingDust);
|
|
1813
|
+
const [updatedState, removedNullifiers] = require_dist.pipe(require_dist.pipe([...tx.intents?.values() ?? []], require_dist.flatMap$2((intent) => {
|
|
1814
|
+
const spendTime = intent.dustActions?.ctime;
|
|
1815
|
+
return (intent.dustActions?.spends ?? []).map((spend) => ({
|
|
1816
|
+
spend,
|
|
1817
|
+
spendTime
|
|
1818
|
+
}));
|
|
1819
|
+
}), require_dist.filterMap$1(({ spend, spendTime }) => require_dist.pipe(require_dist.fromNullable(pendingSpendsMap.get(spend.oldNullifier)), require_dist.map$5(() => ({
|
|
1820
|
+
spend,
|
|
1821
|
+
spendTime
|
|
1822
|
+
}))))), require_dist.reduce([wallet.state, []], ([state, removed], { spend, spendTime }) => [state.processTtls(require_dist.addSeconds(spendTime, wallet.state.params.dustGracePeriodSeconds)), require_dist.append(removed, spend.oldNullifier)]));
|
|
1823
|
+
return {
|
|
1824
|
+
...wallet,
|
|
1825
|
+
state: updatedState,
|
|
1826
|
+
pendingDust: wallet.pendingDust.filter((coin) => !removedNullifiers.includes(coin.nullifier))
|
|
1827
|
+
};
|
|
1828
|
+
},
|
|
1829
|
+
revertTransaction(wallet, tx) {
|
|
1830
|
+
return CoreWallet.applyFailed(wallet, tx);
|
|
1831
|
+
},
|
|
1832
|
+
updateProgress(wallet, { appliedIndex, highestRelevantWalletIndex, highestIndex, highestRelevantIndex, isConnected }) {
|
|
1833
|
+
const updatedProgress = require_dist.createSyncProgress({
|
|
1834
|
+
appliedIndex: appliedIndex ?? wallet.progress.appliedIndex,
|
|
1835
|
+
highestRelevantWalletIndex: highestRelevantWalletIndex ?? wallet.progress.highestRelevantWalletIndex,
|
|
1836
|
+
highestIndex: highestIndex ?? wallet.progress.highestIndex,
|
|
1837
|
+
highestRelevantIndex: highestRelevantIndex ?? wallet.progress.highestRelevantIndex,
|
|
1838
|
+
isConnected: isConnected ?? wallet.progress.isConnected
|
|
1839
|
+
});
|
|
1840
|
+
return {
|
|
1841
|
+
...wallet,
|
|
1842
|
+
progress: updatedProgress
|
|
1843
|
+
};
|
|
1844
|
+
},
|
|
1845
|
+
spendCoins(wallet, secretKey, coins, currentTime) {
|
|
1846
|
+
const [output, newState, newPending] = require_dist.pipe(coins, require_dist.reduce([
|
|
1847
|
+
[],
|
|
1848
|
+
wallet.state,
|
|
1849
|
+
wallet.pendingDust
|
|
1850
|
+
], ([spends, localState, pending], { token: coinToSpend, value: takeFee }) => {
|
|
1851
|
+
const [newState, dustSpend] = localState.spend(secretKey, coinToSpend, takeFee, currentTime);
|
|
1852
|
+
const newPending = [...pending, {
|
|
1853
|
+
...coinToSpend,
|
|
1854
|
+
nullifier: dustSpend.oldNullifier
|
|
1855
|
+
}];
|
|
1856
|
+
return [
|
|
1857
|
+
require_dist.append(spends, dustSpend),
|
|
1858
|
+
newState,
|
|
1859
|
+
newPending
|
|
1860
|
+
];
|
|
1861
|
+
}));
|
|
1862
|
+
return [output, {
|
|
1863
|
+
...wallet,
|
|
1864
|
+
state: newState,
|
|
1865
|
+
pendingDust: newPending
|
|
1866
|
+
}];
|
|
1867
|
+
},
|
|
1868
|
+
pendingDustToMap(coins) {
|
|
1869
|
+
return new Map(coins.map(({ nullifier, ...coins }) => [nullifier, coins]));
|
|
1870
|
+
}
|
|
1871
|
+
};
|
|
1872
|
+
//#endregion
|
|
1873
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/Keys.js
|
|
1874
|
+
const makeDefaultKeysCapability$1 = () => {
|
|
1875
|
+
return {
|
|
1876
|
+
getPublicKey: (state) => {
|
|
1877
|
+
return state.publicKey.publicKey;
|
|
1878
|
+
},
|
|
1879
|
+
getAddress: (state) => {
|
|
1880
|
+
return new require_dist.DustAddress(state.publicKey.publicKey);
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
};
|
|
1884
|
+
//#endregion
|
|
1885
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/Migration.js
|
|
1886
|
+
/**
|
|
1887
|
+
* The migration used when there is no previous wallet at all.
|
|
1888
|
+
*
|
|
1889
|
+
* @remarks
|
|
1890
|
+
* It backs `WalletLike.startEmpty`, which builds a wallet before any key material exists. The resulting state holds no
|
|
1891
|
+
* dust and has a public key derived from a fixed placeholder seed; it is a scaffold to be replaced by a real start,
|
|
1892
|
+
* not a wallet anybody can pay fees with.
|
|
1893
|
+
* @example
|
|
1894
|
+
* ```typescript
|
|
1895
|
+
* const builder = new V1Builder().withDefaults().withMigration(makeEmptyWalletMigration({ networkId, dustParameters }));
|
|
1896
|
+
* ```;
|
|
1897
|
+
*
|
|
1898
|
+
* @param configuration Supplies the network the scaffold state claims to be on, and the dust parameters it uses.
|
|
1899
|
+
* @returns A migration from `null`.
|
|
1900
|
+
*/
|
|
1901
|
+
const makeEmptyWalletMigration$1 = (configuration) => ({ migrate: () => {
|
|
1902
|
+
const seed = require_dist.fromString("0000000000000000000000000000000000000000000000000000000000000001");
|
|
1903
|
+
return require_dist.succeed(CoreWallet.initEmpty(configuration.dustParameters, _midnight_ntwrk_ledger_v8.DustSecretKey.fromSeed(seed), configuration.networkId));
|
|
1904
|
+
} });
|
|
1905
|
+
//#endregion
|
|
1906
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/WalletError.js
|
|
1907
|
+
var OtherWalletError = class extends require_dist.TaggedError("Wallet.Other") {};
|
|
1908
|
+
var SyncWalletError = class extends require_dist.TaggedError("Wallet.Sync") {};
|
|
1909
|
+
var TransactingError = class extends require_dist.TaggedError("Wallet.Transacting") {};
|
|
1910
|
+
var InsufficientFundsError = class extends require_dist.TaggedError("Wallet.InsufficientFunds") {};
|
|
1911
|
+
var TransactionHistoryError = class extends require_dist.TaggedError("Wallet.TransactionHistory") {};
|
|
1912
|
+
/**
|
|
1913
|
+
* A batch of dust ledger events was not in ascending id order: an event arrived at or below the one before it, or at or
|
|
1914
|
+
* below the applied cursor.
|
|
1915
|
+
*
|
|
1916
|
+
* @remarks
|
|
1917
|
+
* Order is all the wallet can check: dust events share one id sequence with zswap and contract events in the indexer,
|
|
1918
|
+
* so gaps in the stream are normal and a skipped event is only ever caught by the ledger's own insertion check. The
|
|
1919
|
+
* whole batch is refused, nothing is applied and the cursor stays, so the running variant retries from the same
|
|
1920
|
+
* place.
|
|
1921
|
+
* @example
|
|
1922
|
+
* ```ts
|
|
1923
|
+
* if (error._tag === 'Wallet.OutOfOrderSyncUpdate') console.warn(`expected above ${error.expected}, got ${error.received}`);
|
|
1924
|
+
* ```
|
|
1925
|
+
*/
|
|
1926
|
+
var OutOfOrderSyncUpdateError = class extends require_dist.TaggedError("Wallet.OutOfOrderSyncUpdate") {};
|
|
1927
|
+
//#endregion
|
|
1928
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/Serialization.js
|
|
1929
|
+
const StateSchema = require_dist.declare((input) => input instanceof _midnight_ntwrk_ledger_v8.DustLocalState).annotations({ identifier: "ledger.DustLocalState" });
|
|
1930
|
+
const Uint8ArraySchema = require_dist.declare((input) => input instanceof Uint8Array).annotations({ identifier: "Uint8Array" });
|
|
1931
|
+
const StateFromUInt8Array = require_dist.asSchema(require_dist.transformOrFail(Uint8ArraySchema, StateSchema, {
|
|
1932
|
+
encode: (state) => {
|
|
1933
|
+
return require_dist.try_({
|
|
1934
|
+
try: () => {
|
|
1935
|
+
return state.serialize();
|
|
1936
|
+
},
|
|
1937
|
+
catch: (err) => {
|
|
1938
|
+
return new require_dist.Unexpected(err, "Could not serialize local state");
|
|
1939
|
+
}
|
|
1940
|
+
});
|
|
1941
|
+
},
|
|
1942
|
+
decode: (bytes) => require_dist.try_({
|
|
1943
|
+
try: () => _midnight_ntwrk_ledger_v8.DustLocalState.deserialize(bytes),
|
|
1944
|
+
catch: (err) => {
|
|
1945
|
+
return new require_dist.Unexpected(err, "Could not deserialize local state");
|
|
1946
|
+
}
|
|
1947
|
+
})
|
|
1948
|
+
}));
|
|
1949
|
+
const HexedState = require_dist.pipe(require_dist.Uint8ArrayFromHex, require_dist.compose(StateFromUInt8Array));
|
|
1950
|
+
const SnapshotSchema = require_dist.Struct({
|
|
1951
|
+
publicKey: require_dist.Struct({ publicKey: require_dist.BigInt$ }),
|
|
1952
|
+
state: HexedState,
|
|
1953
|
+
protocolVersion: require_dist.BigInt$,
|
|
1954
|
+
networkId: require_dist.String$,
|
|
1955
|
+
offset: require_dist.optional(require_dist.BigInt$)
|
|
1956
|
+
});
|
|
1957
|
+
const makeDefaultV1SerializationCapability = () => {
|
|
1958
|
+
return {
|
|
1959
|
+
serialize: (wallet) => {
|
|
1960
|
+
const buildSnapshot = (w) => ({
|
|
1961
|
+
publicKey: w.publicKey,
|
|
1962
|
+
state: w.state,
|
|
1963
|
+
protocolVersion: w.protocolVersion,
|
|
1964
|
+
networkId: w.networkId,
|
|
1965
|
+
offset: w.progress?.appliedIndex
|
|
1966
|
+
});
|
|
1967
|
+
return require_dist.pipe(wallet, buildSnapshot, require_dist.encodeSync(SnapshotSchema), JSON.stringify);
|
|
1968
|
+
},
|
|
1969
|
+
deserialize: (aux, serialized) => {
|
|
1970
|
+
return require_dist.pipe(serialized, require_dist.decodeUnknownEither(require_dist.parseJson(SnapshotSchema)), require_dist.mapLeft((err) => new OtherWalletError({
|
|
1971
|
+
message: "Error while deserializing snapshot",
|
|
1972
|
+
cause: err
|
|
1973
|
+
})), require_dist.flatMap$4((snapshot) => require_dist.try_$1({
|
|
1974
|
+
try: () => CoreWallet.restore(snapshot.state, snapshot.publicKey, [], {
|
|
1975
|
+
appliedIndex: snapshot.offset ?? 0n,
|
|
1976
|
+
highestRelevantWalletIndex: 0n,
|
|
1977
|
+
highestIndex: 0n,
|
|
1978
|
+
highestRelevantIndex: 0n
|
|
1979
|
+
}, snapshot.protocolVersion, snapshot.networkId),
|
|
1980
|
+
catch: (err) => new OtherWalletError({
|
|
1981
|
+
message: "Error while restoring core wallet",
|
|
1982
|
+
cause: err
|
|
1983
|
+
})
|
|
1984
|
+
})));
|
|
1985
|
+
}
|
|
1986
|
+
};
|
|
1987
|
+
};
|
|
1988
|
+
//#endregion
|
|
1989
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/Sync.js
|
|
1990
|
+
/**
|
|
1991
|
+
* Constructors and matchers for {@link BackgroundRepeat}.
|
|
1992
|
+
*
|
|
1993
|
+
* @example
|
|
1994
|
+
* ```ts
|
|
1995
|
+
* const service: SyncService<CoreWallet, DustSecretKey, WalletSyncUpdate> = {
|
|
1996
|
+
* backgroundRepeat: BackgroundRepeat.Once(),
|
|
1997
|
+
* updates: (state, secretKey) => subscribe(state, secretKey),
|
|
1998
|
+
* blockData: () => latestBlock(),
|
|
1999
|
+
* };
|
|
2000
|
+
* ```;
|
|
2001
|
+
*/
|
|
2002
|
+
const BackgroundRepeat$1 = require_dist.taggedEnum();
|
|
2003
|
+
/**
|
|
2004
|
+
* The ledger parameters codecs this variant reads blocks with, unless it is told otherwise.
|
|
2005
|
+
*
|
|
2006
|
+
* @remarks
|
|
2007
|
+
* Open-ended from the minimum supported version, so a wallet whose variant has not been given a narrower range keeps
|
|
2008
|
+
* reading every block exactly as it did before this became routable. A two-variant dust wallet replaces this with a
|
|
2009
|
+
* registry bounded by the range its variant is active over, and then a block from the other side of the boundary is
|
|
2010
|
+
* refused by name instead of being deserialized.
|
|
2011
|
+
*/
|
|
2012
|
+
const defaultLedgerParametersCodecs = require_dist.getOrThrow$1(require_dist.makeCodecs([{
|
|
2013
|
+
sinceVersion: require_dist.MinSupportedVersion,
|
|
2014
|
+
codec: require_dist.fromDeserializer((bytes) => _midnight_ntwrk_ledger_v8.LedgerParameters.deserialize(bytes))
|
|
2015
|
+
}]));
|
|
2016
|
+
/**
|
|
2017
|
+
* Splits a batch of version-tagged items at the end of a variant's activation range.
|
|
2018
|
+
*
|
|
2019
|
+
* @remarks
|
|
2020
|
+
* The split is positional, not a filter: everything from the first out-of-range item onwards is deferred, even if a
|
|
2021
|
+
* later item reports an in-range version again. A batch is a contiguous slice of one timeline, so applying past a
|
|
2022
|
+
* boundary and then resuming behind it would leave a hole no cursor can describe.
|
|
2023
|
+
*
|
|
2024
|
+
* An item whose version is `undefined` is treated as in-range and contributes no annotation: an absent value means "the
|
|
2025
|
+
* indexer did not say", which must keep the un-versioned behaviour exactly, rather than being read as version zero
|
|
2026
|
+
* and dragging the recorded version down.
|
|
2027
|
+
*
|
|
2028
|
+
* This is the one place the boundary rule lives; the indexer capability (per event) and the simulator capability (per
|
|
2029
|
+
* block) both go through it, so they cannot drift apart.
|
|
2030
|
+
* @param items The batch, in source order.
|
|
2031
|
+
* @param versionOf Reads the protocol version an item was reported at, or `undefined` if it carries none.
|
|
2032
|
+
* @param activeRange The variant's half-open activation range.
|
|
2033
|
+
* @returns The applied/deferred split and the version to record.
|
|
2034
|
+
*/
|
|
2035
|
+
const splitAtVersionBoundary$1 = (items, versionOf, activeRange) => {
|
|
2036
|
+
const [, end] = activeRange;
|
|
2037
|
+
const boundary = items.findIndex((item) => {
|
|
2038
|
+
const version = versionOf(item);
|
|
2039
|
+
return version !== void 0 && BigInt(version) >= end;
|
|
2040
|
+
});
|
|
2041
|
+
const [applied, deferred] = boundary < 0 ? [items, []] : [items.slice(0, boundary), items.slice(boundary)];
|
|
2042
|
+
const signalling = deferred.at(0) ?? [...applied].reverse().find((item) => versionOf(item) !== void 0);
|
|
2043
|
+
const signalledVersion = signalling === void 0 ? void 0 : versionOf(signalling);
|
|
2044
|
+
return {
|
|
2045
|
+
applied,
|
|
2046
|
+
deferred,
|
|
2047
|
+
observedVersion: signalledVersion === void 0 ? require_dist.none() : require_dist.some(require_dist.ProtocolVersion(BigInt(signalledVersion)))
|
|
2048
|
+
};
|
|
2049
|
+
};
|
|
2050
|
+
/** Records a batch's observed protocol version on the state, monotonically. A batch that observed none is a no-op. */
|
|
2051
|
+
const annotateVersion$1 = (state, observedVersion) => require_dist.match$1(observedVersion, {
|
|
2052
|
+
onNone: () => state,
|
|
2053
|
+
onSome: (version) => CoreWallet.withProtocolVersion(state, version)
|
|
2054
|
+
});
|
|
2055
|
+
const LedgerEventSchema = require_dist.declare((input) => input instanceof _midnight_ntwrk_ledger_v8.Event).annotations({ identifier: "ledger.Event" });
|
|
2056
|
+
const LedgerEventFromUInt8Array = require_dist.asSchema(require_dist.transformOrFail(Uint8ArraySchema, LedgerEventSchema, {
|
|
2057
|
+
encode: (e) => require_dist.try_({
|
|
2058
|
+
try: () => e.serialize(),
|
|
2059
|
+
catch: (err) => new require_dist.Unexpected(err, "Could not serialize Ledger Event")
|
|
2060
|
+
}),
|
|
2061
|
+
decode: (bytes) => require_dist.try_({
|
|
2062
|
+
try: () => _midnight_ntwrk_ledger_v8.Event.deserialize(bytes),
|
|
2063
|
+
catch: (err) => new require_dist.Unexpected(err, "Could not deserialize Ledger Event")
|
|
2064
|
+
})
|
|
2065
|
+
}));
|
|
2066
|
+
const HexedEvent = require_dist.pipe(require_dist.Uint8ArrayFromHex, require_dist.compose(LedgerEventFromUInt8Array));
|
|
2067
|
+
const SyncEventsUpdateSchema = require_dist.Struct({
|
|
2068
|
+
id: require_dist.Number$,
|
|
2069
|
+
raw: require_dist.String$,
|
|
2070
|
+
maxId: require_dist.Number$,
|
|
2071
|
+
protocolVersion: require_dist.optional(require_dist.Number$)
|
|
2072
|
+
});
|
|
2073
|
+
/**
|
|
2074
|
+
* Reads an event this variant is going to apply.
|
|
2075
|
+
*
|
|
2076
|
+
* @remarks
|
|
2077
|
+
* The counterpart of {@link SyncEventsUpdateSchema} carrying its event encoded: a capability calls this on the batch
|
|
2078
|
+
* prefix it owns, and never on what it defers. Failure here is a genuine one — an event this variant claimed and
|
|
2079
|
+
* cannot read — and is raised rather than returned, because `SyncCapability.applyUpdate` is total in its own domain
|
|
2080
|
+
* and the variant already turns a throw from it into a typed synchronization error.
|
|
2081
|
+
* @param event The event-carrying item to read.
|
|
2082
|
+
* @returns The event it carries.
|
|
2083
|
+
* @throws ParseError if the bytes are not an event this ledger version can deserialize.
|
|
2084
|
+
*/
|
|
2085
|
+
const readEvent = (event) => require_dist.decodeSync(HexedEvent)(event.raw);
|
|
2086
|
+
const VersionSignalSyncUpdate = { create: (version, highestEventId) => {
|
|
2087
|
+
return {
|
|
2088
|
+
_tag: "VersionSignal",
|
|
2089
|
+
version,
|
|
2090
|
+
highestEventId
|
|
2091
|
+
};
|
|
2092
|
+
} };
|
|
2093
|
+
const WalletSyncUpdate = { create: (updates, secretKey, timestamp) => {
|
|
2094
|
+
return {
|
|
2095
|
+
_tag: "Events",
|
|
2096
|
+
updates,
|
|
2097
|
+
secretKey,
|
|
2098
|
+
timestamp
|
|
2099
|
+
};
|
|
2100
|
+
} };
|
|
2101
|
+
/** How often the chain is asked its version when the configuration does not say. */
|
|
2102
|
+
const DEFAULT_VERSION_WATCH_INTERVAL_MS = 3e4;
|
|
2103
|
+
/**
|
|
2104
|
+
* How long one event-id probe is given to produce its single answer.
|
|
2105
|
+
*
|
|
2106
|
+
* @remarks
|
|
2107
|
+
* Both a stall guard and, on a chain with no dust history at all, the ordinary way the tick ends. A wallet with a
|
|
2108
|
+
* cursor subscribes at an event that provably exists, so there the answer arrives at once or the transport is broken;
|
|
2109
|
+
* a wallet on a chain that has never produced a dust event subscribes to a timeline the indexer will keep open and
|
|
2110
|
+
* never write to. Without a bound, either would leave the poll loop parked on a tick that never completes and the
|
|
2111
|
+
* wallet would stop asking altogether. A bound turns both into a skipped tick.
|
|
2112
|
+
*/
|
|
2113
|
+
const EVENT_TIP_PROBE_TIMEOUT = require_dist.seconds(10);
|
|
2114
|
+
/**
|
|
2115
|
+
* Asks the source how far its dust event timeline goes.
|
|
2116
|
+
*
|
|
2117
|
+
* @remarks
|
|
2118
|
+
* Over the event subscription rather than a query, because the schema has no query that reaches a dust ledger event:
|
|
2119
|
+
* `block`/`transactions` reach one only through a block that happens to contain dust events, which on a quiet chain
|
|
2120
|
+
* is precisely the block that does not. `maxId` is a property of the whole dust timeline — the indexer computes it as
|
|
2121
|
+
* the maximum id within the dust grouping — so any single event answers it: the first one delivered is taken and the
|
|
2122
|
+
* subscription closed.
|
|
2123
|
+
*
|
|
2124
|
+
* The cursor is the wallet's own. The event it last applied provably exists, so the source answers immediately and has
|
|
2125
|
+
* the least backfill to abandon; a wallet that has applied nothing asks from the start, where the first event is —
|
|
2126
|
+
* or, on a chain with no dust event at all, where nothing is, and the tick times out into silence.
|
|
2127
|
+
* @param config The sync configuration, carrying the keep-alive the source's subscriptions use.
|
|
2128
|
+
* @param resumeFrom The wallet's cursor; below zero means "from the very start".
|
|
2129
|
+
* @returns The highest dust event id, or nothing if the source did not answer.
|
|
2130
|
+
*/
|
|
2131
|
+
const highestEventId = (config, resumeFrom) => require_dist.pipe(require_dist.DustLedgerEventTip.run({ id: resumeFrom < 0n ? null : Number(resumeFrom) }), require_dist.runHead, require_dist.map$2(require_dist.map$5((answer) => answer.dustLedgerEvents.maxId)), require_dist.scoped, require_dist.timeout(EVENT_TIP_PROBE_TIMEOUT));
|
|
2132
|
+
/**
|
|
2133
|
+
* One check of the chain's protocol version, gated on the wallet being caught up on the source's dust event ids.
|
|
2134
|
+
*
|
|
2135
|
+
* @remarks
|
|
2136
|
+
* The order of the two questions is load-bearing. The tip is read **first**: a tip reported at a version means the
|
|
2137
|
+
* source has indexed through the block that carries it, so every event below it is already counted in the `maxId`
|
|
2138
|
+
* read afterwards. Asked the other way round, an event indexed between the two answers could be one of the version
|
|
2139
|
+
* that preceded the tip — unread, uncounted, and exactly what the gate exists to catch.
|
|
2140
|
+
*
|
|
2141
|
+
* The one short-circuit is an answer rather than a shortcut: a tip at or below the version the wallet already held is a
|
|
2142
|
+
* signal that could only be a no-op, so no probe is opened and nothing is emitted — which is what keeps a settled
|
|
2143
|
+
* wallet from polling a subscription for the rest of its life. There is deliberately no second short-circuit for a
|
|
2144
|
+
* chain that provably holds no dust event, because no such proof is available from the tip; see
|
|
2145
|
+
* {@link VersionSignalSyncUpdate}.
|
|
2146
|
+
*
|
|
2147
|
+
* Everything else is swallowed. A tick that fails says nothing about the chain, so it must neither reach the state nor
|
|
2148
|
+
* take the sync stream down with it; the next tick is the retry, and costs nothing to wait for.
|
|
2149
|
+
* @param config The sync configuration, for the indexer to ask.
|
|
2150
|
+
* @param resumeFrom The wallet's cursor, for the probe.
|
|
2151
|
+
* @param knownVersion The version the wallet already held when this stream opened — a lower bound on what it holds now.
|
|
2152
|
+
* @returns The signal, or nothing when there is nothing to say or nobody said it.
|
|
2153
|
+
*/
|
|
2154
|
+
const readVersionSignal = (config, resumeFrom, knownVersion) => require_dist.pipe(require_dist.BlockHash.run({ offset: null }), require_dist.provide(require_dist.layer$1({ url: config.indexerClientConnection.indexerHttpUrl })), require_dist.scoped, require_dist.flatMap$1((answer) => require_dist.match$1(require_dist.fromNullable(answer.block), {
|
|
2155
|
+
onNone: () => require_dist.succeedNone,
|
|
2156
|
+
onSome: (tip) => BigInt(tip.protocolVersion) <= knownVersion ? require_dist.succeedNone : require_dist.pipe(highestEventId(config, resumeFrom), require_dist.map$2(require_dist.map$5((maxId) => VersionSignalSyncUpdate.create(tip.protocolVersion, maxId))))
|
|
2157
|
+
})), require_dist.catchAll(() => require_dist.succeedNone));
|
|
2158
|
+
/**
|
|
2159
|
+
* The chain's version, re-asked on a timer for as long as sync runs.
|
|
2160
|
+
*
|
|
2161
|
+
* @remarks
|
|
2162
|
+
* Deliberately silent about ticks that say nothing: a tick that finds the chain where the wallet left it, or that
|
|
2163
|
+
* cannot reach the chain at all, emits no element rather than an empty one, so nothing downstream has to know that
|
|
2164
|
+
* polling is how the answer was arrived at.
|
|
2165
|
+
* @param config The sync configuration, carrying the interval.
|
|
2166
|
+
* @param resumeFrom The wallet's cursor, for the probe.
|
|
2167
|
+
* @param knownVersion The version the wallet held when this stream opened.
|
|
2168
|
+
* @returns The signals, or an empty stream when watching is turned off.
|
|
2169
|
+
*/
|
|
2170
|
+
const versionWatch = (config, resumeFrom, knownVersion) => {
|
|
2171
|
+
const intervalMs = config.versionWatch?.intervalMs ?? DEFAULT_VERSION_WATCH_INTERVAL_MS;
|
|
2172
|
+
return intervalMs <= 0 ? require_dist.empty : require_dist.pipe(require_dist.fromSchedule(require_dist.spaced(require_dist.millis(intervalMs))), require_dist.mapEffect(() => readVersionSignal(config, resumeFrom, knownVersion)), require_dist.filterMap(require_dist.identity));
|
|
2173
|
+
};
|
|
2174
|
+
const makeDefaultSyncService$1 = (config) => {
|
|
2175
|
+
const indexerSyncService = makeIndexerSyncService$1(config);
|
|
2176
|
+
return {
|
|
2177
|
+
backgroundRepeat: BackgroundRepeat$1.Once(),
|
|
2178
|
+
updates: (state, secretKey) => {
|
|
2179
|
+
const batchSize = config.batchUpdates?.size ?? 10;
|
|
2180
|
+
const batchTimeout = require_dist.millis(config.batchUpdates?.timeout ?? 1);
|
|
2181
|
+
const batchSpacing = config.batchUpdates?.spacing ?? 4;
|
|
2182
|
+
const timeline = require_dist.pipe(indexerSyncService.subscribeWallet(state), require_dist.groupedWithin(batchSize, batchTimeout), require_dist.map(require_dist.toArray), require_dist.map((data) => WalletSyncUpdate.create(data, secretKey, /* @__PURE__ */ new Date())), batchSpacing > 0 ? require_dist.schedule(require_dist.spaced(require_dist.millis(batchSpacing))) : (eventsStream) => eventsStream);
|
|
2183
|
+
const resumeFrom = state.progress.appliedIndex - 1n;
|
|
2184
|
+
return require_dist.pipe(require_dist.merge(timeline, versionWatch(config, resumeFrom, state.protocolVersion), { haltStrategy: "left" }), require_dist.provideSomeLayer(indexerSyncService.connectionLayer()));
|
|
2185
|
+
},
|
|
2186
|
+
blockData: () => {
|
|
2187
|
+
return require_dist.gen(function* () {
|
|
2188
|
+
return (yield* (yield* require_dist.BlockHash)({ offset: null })).block;
|
|
2189
|
+
}).pipe(require_dist.provide(indexerSyncService.queryClient()), require_dist.scoped, require_dist.catchAll((err) => require_dist.fail$2(new OtherWalletError({
|
|
2190
|
+
message: `Encountered unexpected error: ${err.message}`,
|
|
2191
|
+
cause: err
|
|
2192
|
+
}))), require_dist.flatMap$1((blockData) => {
|
|
2193
|
+
if (!blockData) return require_dist.fail$2(new OtherWalletError({ message: "Unable to fetch block data" }));
|
|
2194
|
+
return require_dist.pipe(require_dist.decode(config.ledgerParametersCodecs ?? defaultLedgerParametersCodecs, require_dist.ProtocolVersion(BigInt(blockData.protocolVersion)), blockData.ledgerParameters), require_dist.map$6((ledgerParameters) => ({
|
|
2195
|
+
hash: blockData.hash,
|
|
2196
|
+
height: blockData.height,
|
|
2197
|
+
protocolVersion: blockData.protocolVersion,
|
|
2198
|
+
ledgerParameters,
|
|
2199
|
+
timestamp: new Date(blockData.timestamp)
|
|
2200
|
+
})), require_dist.mapLeft((error) => new SyncWalletError({
|
|
2201
|
+
message: error.message,
|
|
2202
|
+
cause: error
|
|
2203
|
+
})), require_dist.toEffect);
|
|
2204
|
+
}));
|
|
2205
|
+
}
|
|
2206
|
+
};
|
|
2207
|
+
};
|
|
2208
|
+
const makeIndexerSyncService$1 = (config) => {
|
|
2209
|
+
return {
|
|
2210
|
+
queryClient() {
|
|
2211
|
+
return require_dist.pipe(require_dist.layer$1({ url: config.indexerClientConnection.indexerHttpUrl }), require_dist.mapError$1((error) => new OtherWalletError(error)));
|
|
2212
|
+
},
|
|
2213
|
+
connectionLayer() {
|
|
2214
|
+
const { indexerClientConnection } = config;
|
|
2215
|
+
return require_dist.createWebSocketUrl(indexerClientConnection.indexerHttpUrl, indexerClientConnection.indexerWsUrl).pipe(require_dist.flatMap$4((url) => require_dist.make(url)), require_dist.match$2({
|
|
2216
|
+
onLeft: (error) => require_dist.fail$1(error),
|
|
2217
|
+
onRight: (url) => require_dist.layer({
|
|
2218
|
+
url,
|
|
2219
|
+
keepAlive: indexerClientConnection.keepAlive
|
|
2220
|
+
})
|
|
2221
|
+
}), require_dist.mapError$1((e) => new SyncWalletError({
|
|
2222
|
+
message: "Failed to obtain correct indexer URLs",
|
|
2223
|
+
cause: e
|
|
2224
|
+
})));
|
|
2225
|
+
},
|
|
2226
|
+
subscribeWallet(state) {
|
|
2227
|
+
const { appliedIndex } = state.progress;
|
|
2228
|
+
const bufferSize = config.indexerClientConnection.bufferSize ?? 1e4;
|
|
2229
|
+
const resumeThreshold = config.indexerClientConnection.resumeThreshold ?? 100;
|
|
2230
|
+
const resumeFrom = appliedIndex - 1n;
|
|
2231
|
+
return require_dist.pipe(require_dist.DustLedgerEvents.runWithBackpressure({
|
|
2232
|
+
bufferSize,
|
|
2233
|
+
resumeThreshold,
|
|
2234
|
+
from: resumeFrom,
|
|
2235
|
+
variables: (cursor) => ({ id: cursor < 0n ? null : Number(cursor) }),
|
|
2236
|
+
key: (r) => BigInt(r.dustLedgerEvents.id)
|
|
2237
|
+
}), require_dist.mapEffect((subscription) => require_dist.pipe(require_dist.decodeUnknownEither(SyncEventsUpdateSchema)(subscription.dustLedgerEvents), require_dist.mapLeft((err) => new SyncWalletError(err)), require_dist.toEffect)), require_dist.mapError((error) => new SyncWalletError(error)));
|
|
2238
|
+
}
|
|
2239
|
+
};
|
|
2240
|
+
};
|
|
2241
|
+
/** The result of an update that observed nothing of the chain. */
|
|
2242
|
+
const noChanges = (state) => ({
|
|
2243
|
+
changes: [],
|
|
2244
|
+
protocolVersion: Number(state.protocolVersion)
|
|
2245
|
+
});
|
|
2246
|
+
/**
|
|
2247
|
+
* Folds what the chain said about its own version into the wallet state.
|
|
2248
|
+
*
|
|
2249
|
+
* @remarks
|
|
2250
|
+
* The same recording the event path makes through {@link annotateVersion}, and nothing else: no cursor moves, no dust
|
|
2251
|
+
* changes hands, no tree grows. A signal is an observation about the chain, not a piece of it.
|
|
2252
|
+
*
|
|
2253
|
+
* One situation makes the observation unsafe to record, and it leaves the state exactly as it was: unread events below
|
|
2254
|
+
* the source's tip mean the hand-over would park the cursor in front of history the next variant cannot read — and
|
|
2255
|
+
* those events carry the version themselves, so nothing is lost by waiting for them. That is not an error: the next
|
|
2256
|
+
* tick asks again.
|
|
2257
|
+
*
|
|
2258
|
+
* A version at or below the one already recorded needs no guard of its own — {@link annotateVersion} never goes
|
|
2259
|
+
* backwards — so a source briefly answering from a lagging replica cannot drag a wallet back over a boundary.
|
|
2260
|
+
* @param state The wallet to record on.
|
|
2261
|
+
* @param update What the chain said, and how far its dust event timeline goes.
|
|
2262
|
+
* @returns The wallet, annotated or untouched, and an empty result.
|
|
2263
|
+
*/
|
|
2264
|
+
const applyVersionSignal = (state, update) => [BigInt(update.highestEventId) > state.progress.appliedIndex ? state : annotateVersion$1(state, require_dist.some(require_dist.ProtocolVersion(BigInt(update.version)))), noChanges(state)];
|
|
2265
|
+
/**
|
|
2266
|
+
* Checks that freshly delivered events arrive in strictly ascending id order.
|
|
2267
|
+
*
|
|
2268
|
+
* @remarks
|
|
2269
|
+
* Order is all that can be checked, never contiguity: dust events share one id sequence with zswap and contract events
|
|
2270
|
+
* in the indexer, so gaps in a dust stream are normal. A skipped commitment-inserting event is caught by the ledger's
|
|
2271
|
+
* own insertion check instead. An empty batch is trivially ordered.
|
|
2272
|
+
* @param fresh The events left after the cursor filter, in source order.
|
|
2273
|
+
* @param appliedIndex The highest event id already applied; the first fresh id must exceed it.
|
|
2274
|
+
* @returns The batch unchanged, or the first id that fails to exceed its predecessor as an
|
|
2275
|
+
* {@link OutOfOrderSyncUpdateError}.
|
|
2276
|
+
*/
|
|
2277
|
+
const expectAscending = (fresh, appliedIndex) => require_dist.pipe(require_dist.zipWith(fresh, require_dist.prepend(require_dist.map$3(fresh, (item) => BigInt(item.id)), appliedIndex), (item, previous) => ({
|
|
2278
|
+
item,
|
|
2279
|
+
previous
|
|
2280
|
+
})), require_dist.findFirst(({ item, previous }) => BigInt(item.id) <= previous), require_dist.match$1({
|
|
2281
|
+
onNone: () => require_dist.right(fresh),
|
|
2282
|
+
onSome: ({ item, previous }) => require_dist.left(new OutOfOrderSyncUpdateError({
|
|
2283
|
+
message: `Dust event ${item.id} delivered at or below its predecessor ${previous}; batch refused, applied index stays at ${appliedIndex}`,
|
|
2284
|
+
expected: previous,
|
|
2285
|
+
received: BigInt(item.id)
|
|
2286
|
+
}))
|
|
2287
|
+
}));
|
|
2288
|
+
const makeDefaultSyncCapability$1 = () => {
|
|
2289
|
+
return { applyUpdate(state, wrappedUpdate, activeRange) {
|
|
2290
|
+
if (wrappedUpdate._tag === "VersionSignal") return applyVersionSignal(state, wrappedUpdate);
|
|
2291
|
+
const { updates, secretKey } = wrappedUpdate;
|
|
2292
|
+
if (updates.length === 0) return [state, {
|
|
2293
|
+
changes: [],
|
|
2294
|
+
protocolVersion: Number(state.protocolVersion)
|
|
2295
|
+
}];
|
|
2296
|
+
const appliedIndex = state.progress.appliedIndex;
|
|
2297
|
+
const freshUpdates = updates.filter((u) => BigInt(u.id) > appliedIndex);
|
|
2298
|
+
const highestRelevantWalletIndex = BigInt(updates.at(-1).maxId);
|
|
2299
|
+
const { applied, observedVersion } = splitAtVersionBoundary$1(require_dist.getOrThrowWith(expectAscending(freshUpdates, appliedIndex), require_dist.identity), (update) => update.protocolVersion, activeRange);
|
|
2300
|
+
const [newState, changes] = applied.length === 0 ? [state, []] : CoreWallet.applyEventsWithChanges(state, secretKey, applied.map(readEvent), wrappedUpdate.timestamp);
|
|
2301
|
+
return [CoreWallet.updateProgress(annotateVersion$1(newState, observedVersion), {
|
|
2302
|
+
appliedIndex: applied.length === 0 ? appliedIndex : BigInt(applied.at(-1).id),
|
|
2303
|
+
highestRelevantWalletIndex,
|
|
2304
|
+
isConnected: true
|
|
2305
|
+
}), {
|
|
2306
|
+
changes,
|
|
2307
|
+
protocolVersion: [...applied].reverse().find((u) => u.protocolVersion !== void 0)?.protocolVersion ?? Number(state.protocolVersion)
|
|
2308
|
+
}];
|
|
2309
|
+
} };
|
|
2310
|
+
};
|
|
2311
|
+
//#endregion
|
|
2312
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/Utils.js
|
|
2313
|
+
const SignatureMarker = {
|
|
2314
|
+
signature: "signature",
|
|
2315
|
+
signatureErased: "signature-erased"
|
|
2316
|
+
};
|
|
2317
|
+
const ProofMarker = {
|
|
2318
|
+
proof: "proof",
|
|
2319
|
+
preProof: "pre-proof",
|
|
2320
|
+
noProof: "no-proof"
|
|
2321
|
+
};
|
|
2322
|
+
const BindingMarker = {
|
|
2323
|
+
binding: "binding",
|
|
2324
|
+
preBinding: "pre-binding",
|
|
2325
|
+
noBinding: "no-binding"
|
|
2326
|
+
};
|
|
2327
|
+
//#endregion
|
|
2328
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/Transacting.js
|
|
2329
|
+
const makeDefaultTransactingCapability$1 = (config, getContext) => {
|
|
2330
|
+
return new TransactingCapabilityImplementation$1(config.networkId, config.costParameters, () => getContext().coinSelection, () => getContext().coinsAndBalancesCapability, () => getContext().keysCapability);
|
|
2331
|
+
};
|
|
2332
|
+
/**
|
|
2333
|
+
* Distributes the fee across multiple inputs, draining smaller inputs first when the fee exceeds any single input's
|
|
2334
|
+
* value. Finds the next available intent segment id in a transaction.
|
|
2335
|
+
*
|
|
2336
|
+
* Fallible intent segments occupy the range `[1, 65535]`; segment `0` is reserved for the guaranteed section and is
|
|
2337
|
+
* never returned.
|
|
2338
|
+
*
|
|
2339
|
+
* @param transaction - Transaction whose intent map is inspected.
|
|
2340
|
+
* @returns `Some(segmentId)` with the lowest unused id, or `None` if all 65535 fallible segments are taken.
|
|
2341
|
+
*/
|
|
2342
|
+
const findAvailableSegmentId$1 = (transaction) => {
|
|
2343
|
+
const used = new Set(transaction.intents?.keys() ?? []);
|
|
2344
|
+
return require_dist.pipe(require_dist.range(1, 65535), require_dist.findFirst$1((segmentId) => !used.has(segmentId)));
|
|
2345
|
+
};
|
|
2346
|
+
/**
|
|
2347
|
+
* Distributes the fee across multiple inputs, draining smaller inputs first when the fee exceeds any single input's
|
|
2348
|
+
* value.
|
|
2349
|
+
*/
|
|
2350
|
+
const distributeFeeAcrossInputs$1 = (inputs, fee) => inputs.reduce(({ result, remaining }, input) => {
|
|
2351
|
+
const deduction = remaining >= input.value ? input.value : remaining;
|
|
2352
|
+
return {
|
|
2353
|
+
result: [...result, {
|
|
2354
|
+
...input,
|
|
2355
|
+
value: deduction
|
|
2356
|
+
}],
|
|
2357
|
+
remaining: remaining - deduction
|
|
2358
|
+
};
|
|
2359
|
+
}, {
|
|
2360
|
+
result: [],
|
|
2361
|
+
remaining: fee
|
|
2362
|
+
}).result;
|
|
2363
|
+
var TransactingCapabilityImplementation$1 = class TransactingCapabilityImplementation$1 {
|
|
2364
|
+
networkId;
|
|
2365
|
+
costParams;
|
|
2366
|
+
getCoinSelection;
|
|
2367
|
+
getCoins;
|
|
2368
|
+
getKeys;
|
|
2369
|
+
constructor(networkId, costParams, getCoinSelection, getCoins, getKeys) {
|
|
2370
|
+
this.getCoins = getCoins;
|
|
2371
|
+
this.networkId = networkId;
|
|
2372
|
+
this.costParams = costParams;
|
|
2373
|
+
this.getCoinSelection = getCoinSelection;
|
|
2374
|
+
this.getKeys = getKeys;
|
|
2375
|
+
}
|
|
2376
|
+
createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress) {
|
|
2377
|
+
const makeOffer = (utxos) => {
|
|
2378
|
+
if (utxos.length === 0) return require_dist.none();
|
|
2379
|
+
const totalValue = require_dist.pipe(utxos, require_dist.map$4((coin) => coin.utxo.value), require_dist.sumAll);
|
|
2380
|
+
const inputs = utxos.map(({ utxo }) => ({
|
|
2381
|
+
...utxo,
|
|
2382
|
+
owner: nightVerifyingKey
|
|
2383
|
+
}));
|
|
2384
|
+
const output = {
|
|
2385
|
+
owner: (0, _midnight_ntwrk_ledger_v8.addressFromKey)(nightVerifyingKey),
|
|
2386
|
+
type: require_dist.Token.night,
|
|
2387
|
+
value: totalValue
|
|
2388
|
+
};
|
|
2389
|
+
return require_dist.some(_midnight_ntwrk_ledger_v8.UnshieldedOffer.new(inputs, [output], []));
|
|
2390
|
+
};
|
|
2391
|
+
return require_dist.gen$1(this, function* () {
|
|
2392
|
+
const receiver = dustReceiverAddress ? dustReceiverAddress.data : void 0;
|
|
2393
|
+
return yield* require_dist.ledgerTry(() => {
|
|
2394
|
+
const network = this.networkId;
|
|
2395
|
+
const splitResult = this.getCoins().splitNightUtxos(nightUtxos);
|
|
2396
|
+
const feePayment = receiver ? require_dist.pipe(splitResult.guaranteed, require_dist.filter$2((coin) => !coin.utxo.registeredForDustGeneration), require_dist.map$4((coin) => coin.dust.generatedNow), require_dist.sumAll) : 0n;
|
|
2397
|
+
const maybeGuaranteedOffer = makeOffer(splitResult.guaranteed);
|
|
2398
|
+
const maybeFallibleOffer = makeOffer(splitResult.fallible);
|
|
2399
|
+
const dustRegistration = new _midnight_ntwrk_ledger_v8.DustRegistration(SignatureMarker.signature, nightVerifyingKey, receiver, feePayment);
|
|
2400
|
+
const dustActions = new _midnight_ntwrk_ledger_v8.DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [], [dustRegistration]);
|
|
2401
|
+
const intent = require_dist.pipe(_midnight_ntwrk_ledger_v8.Intent.new(ttl), (intent) => require_dist.match$1(maybeGuaranteedOffer, {
|
|
2402
|
+
onNone: () => intent,
|
|
2403
|
+
onSome: (guaranteedOffer) => {
|
|
2404
|
+
intent.guaranteedUnshieldedOffer = guaranteedOffer;
|
|
2405
|
+
return intent;
|
|
2406
|
+
}
|
|
2407
|
+
}), (intent) => require_dist.match$1(maybeFallibleOffer, {
|
|
2408
|
+
onNone: () => intent,
|
|
2409
|
+
onSome: (fallibleOffer) => {
|
|
2410
|
+
intent.fallibleUnshieldedOffer = fallibleOffer;
|
|
2411
|
+
return intent;
|
|
2412
|
+
}
|
|
2413
|
+
}), (intent) => {
|
|
2414
|
+
intent.dustActions = dustActions;
|
|
2415
|
+
return intent;
|
|
2416
|
+
});
|
|
2417
|
+
return _midnight_ntwrk_ledger_v8.Transaction.fromParts(network, void 0, void 0, intent);
|
|
2418
|
+
});
|
|
2419
|
+
});
|
|
2420
|
+
}
|
|
2421
|
+
splitNightUtxosForDustRegistration(utxosWithDustValue, isRegistration) {
|
|
2422
|
+
const splitResult = this.getCoins().splitNightUtxos(utxosWithDustValue);
|
|
2423
|
+
const feePayment = isRegistration ? require_dist.pipe(splitResult.guaranteed, require_dist.filter$2((coin) => !coin.utxo.registeredForDustGeneration), require_dist.map$4((coin) => coin.dust.generatedNow), require_dist.sumAll) : 0n;
|
|
2424
|
+
return {
|
|
2425
|
+
guaranteedUtxos: splitResult.guaranteed,
|
|
2426
|
+
fallibleUtxos: splitResult.fallible,
|
|
2427
|
+
feePayment
|
|
2428
|
+
};
|
|
2429
|
+
}
|
|
2430
|
+
attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
2431
|
+
return require_dist.gen$1(this, function* () {
|
|
2432
|
+
const intent = transaction.intents?.get(1);
|
|
2433
|
+
if (!intent) return yield* require_dist.left(new TransactingError({ message: "No intent found at segment 1; expected an intent built by rotateUtxos" }));
|
|
2434
|
+
if (intent.dustActions !== void 0 && intent.dustActions.registrations.length > 0) return yield* require_dist.left(new TransactingError({ message: "Intent at segment 1 already has a dust registration attached" }));
|
|
2435
|
+
return yield* require_dist.ledgerTry(() => {
|
|
2436
|
+
const receiver = dustReceiverAddress ? dustReceiverAddress.data : void 0;
|
|
2437
|
+
const dustRegistration = new _midnight_ntwrk_ledger_v8.DustRegistration(SignatureMarker.signature, nightVerifyingKey, receiver, feePayment);
|
|
2438
|
+
const dustActions = new _midnight_ntwrk_ledger_v8.DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [], [dustRegistration]);
|
|
2439
|
+
const newIntent = _midnight_ntwrk_ledger_v8.Intent.deserialize(SignatureMarker.signature, ProofMarker.preProof, BindingMarker.preBinding, intent.serialize());
|
|
2440
|
+
newIntent.dustActions = dustActions;
|
|
2441
|
+
const newTransaction = _midnight_ntwrk_ledger_v8.Transaction.deserialize(SignatureMarker.signature, ProofMarker.preProof, BindingMarker.preBinding, transaction.serialize());
|
|
2442
|
+
newTransaction.intents = newTransaction.intents.set(1, newIntent);
|
|
2443
|
+
return newTransaction;
|
|
2444
|
+
});
|
|
2445
|
+
});
|
|
2446
|
+
}
|
|
2447
|
+
addDustRegistrationSignature(transaction, signatureData) {
|
|
2448
|
+
return require_dist.gen$1(this, function* () {
|
|
2449
|
+
const intent = transaction.intents?.get(1);
|
|
2450
|
+
if (!intent) return yield* require_dist.left(new TransactingError({ message: "No intent found in the transaction intents with segment = 1" }));
|
|
2451
|
+
const { dustActions } = intent;
|
|
2452
|
+
if (!dustActions) return yield* require_dist.left(new TransactingError({ message: "No dustActions found in intent" }));
|
|
2453
|
+
const [registration, ...restRegistrations] = dustActions.registrations;
|
|
2454
|
+
if (!registration) return yield* require_dist.left(new TransactingError({ message: "No registrations found in dustActions" }));
|
|
2455
|
+
return yield* require_dist.ledgerTry(() => {
|
|
2456
|
+
const signature = new _midnight_ntwrk_ledger_v8.SignatureEnabled(signatureData);
|
|
2457
|
+
const registrationWithSignature = new _midnight_ntwrk_ledger_v8.DustRegistration(signature.instance, registration.nightKey, registration.dustAddress, registration.allowFeePayment, signature);
|
|
2458
|
+
const newDustActions = new _midnight_ntwrk_ledger_v8.DustActions(signature.instance, ProofMarker.preProof, dustActions.ctime, dustActions.spends, [registrationWithSignature, ...restRegistrations]);
|
|
2459
|
+
const newIntent = _midnight_ntwrk_ledger_v8.Intent.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, intent.serialize());
|
|
2460
|
+
newIntent.dustActions = newDustActions;
|
|
2461
|
+
const newTransaction = _midnight_ntwrk_ledger_v8.Transaction.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, transaction.serialize());
|
|
2462
|
+
newTransaction.intents = newTransaction.intents.set(1, newIntent);
|
|
2463
|
+
return newTransaction;
|
|
2464
|
+
});
|
|
2465
|
+
});
|
|
2466
|
+
}
|
|
2467
|
+
addDustGenerationSignature(transaction, signatureData) {
|
|
2468
|
+
return require_dist.gen$1(this, function* () {
|
|
2469
|
+
const intent = transaction.intents?.get(1);
|
|
2470
|
+
if (!intent) return yield* require_dist.left(new TransactingError({ message: "No intent found in the transaction intents with segment = 1" }));
|
|
2471
|
+
const { dustActions, guaranteedUnshieldedOffer, fallibleUnshieldedOffer } = intent;
|
|
2472
|
+
if (!dustActions) return yield* require_dist.left(new TransactingError({ message: "No dustActions found in intent" }));
|
|
2473
|
+
if (!guaranteedUnshieldedOffer) return yield* require_dist.left(new TransactingError({ message: "No guaranteedUnshieldedOffer found in intent" }));
|
|
2474
|
+
const [registration, ...restRegistrations] = dustActions.registrations;
|
|
2475
|
+
if (!registration) return yield* require_dist.left(new TransactingError({ message: "No registrations found in dustActions" }));
|
|
2476
|
+
return yield* require_dist.ledgerTry(() => {
|
|
2477
|
+
const signature = new _midnight_ntwrk_ledger_v8.SignatureEnabled(signatureData);
|
|
2478
|
+
const registrationWithSignature = new _midnight_ntwrk_ledger_v8.DustRegistration(signature.instance, registration.nightKey, registration.dustAddress, registration.allowFeePayment, signature);
|
|
2479
|
+
const newDustActions = new _midnight_ntwrk_ledger_v8.DustActions(signature.instance, ProofMarker.preProof, dustActions.ctime, dustActions.spends, [registrationWithSignature, ...restRegistrations]);
|
|
2480
|
+
const newIntent = _midnight_ntwrk_ledger_v8.Intent.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, intent.serialize());
|
|
2481
|
+
newIntent.dustActions = newDustActions;
|
|
2482
|
+
const guaranteedSignatures = Array.from({ length: guaranteedUnshieldedOffer.inputs.length }, (_, i) => guaranteedUnshieldedOffer.signatures.at(i) ?? signatureData);
|
|
2483
|
+
newIntent.guaranteedUnshieldedOffer = guaranteedUnshieldedOffer.addSignatures(guaranteedSignatures);
|
|
2484
|
+
if (fallibleUnshieldedOffer) {
|
|
2485
|
+
const fallibleSignatures = Array.from({ length: fallibleUnshieldedOffer.inputs.length }, (_, i) => fallibleUnshieldedOffer.signatures.at(i) ?? signatureData);
|
|
2486
|
+
newIntent.fallibleUnshieldedOffer = fallibleUnshieldedOffer.addSignatures(fallibleSignatures);
|
|
2487
|
+
}
|
|
2488
|
+
const newTransaction = _midnight_ntwrk_ledger_v8.Transaction.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, transaction.serialize());
|
|
2489
|
+
newTransaction.intents = newTransaction.intents.set(1, newIntent);
|
|
2490
|
+
return newTransaction;
|
|
2491
|
+
});
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
calculateFee(transaction, ledgerParams) {
|
|
2495
|
+
return transaction.feesWithMargin(ledgerParams, this.costParams.feeBlocksMargin) + (this.costParams.additionalFeeOverhead ?? 0n);
|
|
2496
|
+
}
|
|
2497
|
+
dryRunFee(recipeInputs, transactions, secretKey, state, ttl, currentTime, ledgerParams) {
|
|
2498
|
+
const network = this.networkId;
|
|
2499
|
+
const [spends] = CoreWallet.spendCoins(state, secretKey, recipeInputs, currentTime);
|
|
2500
|
+
const intent = _midnight_ntwrk_ledger_v8.Intent.new(ttl);
|
|
2501
|
+
intent.dustActions = new _midnight_ntwrk_ledger_v8.DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [...spends], []);
|
|
2502
|
+
const [first, ...rest] = transactions.map((tx) => tx.eraseProofs());
|
|
2503
|
+
const mergedExisting = first ? rest.reduce((acc, tx) => acc.merge(tx), first) : void 0;
|
|
2504
|
+
const segmentId = mergedExisting ? require_dist.getOrElse(findAvailableSegmentId$1(mergedExisting), () => 1) : 1;
|
|
2505
|
+
const erasedBalancing = _midnight_ntwrk_ledger_v8.Transaction.fromParts(network).addIntent({
|
|
2506
|
+
tag: "specific",
|
|
2507
|
+
value: segmentId
|
|
2508
|
+
}, intent).eraseProofs();
|
|
2509
|
+
const mergedTx = mergedExisting ? mergedExisting.merge(erasedBalancing) : erasedBalancing;
|
|
2510
|
+
return this.calculateFee(mergedTx, ledgerParams);
|
|
2511
|
+
}
|
|
2512
|
+
static feeImbalance(transaction, totalFee) {
|
|
2513
|
+
const [_, imbalance] = transaction.imbalances(0, totalFee).entries().find(([tt, _]) => tt.tag === "dust") ?? [];
|
|
2514
|
+
return imbalance ?? 0n;
|
|
2515
|
+
}
|
|
2516
|
+
computeBalancingRecipe(secretKey, state, transactions, ttl, currentTime, ledgerParams) {
|
|
2517
|
+
const initialFees = transactions.reduce((total, transaction) => total + TransactingCapabilityImplementation$1.feeImbalance(transaction, this.calculateFee(transaction, ledgerParams)), 0n);
|
|
2518
|
+
const dust = this.getCoins().getAvailableCoinsWithGeneratedDust(state, currentTime);
|
|
2519
|
+
return require_dist.pipe(require_dist.iterate({
|
|
2520
|
+
currentFee: initialFees,
|
|
2521
|
+
recipeInputs: [],
|
|
2522
|
+
converged: false
|
|
2523
|
+
}, {
|
|
2524
|
+
while: (s) => !s.converged,
|
|
2525
|
+
body: ({ currentFee }) => require_dist.try_({
|
|
2526
|
+
try: () => {
|
|
2527
|
+
const recipeInputs = require_dist.getBalanceRecipe({
|
|
2528
|
+
coins: dust.map((coin) => ({
|
|
2529
|
+
type: "dust",
|
|
2530
|
+
value: coin.value,
|
|
2531
|
+
token: coin.token
|
|
2532
|
+
})),
|
|
2533
|
+
initialImbalances: require_dist.Imbalances.fromEntry("dust", currentFee),
|
|
2534
|
+
feeTokenType: "dust",
|
|
2535
|
+
coinSelection: this.getCoinSelection(),
|
|
2536
|
+
transactionCostModel: {
|
|
2537
|
+
inputFeeOverhead: 0n,
|
|
2538
|
+
outputFeeOverhead: 0n
|
|
2539
|
+
},
|
|
2540
|
+
createOutput: (coin) => coin,
|
|
2541
|
+
isCoinEqual: (a, b) => a.token.nonce === b.token.nonce
|
|
2542
|
+
}).inputs.map(({ token, value }) => ({
|
|
2543
|
+
token,
|
|
2544
|
+
value
|
|
2545
|
+
}));
|
|
2546
|
+
const newFee = this.dryRunFee(recipeInputs, transactions, secretKey, state, ttl, currentTime, ledgerParams);
|
|
2547
|
+
return {
|
|
2548
|
+
currentFee: newFee,
|
|
2549
|
+
recipeInputs,
|
|
2550
|
+
converged: newFee <= recipeInputs.reduce((sum, input) => sum + input.value, 0n)
|
|
2551
|
+
};
|
|
2552
|
+
},
|
|
2553
|
+
catch: (err) => {
|
|
2554
|
+
if (err instanceof require_dist.InsufficientFundsError) return new InsufficientFundsError({
|
|
2555
|
+
message: err.message,
|
|
2556
|
+
tokenType: err.tokenType
|
|
2557
|
+
});
|
|
2558
|
+
else return new OtherWalletError({
|
|
2559
|
+
message: err instanceof Error ? err.message : "Dust balancing failed",
|
|
2560
|
+
cause: err
|
|
2561
|
+
});
|
|
2562
|
+
}
|
|
2563
|
+
})
|
|
2564
|
+
}), require_dist.either$1, require_dist.runSync, require_dist.map$6(({ currentFee, recipeInputs }) => ({
|
|
2565
|
+
fee: currentFee,
|
|
2566
|
+
recipeInputs: distributeFeeAcrossInputs$1(recipeInputs, currentFee)
|
|
2567
|
+
})));
|
|
2568
|
+
}
|
|
2569
|
+
estimateFee(secretKey, state, transactions, ttl, currentTime, ledgerParams) {
|
|
2570
|
+
return require_dist.pipe(this.computeBalancingRecipe(secretKey, state, transactions, ttl, currentTime, ledgerParams), require_dist.map$6(({ fee }) => fee));
|
|
2571
|
+
}
|
|
2572
|
+
balanceTransactions(secretKey, state, transactions, ttl, currentTime, ledgerParams) {
|
|
2573
|
+
const networkId = this.networkId;
|
|
2574
|
+
return require_dist.pipe(this.computeBalancingRecipe(secretKey, state, transactions, ttl, currentTime, ledgerParams), require_dist.flatMap$4(({ recipeInputs }) => {
|
|
2575
|
+
return require_dist.ledgerTry(() => {
|
|
2576
|
+
const intent = _midnight_ntwrk_ledger_v8.Intent.new(ttl);
|
|
2577
|
+
const [spends, updatedState] = CoreWallet.spendCoins(state, secretKey, recipeInputs, currentTime);
|
|
2578
|
+
intent.dustActions = new _midnight_ntwrk_ledger_v8.DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [...spends], []);
|
|
2579
|
+
const [first, ...rest] = transactions.map((tx) => tx.eraseProofs());
|
|
2580
|
+
const mergedExisting = first ? rest.reduce((acc, tx) => acc.merge(tx), first) : void 0;
|
|
2581
|
+
const segmentId = mergedExisting ? require_dist.getOrElse(findAvailableSegmentId$1(mergedExisting), () => 1) : 1;
|
|
2582
|
+
return [_midnight_ntwrk_ledger_v8.Transaction.fromParts(networkId).addIntent({
|
|
2583
|
+
tag: "specific",
|
|
2584
|
+
value: segmentId
|
|
2585
|
+
}, intent), updatedState];
|
|
2586
|
+
});
|
|
2587
|
+
}));
|
|
2588
|
+
}
|
|
2589
|
+
revertTransaction(state, transaction) {
|
|
2590
|
+
return require_dist.try_$1({
|
|
2591
|
+
try: () => CoreWallet.revertTransaction(state, transaction),
|
|
2592
|
+
catch: (err) => {
|
|
2593
|
+
return new OtherWalletError({
|
|
2594
|
+
message: `Error while reverting transaction ${transaction.identifiers().at(0)}`,
|
|
2595
|
+
cause: err
|
|
2596
|
+
});
|
|
2597
|
+
}
|
|
2598
|
+
});
|
|
2599
|
+
}
|
|
2600
|
+
};
|
|
2601
|
+
//#endregion
|
|
2602
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/RunningV1Variant.js
|
|
2603
|
+
const progress = (state) => {
|
|
2604
|
+
const appliedIndex = state.progress?.appliedIndex ?? 0n;
|
|
2605
|
+
const highestRelevantWalletIndex = state.progress?.highestRelevantWalletIndex ?? 0n;
|
|
2606
|
+
const sourceGap = (state.progress?.highestIndex ?? 0n) - (state.progress?.highestRelevantIndex ?? 0n);
|
|
2607
|
+
const applyGap = highestRelevantWalletIndex - appliedIndex;
|
|
2608
|
+
return [require_dist.ProgressUpdate({
|
|
2609
|
+
sourceGap,
|
|
2610
|
+
applyGap
|
|
2611
|
+
})];
|
|
2612
|
+
};
|
|
2613
|
+
/**
|
|
2614
|
+
* The version signals this variant puts on its state stream.
|
|
2615
|
+
*
|
|
2616
|
+
* @remarks
|
|
2617
|
+
* Two of them, for two different situations. A transition is the ordinary one: the state moved to a version the variant
|
|
2618
|
+
* may or may not own, and the runtime decides. The healing emission covers restore: a snapshot taken between the
|
|
2619
|
+
* moment sync annotated an out-of-range version and the moment the runtime acted on it comes back with a version this
|
|
2620
|
+
* variant does not own and no transition to announce it, so it would sit there forever. Announcing it on the first
|
|
2621
|
+
* observation is what forward-migrates such a snapshot.
|
|
2622
|
+
*/
|
|
2623
|
+
const protocolVersionChange = (previous, current, isInitial, activationRange) => {
|
|
2624
|
+
const transitioned = previous.protocolVersion != current.protocolVersion;
|
|
2625
|
+
const strandedOutsideRange = isInitial && !require_dist.withinRange(current.protocolVersion, activationRange);
|
|
2626
|
+
return transitioned || strandedOutsideRange ? [require_dist.VersionChange({ change: require_dist.Version({ version: require_dist.ProtocolVersion(current.protocolVersion) }) })] : [];
|
|
2627
|
+
};
|
|
2628
|
+
const V1Tag = Symbol("V1");
|
|
2629
|
+
/**
|
|
2630
|
+
* How a failing synchronization pass is retried.
|
|
2631
|
+
*
|
|
2632
|
+
* @remarks
|
|
2633
|
+
* Exported so the delays it actually produces can be asserted. A schedule reads as though its combinators apply to the
|
|
2634
|
+
* delay, and for some of them they do not — which is worth pinning in a test rather than trusting by eye.
|
|
2635
|
+
*/
|
|
2636
|
+
const syncRetrySchedule = require_dist.pipe(require_dist.exponential(require_dist.seconds(1), 2), require_dist.jittered, require_dist.union(require_dist.spaced(require_dist.minutes(2))));
|
|
2637
|
+
var RunningV1Variant = class {
|
|
2638
|
+
__polyTag__ = V1Tag;
|
|
2639
|
+
#scope;
|
|
2640
|
+
#context;
|
|
2641
|
+
#v1Context;
|
|
2642
|
+
#txHistoryPermits = require_dist.makeSemaphore(8).pipe(require_dist.runSync);
|
|
2643
|
+
state;
|
|
2644
|
+
#syncLock;
|
|
2645
|
+
/**
|
|
2646
|
+
* Whether a background synchronization worker is already running.
|
|
2647
|
+
*
|
|
2648
|
+
* @remarks
|
|
2649
|
+
* Distinct from {@link #syncLock}, which is released at the end of every pass and so says nothing about the worker
|
|
2650
|
+
* that runs them. Held for the worker's whole lifetime — polling delays and retries included — and released as it
|
|
2651
|
+
* exits, so a wallet started again while it is already synchronizing keeps the worker it has instead of gaining a
|
|
2652
|
+
* second one that polls alongside it until the wallet stops.
|
|
2653
|
+
*
|
|
2654
|
+
* The guard asks only whether a worker is running, not what it was started with, so a second start is ignored even
|
|
2655
|
+
* when it carries different key material. Starting a running wallet on a second key is not a supported way to
|
|
2656
|
+
* change keys: stop it first. Two workers would be no better — they would apply two keys' updates to one state.
|
|
2657
|
+
*/
|
|
2658
|
+
#backgroundWorkerLock;
|
|
2659
|
+
constructor(scope, context, v1Context) {
|
|
2660
|
+
this.#scope = scope;
|
|
2661
|
+
this.#context = context;
|
|
2662
|
+
this.#v1Context = v1Context;
|
|
2663
|
+
this.#syncLock = require_dist.runSync(require_dist.make$2(false));
|
|
2664
|
+
this.#backgroundWorkerLock = require_dist.runSync(require_dist.make$2(false));
|
|
2665
|
+
this.state = require_dist.fromEffect(context.stateRef.get).pipe(require_dist.flatMap((initialState) => context.stateRef.changes.pipe(require_dist.mapAccum({
|
|
2666
|
+
previous: initialState,
|
|
2667
|
+
isInitial: true
|
|
2668
|
+
}, (seen, current) => [{
|
|
2669
|
+
previous: current,
|
|
2670
|
+
isInitial: false
|
|
2671
|
+
}, [
|
|
2672
|
+
seen.previous,
|
|
2673
|
+
current,
|
|
2674
|
+
seen.isInitial
|
|
2675
|
+
]]))), require_dist.mapConcat(([previous, current, isInitial]) => {
|
|
2676
|
+
return [
|
|
2677
|
+
require_dist.State({ state: current }),
|
|
2678
|
+
...progress(current),
|
|
2679
|
+
...protocolVersionChange(previous, current, isInitial, context.activationRange)
|
|
2680
|
+
];
|
|
2681
|
+
}));
|
|
2682
|
+
}
|
|
2683
|
+
startSyncInBackground(startAux) {
|
|
2684
|
+
const attempt = this.startSync(startAux).pipe(require_dist.runScoped(require_dist.drain), require_dist.scoped).pipe(require_dist.retry$1(syncRetrySchedule));
|
|
2685
|
+
const worker = BackgroundRepeat$1.$match(this.#v1Context.syncService.backgroundRepeat, {
|
|
2686
|
+
Once: () => attempt,
|
|
2687
|
+
WithDelay: ({ delay }) => require_dist.repeat(attempt, require_dist.spaced(delay)).pipe(require_dist.asVoid)
|
|
2688
|
+
});
|
|
2689
|
+
return require_dist.modify(this.#backgroundWorkerLock, (isRunning) => [!isRunning, true]).pipe(require_dist.flatMap$1((acquired) => acquired ? worker.pipe(require_dist.ensuring$1(require_dist.set(this.#backgroundWorkerLock, false)), require_dist.forkScoped, require_dist.asVoid) : require_dist._void), require_dist.provideService(require_dist.Scope, this.#scope));
|
|
2690
|
+
}
|
|
2691
|
+
/**
|
|
2692
|
+
* Runs one sync pass to completion, rather than forking it into the background.
|
|
2693
|
+
*
|
|
2694
|
+
* @remarks
|
|
2695
|
+
* Only meaningful with a sync service whose stream terminates. The indexer-event service this variant defaults to is
|
|
2696
|
+
* an open subscription, so use {@link startSyncInBackground} with it; this entry point exists for a finite service
|
|
2697
|
+
* supplied through the builder's `withSync`. It shares {@link startSync}'s lock, so a pass started while a
|
|
2698
|
+
* background sync is running returns immediately without touching the state.
|
|
2699
|
+
*/
|
|
2700
|
+
sync(startAux) {
|
|
2701
|
+
return this.startSync(startAux).pipe(require_dist.runScoped(require_dist.drain), require_dist.scoped);
|
|
2702
|
+
}
|
|
2703
|
+
startSync(startAux) {
|
|
2704
|
+
return require_dist.pipe(require_dist.modify(this.#syncLock, (isLocked) => [!isLocked, true]), require_dist.fromEffect, require_dist.flatMap((acquired) => {
|
|
2705
|
+
if (!acquired) return require_dist.empty;
|
|
2706
|
+
return require_dist.pipe(require_dist.get(this.#context.stateRef), require_dist.fromEffect, require_dist.flatMap((state) => this.#v1Context.syncService.updates(state, startAux)), require_dist.mapEffect((update) => require_dist.modifyEffect(this.#context.stateRef, (state) => require_dist.try_({
|
|
2707
|
+
try: () => {
|
|
2708
|
+
const [newState, changesResult] = this.#v1Context.syncCapability.applyUpdate(state, update, this.#context.activationRange);
|
|
2709
|
+
return [changesResult, newState];
|
|
2710
|
+
},
|
|
2711
|
+
catch: (err) => new OtherWalletError({
|
|
2712
|
+
message: "Error while applying sync update",
|
|
2713
|
+
cause: err
|
|
2714
|
+
})
|
|
2715
|
+
})).pipe(require_dist.flatMap$1(({ changes, protocolVersion }) => changes.length === 0 ? require_dist._void : require_dist.pipe(require_dist.forEach(changes, (change) => require_dist.pipe(this.#txHistoryPermits.withPermits(1)(require_dist.pipe(this.#v1Context.transactionHistoryService.getTransactionDetails(change.source), require_dist.flatMap$1((metadata) => this.#v1Context.transactionHistoryService.put(change, metadata, protocolVersion)))), require_dist.catchAllCause((cause) => require_dist.logError(cause, `Failed to record dust tx-history section for ${change.source}`))), {
|
|
2716
|
+
discard: true,
|
|
2717
|
+
concurrency: 8
|
|
2718
|
+
}), require_dist.forkScoped)), require_dist.provideService(require_dist.Scope, this.#scope))), require_dist.tapError((error$1) => require_dist.error(error$1)), require_dist.ensuring(require_dist.set(this.#syncLock, false)));
|
|
2719
|
+
}));
|
|
2720
|
+
}
|
|
2721
|
+
createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress) {
|
|
2722
|
+
if (nightUtxos.some((utxo) => utxo.type !== require_dist.Token.night)) return require_dist.fail$2(new OtherWalletError({ message: "Token of a non-Night type received" }));
|
|
2723
|
+
return require_dist.Do.pipe(require_dist.bind("currentState", () => require_dist.get(this.#context.stateRef)), require_dist.bind("blockData", () => this.#v1Context.syncService.blockData()), require_dist.let_("resolvedTime", ({ blockData }) => currentTime ?? blockData.timestamp), require_dist.let_("utxosWithDustValue", ({ currentState, resolvedTime }) => {
|
|
2724
|
+
return this.#v1Context.coinsAndBalancesCapability.estimateDustGeneration(currentState, nightUtxos, resolvedTime);
|
|
2725
|
+
}), require_dist.flatMap$1(({ utxosWithDustValue, resolvedTime }) => {
|
|
2726
|
+
return this.#v1Context.transactingCapability.createDustGenerationTransaction(resolvedTime, ttl, utxosWithDustValue, nightVerifyingKey, dustReceiverAddress).pipe(require_dist.toEffect);
|
|
2727
|
+
}));
|
|
2728
|
+
}
|
|
2729
|
+
splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration) {
|
|
2730
|
+
if (nightUtxos.some((utxo) => utxo.type !== require_dist.Token.night)) return require_dist.fail$2(new OtherWalletError({ message: "Token of a non-Night type received" }));
|
|
2731
|
+
return require_dist.gen(this, function* () {
|
|
2732
|
+
const currentState = yield* require_dist.get(this.#context.stateRef);
|
|
2733
|
+
const utxosWithDustValue = this.#v1Context.coinsAndBalancesCapability.estimateDustGeneration(currentState, nightUtxos, currentTime);
|
|
2734
|
+
return this.#v1Context.transactingCapability.splitNightUtxosForDustRegistration(utxosWithDustValue, isRegistration);
|
|
2735
|
+
});
|
|
2736
|
+
}
|
|
2737
|
+
attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
2738
|
+
return this.#v1Context.transactingCapability.attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment).pipe(require_dist.toEffect);
|
|
2739
|
+
}
|
|
2740
|
+
addDustGenerationSignature(transaction, signature) {
|
|
2741
|
+
return this.#v1Context.transactingCapability.addDustGenerationSignature(transaction, signature).pipe(require_dist.toEffect);
|
|
2742
|
+
}
|
|
2743
|
+
addDustRegistrationSignature(transaction, signature) {
|
|
2744
|
+
return this.#v1Context.transactingCapability.addDustRegistrationSignature(transaction, signature).pipe(require_dist.toEffect);
|
|
2745
|
+
}
|
|
2746
|
+
calculateFee(transactions) {
|
|
2747
|
+
return require_dist.pipe(this.#v1Context.syncService.blockData(), require_dist.map$2((blockData) => require_dist.pipe(transactions, require_dist.map$3((transaction) => this.#v1Context.transactingCapability.calculateFee(transaction, blockData.ledgerParameters)), require_dist.sumBigInt)));
|
|
2748
|
+
}
|
|
2749
|
+
estimateFee(secretKey, transactions, ttl, currentTime) {
|
|
2750
|
+
return require_dist.pipe(require_dist.all([require_dist.get(this.#context.stateRef), this.#v1Context.syncService.blockData()]), require_dist.flatMap$1(([state, blockData]) => require_dist.pipe(this.#v1Context.transactingCapability.estimateFee(secretKey, state, transactions, ttl, currentTime ?? blockData.timestamp, blockData.ledgerParameters), require_dist.toEffect)));
|
|
2751
|
+
}
|
|
2752
|
+
balanceTransactions(secretKey, transactions, ttl, currentTime) {
|
|
2753
|
+
return require_dist.pipe(this.#v1Context.syncService.blockData(), require_dist.flatMap$1((blockData) => require_dist.pipe(require_dist.modifyEffect(this.#context.stateRef, (state) => this.#v1Context.transactingCapability.balanceTransactions(secretKey, state, transactions, ttl, currentTime ?? blockData.timestamp, blockData.ledgerParameters)), require_dist.map$2((transaction) => ({
|
|
2754
|
+
transaction,
|
|
2755
|
+
blockData
|
|
2756
|
+
})))));
|
|
2757
|
+
}
|
|
2758
|
+
revertTransaction(transaction) {
|
|
2759
|
+
return require_dist.updateEffect(this.#context.stateRef, (state) => {
|
|
2760
|
+
return require_dist.pipe(this.#v1Context.transactingCapability.revertTransaction(state, transaction), require_dist.toEffect);
|
|
2761
|
+
});
|
|
2762
|
+
}
|
|
2763
|
+
};
|
|
2764
|
+
//#endregion
|
|
2765
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/TransactionHistory.js
|
|
2766
|
+
const DustUtxoInfoSchema$1 = require_dist.Struct({
|
|
2767
|
+
initialValue: require_dist.BigInt$,
|
|
2768
|
+
nonce: require_dist.BigInt$,
|
|
2769
|
+
seq: require_dist.Number$,
|
|
2770
|
+
backingNight: require_dist.String$,
|
|
2771
|
+
mtIndex: require_dist.BigInt$
|
|
2772
|
+
});
|
|
2773
|
+
const DustSectionSchema$1 = require_dist.Struct({
|
|
2774
|
+
receivedUtxos: require_dist.Array$(DustUtxoInfoSchema$1),
|
|
2775
|
+
spentUtxos: require_dist.Array$(DustUtxoInfoSchema$1)
|
|
2776
|
+
});
|
|
2777
|
+
require_dist.extendEntrySchema({ dust: require_dist.optional(DustSectionSchema$1) });
|
|
2778
|
+
require_dist.equivalence(DustUtxoInfoSchema$1);
|
|
2779
|
+
const convertQualifiedDustOutput$1 = (utxo) => ({
|
|
2780
|
+
initialValue: utxo.initialValue,
|
|
2781
|
+
nonce: utxo.nonce,
|
|
2782
|
+
seq: utxo.seq,
|
|
2783
|
+
backingNight: utxo.backingNight,
|
|
2784
|
+
mtIndex: utxo.mtIndex
|
|
2785
|
+
});
|
|
2786
|
+
const convertUpdateToFinalizedInput$1 = (changes, metadata, protocolVersion) => ({
|
|
2787
|
+
hash: changes.source,
|
|
2788
|
+
protocolVersion,
|
|
2789
|
+
status: metadata.status,
|
|
2790
|
+
identifiers: metadata.identifiers,
|
|
2791
|
+
fees: metadata.fees,
|
|
2792
|
+
finalizedBlock: {
|
|
2793
|
+
hash: metadata.block.hash,
|
|
2794
|
+
height: metadata.block.height,
|
|
2795
|
+
timestamp: new Date(metadata.block.timestamp)
|
|
2796
|
+
},
|
|
2797
|
+
dust: {
|
|
2798
|
+
receivedUtxos: changes.receivedUtxos.map(convertQualifiedDustOutput$1),
|
|
2799
|
+
spentUtxos: changes.spentUtxos.map(convertQualifiedDustOutput$1)
|
|
2800
|
+
}
|
|
2801
|
+
});
|
|
2802
|
+
const gotFinalizedDust$1 = (txHistoryStorage, input) => require_dist.tryPromise({
|
|
2803
|
+
try: () => txHistoryStorage.gotFinalized(input),
|
|
2804
|
+
catch: (e) => new TransactionHistoryError({
|
|
2805
|
+
message: `Failed to record finalized history entry for ${input.hash}`,
|
|
2806
|
+
cause: e
|
|
2807
|
+
})
|
|
2808
|
+
});
|
|
2809
|
+
const makeDefaultTransactionHistoryService$1 = (config, _getContext) => {
|
|
2810
|
+
const txHistoryStorage = config.txHistoryStorage;
|
|
2811
|
+
const queryClientLayer = require_dist.layer$1({ url: config.indexerClientConnection.indexerHttpUrl });
|
|
2812
|
+
const retryWindow = config.transactionDetailsRetryWindow ?? require_dist.minutes(2);
|
|
2813
|
+
return {
|
|
2814
|
+
put: (changes, metadata, protocolVersion) => gotFinalizedDust$1(txHistoryStorage, convertUpdateToFinalizedInput$1(changes, metadata, protocolVersion)),
|
|
2815
|
+
getTransactionDetails: (hash) => require_dist.gen(function* () {
|
|
2816
|
+
const result = yield* (yield* require_dist.TransactionHistoryDetail)({ transactionHash: hash });
|
|
2817
|
+
const tx = yield* require_dist.head$1(result.transactions).pipe(require_dist.orElseFail(() => new TransactionHistoryError({ message: `Indexer has not yet indexed transaction ${hash}` })));
|
|
2818
|
+
const rawStatus = tx.__typename === "RegularTransaction" ? tx.transactionResult.status : void 0;
|
|
2819
|
+
const status = rawStatus === "FAILURE" || rawStatus === "PARTIAL_SUCCESS" ? rawStatus : "SUCCESS";
|
|
2820
|
+
const identifiers = tx.__typename === "RegularTransaction" ? tx.identifiers : [];
|
|
2821
|
+
const fees = tx.__typename === "RegularTransaction" ? BigInt(tx.fees.paidFees) : null;
|
|
2822
|
+
return {
|
|
2823
|
+
hash: tx.hash,
|
|
2824
|
+
block: {
|
|
2825
|
+
hash: tx.block.hash,
|
|
2826
|
+
height: tx.block.height,
|
|
2827
|
+
timestamp: tx.block.timestamp
|
|
2828
|
+
},
|
|
2829
|
+
status,
|
|
2830
|
+
identifiers,
|
|
2831
|
+
fees
|
|
2832
|
+
};
|
|
2833
|
+
}).pipe(require_dist.provide(queryClientLayer), require_dist.scoped, require_dist.retry$1({
|
|
2834
|
+
schedule: require_dist.exponential(require_dist.seconds(1)).pipe(require_dist.either(require_dist.spaced(require_dist.seconds(10))), require_dist.jittered, require_dist.upTo(retryWindow)),
|
|
2835
|
+
while: (error) => error instanceof TransactionHistoryError
|
|
2836
|
+
}), require_dist.mapError$2((error) => error instanceof TransactionHistoryError ? error : new TransactionHistoryError({
|
|
2837
|
+
message: `Failed to fetch transaction metadata for ${hash}`,
|
|
2838
|
+
cause: error
|
|
2839
|
+
})))
|
|
2840
|
+
};
|
|
2841
|
+
};
|
|
2842
|
+
//#endregion
|
|
2843
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/CoinsAndBalances.js
|
|
2844
|
+
const chooseCoin$1 = (coins) => coins.filter((coin) => coin.value > 0n).toSorted((a, b) => Number(a.value - b.value)).at(0);
|
|
2845
|
+
const FAKE_NONCE$1 = "0".repeat(64);
|
|
2846
|
+
const makeDefaultCoinsAndBalancesCapability$1 = (_config, getContext) => {
|
|
2847
|
+
const getWalletBalance = (state, time) => {
|
|
2848
|
+
return state.state.walletBalance(time);
|
|
2849
|
+
};
|
|
2850
|
+
const getGenerationInfo = (state, coin) => {
|
|
2851
|
+
const info = state.state.generationInfo(coin);
|
|
2852
|
+
return info && info.dtime ? {
|
|
2853
|
+
...info,
|
|
2854
|
+
dtime: /* @__PURE__ */ new Date(+info.dtime)
|
|
2855
|
+
} : info;
|
|
2856
|
+
};
|
|
2857
|
+
const resolveTime = (state, time) => time ?? state.state.syncTime;
|
|
2858
|
+
const toFullInfo = (state, coins, time) => coins.flatMap((coin) => {
|
|
2859
|
+
const genInfo = getGenerationInfo(state, coin);
|
|
2860
|
+
return genInfo ? [{
|
|
2861
|
+
token: coin,
|
|
2862
|
+
...getFullDustInfo(state.state.params, genInfo, coin, time)
|
|
2863
|
+
}] : [];
|
|
2864
|
+
});
|
|
2865
|
+
const availableDustTokens = (state) => {
|
|
2866
|
+
const pendingSpends = new Set([...state.pendingDust.values()].map((coin) => coin.nonce));
|
|
2867
|
+
return require_dist.pipe(state.state.utxos, require_dist.filter$1((coin) => !pendingSpends.has(coin.nonce)));
|
|
2868
|
+
};
|
|
2869
|
+
const getAvailableCoins = (state, time) => toFullInfo(state, availableDustTokens(state), resolveTime(state, time));
|
|
2870
|
+
const getPendingCoins = (state, time) => toFullInfo(state, state.pendingDust, resolveTime(state, time));
|
|
2871
|
+
const getTotalCoins = (state, time) => {
|
|
2872
|
+
const effectiveTime = resolveTime(state, time);
|
|
2873
|
+
return [...getAvailableCoins(state, effectiveTime), ...getPendingCoins(state, effectiveTime)];
|
|
2874
|
+
};
|
|
2875
|
+
const getAvailableCoinsWithGeneratedDust = (state, currentTime) => getAvailableCoins(state, currentTime).map((info) => ({
|
|
2876
|
+
token: info.token,
|
|
2877
|
+
value: info.generatedNow
|
|
2878
|
+
}));
|
|
2879
|
+
const getFullDustInfo = (parameters, genInfo, coin, currentTime) => {
|
|
2880
|
+
const generatedValue = _midnight_ntwrk_ledger_v8.updatedValue(coin.ctime, coin.initialValue, genInfo, currentTime, parameters);
|
|
2881
|
+
return {
|
|
2882
|
+
dtime: genInfo.dtime,
|
|
2883
|
+
maxCap: genInfo.value * parameters.nightDustRatio,
|
|
2884
|
+
maxCapReachedAt: require_dist.addSeconds(coin.ctime, parameters.timeToCapSeconds),
|
|
2885
|
+
generatedNow: generatedValue,
|
|
2886
|
+
rate: genInfo.value * parameters.generationDecayRate
|
|
2887
|
+
};
|
|
2888
|
+
};
|
|
2889
|
+
const estimateDustGeneration = (state, nightUtxos, currentTime) => {
|
|
2890
|
+
const dustPublicKey = getContext().keysCapability.getPublicKey(state);
|
|
2891
|
+
return require_dist.pipe(nightUtxos, require_dist.map$3((utxo) => {
|
|
2892
|
+
const genInfo = fakeGenerationInfo(utxo, dustPublicKey);
|
|
2893
|
+
const fakeDustCoin = fakeDustToken(dustPublicKey, utxo);
|
|
2894
|
+
return {
|
|
2895
|
+
utxo,
|
|
2896
|
+
dust: getFullDustInfo(state.state.params, genInfo, fakeDustCoin, currentTime)
|
|
2897
|
+
};
|
|
2898
|
+
}));
|
|
2899
|
+
};
|
|
2900
|
+
/** Create a fake generation info for a given Utxo. It allows to estimate the Dust generation from it */
|
|
2901
|
+
const fakeGenerationInfo = (utxo, dustPublicKey) => {
|
|
2902
|
+
return {
|
|
2903
|
+
value: utxo.value,
|
|
2904
|
+
owner: dustPublicKey,
|
|
2905
|
+
nonce: FAKE_NONCE$1,
|
|
2906
|
+
dtime: void 0
|
|
2907
|
+
};
|
|
2908
|
+
};
|
|
2909
|
+
/** Create a fake dust coin for a given Utxo. It allows to estimate full details of the Dust generation from it */
|
|
2910
|
+
const fakeDustToken = (dustPublicKey, utxo) => ({
|
|
2911
|
+
initialValue: 0n,
|
|
2912
|
+
owner: dustPublicKey,
|
|
2913
|
+
nonce: 0n,
|
|
2914
|
+
seq: 0,
|
|
2915
|
+
ctime: utxo.ctime,
|
|
2916
|
+
backingNight: "",
|
|
2917
|
+
mtIndex: 0n
|
|
2918
|
+
});
|
|
2919
|
+
const splitNightUtxos = (utxos) => {
|
|
2920
|
+
const [guaranteed, fallible] = require_dist.pipe(utxos, require_dist.sort(require_dist.pipe(require_dist.bigint, require_dist.reverse, require_dist.mapInput((coin) => coin.dust.generatedNow))), require_dist.splitAt(1));
|
|
2921
|
+
return {
|
|
2922
|
+
guaranteed,
|
|
2923
|
+
fallible
|
|
2924
|
+
};
|
|
2925
|
+
};
|
|
2926
|
+
return {
|
|
2927
|
+
getWalletBalance,
|
|
2928
|
+
getAvailableCoins,
|
|
2929
|
+
getPendingCoins,
|
|
2930
|
+
getTotalCoins,
|
|
2931
|
+
getAvailableCoinsWithGeneratedDust,
|
|
2932
|
+
getGenerationInfo,
|
|
2933
|
+
estimateDustGeneration,
|
|
2934
|
+
splitNightUtxos
|
|
2935
|
+
};
|
|
2936
|
+
};
|
|
2937
|
+
//#endregion
|
|
2938
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v1/V1Builder.js
|
|
2939
|
+
/**
|
|
2940
|
+
* Completes a builder configuration into the one the empty-wallet migration asks for.
|
|
2941
|
+
*
|
|
2942
|
+
* @remarks
|
|
2943
|
+
* The dust parameters are optional on the builder and required on the migration, and this is the single place that gap
|
|
2944
|
+
* is closed, so the fallback the unconfigured `build` takes and the one {@link V1Builder.withMigrationDefaults} states
|
|
2945
|
+
* explicitly cannot drift apart.
|
|
2946
|
+
*/
|
|
2947
|
+
const emptyWalletMigrationConfiguration$1 = (configuration) => ({
|
|
2948
|
+
networkId: configuration.networkId,
|
|
2949
|
+
dustParameters: configuration.dustParameters ?? _midnight_ntwrk_ledger_v8.LedgerParameters.initialParameters().dust
|
|
2950
|
+
});
|
|
2951
|
+
var V1Builder = class V1Builder {
|
|
2952
|
+
#buildState;
|
|
2953
|
+
constructor(buildState = {}) {
|
|
2954
|
+
this.#buildState = buildState;
|
|
2955
|
+
}
|
|
2956
|
+
withDefaults() {
|
|
2957
|
+
return this.withDefaultTransactionType().withSyncDefaults().withSerializationDefaults().withTransactingDefaults().withCoinsAndBalancesDefaults().withTransactionHistoryDefaults().withKeysDefaults().withStartAuxDefaults().withCoinSelectionDefaults();
|
|
2958
|
+
}
|
|
2959
|
+
withTransactionType() {
|
|
2960
|
+
return new V1Builder({
|
|
2961
|
+
...this.#buildState,
|
|
2962
|
+
transactingCapability: void 0
|
|
2963
|
+
});
|
|
2964
|
+
}
|
|
2965
|
+
withDefaultTransactionType() {
|
|
2966
|
+
return this.withTransactionType();
|
|
2967
|
+
}
|
|
2968
|
+
withSyncDefaults() {
|
|
2969
|
+
return this.withSync(makeDefaultSyncService$1, makeDefaultSyncCapability$1);
|
|
2970
|
+
}
|
|
2971
|
+
withSync(syncService, syncCapability) {
|
|
2972
|
+
return new V1Builder({
|
|
2973
|
+
...this.#buildState,
|
|
2974
|
+
syncService,
|
|
2975
|
+
syncCapability,
|
|
2976
|
+
startAux: void 0
|
|
2977
|
+
});
|
|
2978
|
+
}
|
|
2979
|
+
withSerializationDefaults() {
|
|
2980
|
+
return this.withSerialization(makeDefaultV1SerializationCapability);
|
|
2981
|
+
}
|
|
2982
|
+
withSerialization(serializationCapability) {
|
|
2983
|
+
return new V1Builder({
|
|
2984
|
+
...this.#buildState,
|
|
2985
|
+
serializationCapability
|
|
2986
|
+
});
|
|
2987
|
+
}
|
|
2988
|
+
withTransactingDefaults() {
|
|
2989
|
+
return this.withTransacting(makeDefaultTransactingCapability$1);
|
|
2990
|
+
}
|
|
2991
|
+
withTransacting(transactingCapability) {
|
|
2992
|
+
return new V1Builder({
|
|
2993
|
+
...this.#buildState,
|
|
2994
|
+
transactingCapability
|
|
2995
|
+
});
|
|
2996
|
+
}
|
|
2997
|
+
withCoinSelection(coinSelection) {
|
|
2998
|
+
return new V1Builder({
|
|
2999
|
+
...this.#buildState,
|
|
3000
|
+
coinSelection
|
|
3001
|
+
});
|
|
3002
|
+
}
|
|
3003
|
+
withCoinSelectionDefaults() {
|
|
3004
|
+
return this.withCoinSelection(() => chooseCoin$1);
|
|
3005
|
+
}
|
|
3006
|
+
withCoinsAndBalancesDefaults() {
|
|
3007
|
+
return this.withCoinsAndBalances(makeDefaultCoinsAndBalancesCapability$1);
|
|
3008
|
+
}
|
|
3009
|
+
withCoinsAndBalances(coinsAndBalancesCapability) {
|
|
3010
|
+
return new V1Builder({
|
|
3011
|
+
...this.#buildState,
|
|
3012
|
+
coinsAndBalancesCapability
|
|
3013
|
+
});
|
|
3014
|
+
}
|
|
3015
|
+
withTransactionHistoryDefaults() {
|
|
3016
|
+
return this.withTransactionHistory(makeDefaultTransactionHistoryService$1);
|
|
3017
|
+
}
|
|
3018
|
+
withTransactionHistory(transactionHistoryService) {
|
|
3019
|
+
return new V1Builder({
|
|
3020
|
+
...this.#buildState,
|
|
3021
|
+
transactionHistoryService
|
|
3022
|
+
});
|
|
3023
|
+
}
|
|
3024
|
+
withKeysDefaults() {
|
|
3025
|
+
return this.withKeys(makeDefaultKeysCapability$1);
|
|
3026
|
+
}
|
|
3027
|
+
withKeys(keysCapability) {
|
|
3028
|
+
return new V1Builder({
|
|
3029
|
+
...this.#buildState,
|
|
3030
|
+
keysCapability
|
|
3031
|
+
});
|
|
3032
|
+
}
|
|
3033
|
+
/**
|
|
3034
|
+
* Uses the default migration: an empty wallet built from nothing.
|
|
3035
|
+
*
|
|
3036
|
+
* @remarks
|
|
3037
|
+
* This is what an unconfigured builder already does, so calling it changes no behaviour — it states the choice rather
|
|
3038
|
+
* than inheriting it. Registering this variant as the target of a real fork means calling
|
|
3039
|
+
* {@link V1Builder.withMigration} with {@link makeCrossLedgerMigration} instead.
|
|
3040
|
+
*
|
|
3041
|
+
* The parameters the empty dust state is valued against come from the builder configuration when it names them, and
|
|
3042
|
+
* from the ledger's initial parameters when it does not.
|
|
3043
|
+
*/
|
|
3044
|
+
withMigrationDefaults() {
|
|
3045
|
+
return this.withMigration((configuration) => makeEmptyWalletMigration$1(emptyWalletMigrationConfiguration$1(configuration)));
|
|
3046
|
+
}
|
|
3047
|
+
/**
|
|
3048
|
+
* Chooses how this variant produces its first state from the state that preceded it.
|
|
3049
|
+
*
|
|
3050
|
+
* @remarks
|
|
3051
|
+
* The strategy's input type becomes the variant's `TPreviousState`, which is what the runtime type-checks a
|
|
3052
|
+
* registration against: a variant declaring it migrates from a ledger-v8 dust wallet cannot be registered after one
|
|
3053
|
+
* that produces something else.
|
|
3054
|
+
*
|
|
3055
|
+
* The context the factory reads is a type parameter of the method, exactly as it is for every other capability here,
|
|
3056
|
+
* rather than the builder's own `TContext`. Naming `TContext` in an argument position would make the builder
|
|
3057
|
+
* invariant in it, and a chain that has not yet configured every capability — which is how the simulator-backed
|
|
3058
|
+
* variants are assembled — could then no longer be handed to {@link V1Builder.build}.
|
|
3059
|
+
* @example
|
|
3060
|
+
* ```typescript
|
|
3061
|
+
* const forkTarget = new V1Builder().withDefaults().withMigration(makeCrossLedgerMigration);
|
|
3062
|
+
* ```;
|
|
3063
|
+
*
|
|
3064
|
+
* @param migration Builds the migration from the configuration and the sibling capabilities.
|
|
3065
|
+
*/
|
|
3066
|
+
withMigration(migration) {
|
|
3067
|
+
const capabilities = this.#buildState;
|
|
3068
|
+
return new V1Builder({
|
|
3069
|
+
...capabilities,
|
|
3070
|
+
migration
|
|
3071
|
+
});
|
|
3072
|
+
}
|
|
3073
|
+
build(configuration) {
|
|
3074
|
+
const v1Context = this.#buildContextFromBuildState(configuration);
|
|
3075
|
+
const migration = this.#resolveMigration(configuration, () => v1Context);
|
|
3076
|
+
return {
|
|
3077
|
+
__polyTag__: V1Tag,
|
|
3078
|
+
coinsAndBalances: v1Context.coinsAndBalancesCapability,
|
|
3079
|
+
keys: v1Context.keysCapability,
|
|
3080
|
+
serialization: v1Context.serializationCapability,
|
|
3081
|
+
transactionHistory: v1Context.transactionHistoryService,
|
|
3082
|
+
startAux: this.#resolveStartAux(),
|
|
3083
|
+
start(context) {
|
|
3084
|
+
return require_dist.gen(function* () {
|
|
3085
|
+
return new RunningV1Variant(yield* require_dist.Scope, context, v1Context);
|
|
3086
|
+
});
|
|
3087
|
+
},
|
|
3088
|
+
migrateState: (previousState) => migration.migrate(previousState).pipe(require_dist.mapError$2((error) => new require_dist.WalletRuntimeError({
|
|
3089
|
+
message: "Failed to migrate dust wallet state into this variant",
|
|
3090
|
+
cause: error
|
|
3091
|
+
}))),
|
|
3092
|
+
deserializeState: (serialized) => {
|
|
3093
|
+
return v1Context.serializationCapability.deserialize(null, serialized);
|
|
3094
|
+
}
|
|
3095
|
+
};
|
|
3096
|
+
}
|
|
3097
|
+
/**
|
|
3098
|
+
* Uses the default derivation: this ledger version's own dust secret key, built from the seed.
|
|
3099
|
+
*
|
|
3100
|
+
* @remarks
|
|
3101
|
+
* Constrained to a builder whose sync is started with a `DustSecretKey`, because that is the only start-aux this
|
|
3102
|
+
* derivation can produce. A builder whose sync expects something else has to say how that is derived, or say
|
|
3103
|
+
* nothing and be refused at `build`.
|
|
3104
|
+
* @returns A builder that produces a variant able to start sync from a seed alone.
|
|
3105
|
+
*/
|
|
3106
|
+
withStartAuxDefaults() {
|
|
3107
|
+
return this.withStartAux({ fromSeed: (seed) => _midnight_ntwrk_ledger_v8.DustSecretKey.fromSeed(seed) });
|
|
3108
|
+
}
|
|
3109
|
+
/**
|
|
3110
|
+
* Chooses how this variant derives the key material its synchronization is started with from a seed.
|
|
3111
|
+
*
|
|
3112
|
+
* @param startAux The derivation.
|
|
3113
|
+
* @returns A builder that produces a variant able to start sync from a seed alone.
|
|
3114
|
+
*/
|
|
3115
|
+
withStartAux(startAux) {
|
|
3116
|
+
return new V1Builder({
|
|
3117
|
+
...this.#buildState,
|
|
3118
|
+
startAux
|
|
3119
|
+
});
|
|
3120
|
+
}
|
|
3121
|
+
/**
|
|
3122
|
+
* Resolves the configured derivation, refusing a builder that never stated one.
|
|
3123
|
+
*
|
|
3124
|
+
* @remarks
|
|
3125
|
+
* Kept out of the structural completeness check because it is typed rather than merely present: a builder whose sync
|
|
3126
|
+
* expects one kind of key material and whose derivation produces another is a wallet that would be silently handed
|
|
3127
|
+
* key objects of the wrong shape at the first migration.
|
|
3128
|
+
*/
|
|
3129
|
+
#resolveStartAux() {
|
|
3130
|
+
const configured = this.#buildState.startAux;
|
|
3131
|
+
if (configured === void 0) throw new Error("Not all components are configured in V1Builder: startAux");
|
|
3132
|
+
return configured;
|
|
3133
|
+
}
|
|
3134
|
+
/**
|
|
3135
|
+
* Resolves the configured migration, or the empty-wallet fallback when none was configured.
|
|
3136
|
+
*
|
|
3137
|
+
* @remarks
|
|
3138
|
+
* The fallback is written as a nullary function on purpose. It ignores whatever preceded it — it builds an empty
|
|
3139
|
+
* wallet from nothing — which makes it a valid migration from _any_ previous state, but a `StateMigration<null>`
|
|
3140
|
+
* value could only be widened to `StateMigration<TPreviousState>` through a cast. Declaring no parameter says the
|
|
3141
|
+
* same thing to the type system without one.
|
|
3142
|
+
*/
|
|
3143
|
+
#resolveMigration(configuration, getContext) {
|
|
3144
|
+
const configured = this.#buildState.migration;
|
|
3145
|
+
return configured === void 0 ? { migrate: () => makeEmptyWalletMigration$1(emptyWalletMigrationConfiguration$1(configuration)).migrate(null) } : configured(configuration, getContext);
|
|
3146
|
+
}
|
|
3147
|
+
#buildContextFromBuildState(configuration) {
|
|
3148
|
+
if (!isBuildStateFull$1(this.#buildState)) throw new Error("Not all components are configured in V1 Builder");
|
|
3149
|
+
const { syncCapability, syncService, transactingCapability, serializationCapability, coinSelection, coinsAndBalancesCapability, keysCapability, transactionHistoryService } = this.#buildState;
|
|
3150
|
+
const getContext = () => context;
|
|
3151
|
+
const context = {
|
|
3152
|
+
serializationCapability: serializationCapability(configuration, getContext),
|
|
3153
|
+
syncCapability: syncCapability(configuration, getContext),
|
|
3154
|
+
syncService: syncService(configuration, getContext),
|
|
3155
|
+
transactingCapability: transactingCapability(configuration, getContext),
|
|
3156
|
+
coinsAndBalancesCapability: coinsAndBalancesCapability(configuration, getContext),
|
|
3157
|
+
keysCapability: keysCapability(configuration, getContext),
|
|
3158
|
+
coinSelection: coinSelection(configuration, getContext),
|
|
3159
|
+
transactionHistoryService: transactionHistoryService(configuration, getContext)
|
|
3160
|
+
};
|
|
3161
|
+
return context;
|
|
3162
|
+
}
|
|
3163
|
+
};
|
|
3164
|
+
const isBuildStateFull$1 = (buildState) => {
|
|
3165
|
+
return [
|
|
3166
|
+
"syncService",
|
|
3167
|
+
"syncCapability",
|
|
3168
|
+
"transactingCapability",
|
|
3169
|
+
"coinSelection",
|
|
3170
|
+
"serializationCapability",
|
|
3171
|
+
"coinsAndBalancesCapability",
|
|
3172
|
+
"keysCapability",
|
|
3173
|
+
"transactionHistoryService"
|
|
3174
|
+
].every((key) => typeof buildState[key] == "function");
|
|
3175
|
+
};
|
|
3176
|
+
//#endregion
|
|
3177
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/Keys.js
|
|
3178
|
+
const makeDefaultKeysCapability = () => {
|
|
3179
|
+
return {
|
|
3180
|
+
getPublicKey: (state) => {
|
|
3181
|
+
return state.publicKey.publicKey;
|
|
3182
|
+
},
|
|
3183
|
+
getAddress: (state) => {
|
|
3184
|
+
return new require_dist.DustAddress(state.publicKey.publicKey);
|
|
3185
|
+
}
|
|
3186
|
+
};
|
|
3187
|
+
};
|
|
3188
|
+
//#endregion
|
|
3189
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/Migration.js
|
|
3190
|
+
/**
|
|
3191
|
+
* The migration used when there is no previous wallet at all.
|
|
3192
|
+
*
|
|
3193
|
+
* @remarks
|
|
3194
|
+
* It backs `WalletLike.startEmpty`, which builds a wallet before any key material exists. The resulting state holds no
|
|
3195
|
+
* dust and has a public key derived from a fixed placeholder seed; it is a scaffold to be replaced by a real start,
|
|
3196
|
+
* not a wallet anybody can pay fees with.
|
|
3197
|
+
* @example
|
|
3198
|
+
* ```typescript
|
|
3199
|
+
* const builder = new V2Builder().withDefaults().withMigration(makeEmptyWalletMigration({ networkId, dustParameters }));
|
|
3200
|
+
* ```;
|
|
3201
|
+
*
|
|
3202
|
+
* @param configuration Supplies the network the scaffold state claims to be on, and the dust parameters it uses.
|
|
3203
|
+
* @returns A migration from `null`.
|
|
3204
|
+
*/
|
|
3205
|
+
const makeEmptyWalletMigration = (configuration) => ({ migrate: () => {
|
|
3206
|
+
const seed = require_dist.fromString("0000000000000000000000000000000000000000000000000000000000000001");
|
|
3207
|
+
return require_dist.succeed(CoreWallet$1.initEmpty(configuration.dustParameters, _midnightntwrk_ledger_v9.DustSecretKey.fromSeed(seed), configuration.networkId));
|
|
3208
|
+
} });
|
|
3209
|
+
/**
|
|
3210
|
+
* The migration across a ledger-version boundary: a dustless state of this version, carrying identity and position.
|
|
3211
|
+
*
|
|
3212
|
+
* @remarks
|
|
3213
|
+
* The indexer replays the timeline after the hard fork, re-emitting the wallet's history as events of ledger-v9
|
|
3214
|
+
* version. A migrated wallet therefore does not need — and must not attempt — to carry its dust: exactly the same
|
|
3215
|
+
* dust is generated again by ordinary sync, from the replayed registration events, and valued against this version's
|
|
3216
|
+
* parameters. Carrying it across as well would double-count what the replay is about to deliver, on top of requiring
|
|
3217
|
+
* generation and commitment trees that this ledger's WASM module cannot read.
|
|
3218
|
+
*
|
|
3219
|
+
* So what crosses is the dust public key, the network, the protocol version that triggered the hand-over, and the
|
|
3220
|
+
* cursor. Sync progress is **parked at the fork** rather than rewound: the indexer numbers the replayed events
|
|
3221
|
+
* onwards from whatever id it had reached when the fork happened, never from zero, so the inherited cursor is exactly
|
|
3222
|
+
* where the replay begins. A wallet that rewound to zero would wait on a stretch of the timeline this ledger
|
|
3223
|
+
* version's events do not occupy.
|
|
3224
|
+
*
|
|
3225
|
+
* If the ledger team ships a byte-level translation for wallet local state, it replaces this instance without touching
|
|
3226
|
+
* anything around it — that is the point of the {@link StateMigration} seam.
|
|
3227
|
+
* @param configuration Supplies this ledger version's dust parameters for the fresh state.
|
|
3228
|
+
* @returns A migration from a previous-ledger-version wallet.
|
|
3229
|
+
*/
|
|
3230
|
+
const makeCrossLedgerMigration = (configuration) => ({ migrate: (previousState) => require_dist.succeed(CoreWallet$1.fromPreviousVersion({
|
|
3231
|
+
publicKey: { publicKey: previousState.publicKey.publicKey },
|
|
3232
|
+
networkId: previousState.networkId,
|
|
3233
|
+
protocolVersion: previousState.protocolVersion,
|
|
3234
|
+
progress: previousState.progress,
|
|
3235
|
+
dustParameters: configuration.dustParameters
|
|
3236
|
+
})) });
|
|
3237
|
+
//#endregion
|
|
3238
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/Transacting.js
|
|
3239
|
+
const makeDefaultTransactingCapability = (config, getContext) => {
|
|
3240
|
+
return new TransactingCapabilityImplementation(config.networkId, config.costParameters, () => getContext().coinSelection, () => getContext().coinsAndBalancesCapability, () => getContext().keysCapability);
|
|
3241
|
+
};
|
|
3242
|
+
/**
|
|
3243
|
+
* Distributes the fee across multiple inputs, draining smaller inputs first when the fee exceeds any single input's
|
|
3244
|
+
* value. Finds the next available intent segment id in a transaction.
|
|
3245
|
+
*
|
|
3246
|
+
* Fallible intent segments occupy the range `[1, 65535]`; segment `0` is reserved for the guaranteed section and is
|
|
3247
|
+
* never returned.
|
|
3248
|
+
*
|
|
3249
|
+
* @param transaction - Transaction whose intent map is inspected.
|
|
3250
|
+
* @returns `Some(segmentId)` with the lowest unused id, or `None` if all 65535 fallible segments are taken.
|
|
3251
|
+
*/
|
|
3252
|
+
const findAvailableSegmentId = (transaction) => {
|
|
3253
|
+
const used = new Set(transaction.intents?.keys() ?? []);
|
|
3254
|
+
return require_dist.pipe(require_dist.range(1, 65535), require_dist.findFirst$1((segmentId) => !used.has(segmentId)));
|
|
3255
|
+
};
|
|
3256
|
+
/**
|
|
3257
|
+
* Distributes the fee across multiple inputs, draining smaller inputs first when the fee exceeds any single input's
|
|
3258
|
+
* value.
|
|
3259
|
+
*/
|
|
3260
|
+
const distributeFeeAcrossInputs = (inputs, fee) => inputs.reduce(({ result, remaining }, input) => {
|
|
3261
|
+
const deduction = remaining >= input.value ? input.value : remaining;
|
|
3262
|
+
return {
|
|
3263
|
+
result: [...result, {
|
|
3264
|
+
...input,
|
|
3265
|
+
value: deduction
|
|
3266
|
+
}],
|
|
3267
|
+
remaining: remaining - deduction
|
|
3268
|
+
};
|
|
3269
|
+
}, {
|
|
3270
|
+
result: [],
|
|
3271
|
+
remaining: fee
|
|
3272
|
+
}).result;
|
|
3273
|
+
var TransactingCapabilityImplementation = class TransactingCapabilityImplementation {
|
|
3274
|
+
networkId;
|
|
3275
|
+
costParams;
|
|
3276
|
+
getCoinSelection;
|
|
3277
|
+
getCoins;
|
|
3278
|
+
getKeys;
|
|
3279
|
+
constructor(networkId, costParams, getCoinSelection, getCoins, getKeys) {
|
|
3280
|
+
this.getCoins = getCoins;
|
|
3281
|
+
this.networkId = networkId;
|
|
3282
|
+
this.costParams = costParams;
|
|
3283
|
+
this.getCoinSelection = getCoinSelection;
|
|
3284
|
+
this.getKeys = getKeys;
|
|
3285
|
+
}
|
|
3286
|
+
createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress) {
|
|
3287
|
+
const makeOffer = (utxos) => {
|
|
3288
|
+
if (utxos.length === 0) return require_dist.none();
|
|
3289
|
+
const totalValue = require_dist.pipe(utxos, require_dist.map$4((coin) => coin.utxo.value), require_dist.sumAll);
|
|
3290
|
+
const inputs = utxos.map(({ utxo }) => ({
|
|
3291
|
+
...utxo,
|
|
3292
|
+
owner: nightVerifyingKey
|
|
3293
|
+
}));
|
|
3294
|
+
const output = {
|
|
3295
|
+
owner: (0, _midnightntwrk_ledger_v9.addressFromKey)(nightVerifyingKey),
|
|
3296
|
+
type: require_dist.Token.night,
|
|
3297
|
+
value: totalValue
|
|
3298
|
+
};
|
|
3299
|
+
return require_dist.some(_midnightntwrk_ledger_v9.UnshieldedOffer.new(inputs, [output], []));
|
|
3300
|
+
};
|
|
3301
|
+
return require_dist.gen$1(this, function* () {
|
|
3302
|
+
const receiver = dustReceiverAddress ? dustReceiverAddress.data : void 0;
|
|
3303
|
+
return yield* require_dist.ledgerTry(() => {
|
|
3304
|
+
const network = this.networkId;
|
|
3305
|
+
const splitResult = this.getCoins().splitNightUtxos(nightUtxos);
|
|
3306
|
+
const feePayment = receiver ? require_dist.pipe(splitResult.guaranteed, require_dist.filter$2((coin) => !coin.utxo.registeredForDustGeneration), require_dist.map$4((coin) => coin.dust.generatedNow), require_dist.sumAll) : 0n;
|
|
3307
|
+
const maybeGuaranteedOffer = makeOffer(splitResult.guaranteed);
|
|
3308
|
+
const maybeFallibleOffer = makeOffer(splitResult.fallible);
|
|
3309
|
+
const dustRegistration = new _midnightntwrk_ledger_v9.DustRegistration(SignatureMarker$1.signature, nightVerifyingKey, receiver, feePayment);
|
|
3310
|
+
const dustActions = new _midnightntwrk_ledger_v9.DustActions(SignatureMarker$1.signature, ProofMarker$1.preProof, currentTime, [], [dustRegistration]);
|
|
3311
|
+
const intent = require_dist.pipe(_midnightntwrk_ledger_v9.Intent.new(ttl), (intent) => require_dist.match$1(maybeGuaranteedOffer, {
|
|
3312
|
+
onNone: () => intent,
|
|
3313
|
+
onSome: (guaranteedOffer) => {
|
|
3314
|
+
intent.guaranteedUnshieldedOffer = guaranteedOffer;
|
|
3315
|
+
return intent;
|
|
3316
|
+
}
|
|
3317
|
+
}), (intent) => require_dist.match$1(maybeFallibleOffer, {
|
|
3318
|
+
onNone: () => intent,
|
|
3319
|
+
onSome: (fallibleOffer) => {
|
|
3320
|
+
intent.fallibleUnshieldedOffer = fallibleOffer;
|
|
3321
|
+
return intent;
|
|
3322
|
+
}
|
|
3323
|
+
}), (intent) => {
|
|
3324
|
+
intent.dustActions = dustActions;
|
|
3325
|
+
return intent;
|
|
3326
|
+
});
|
|
3327
|
+
return _midnightntwrk_ledger_v9.Transaction.fromParts(network, void 0, void 0, intent);
|
|
3328
|
+
});
|
|
3329
|
+
});
|
|
3330
|
+
}
|
|
3331
|
+
splitNightUtxosForDustRegistration(utxosWithDustValue, isRegistration) {
|
|
3332
|
+
const splitResult = this.getCoins().splitNightUtxos(utxosWithDustValue);
|
|
3333
|
+
const feePayment = isRegistration ? require_dist.pipe(splitResult.guaranteed, require_dist.filter$2((coin) => !coin.utxo.registeredForDustGeneration), require_dist.map$4((coin) => coin.dust.generatedNow), require_dist.sumAll) : 0n;
|
|
3334
|
+
return {
|
|
3335
|
+
guaranteedUtxos: splitResult.guaranteed,
|
|
3336
|
+
fallibleUtxos: splitResult.fallible,
|
|
3337
|
+
feePayment
|
|
3338
|
+
};
|
|
3339
|
+
}
|
|
3340
|
+
attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
3341
|
+
return require_dist.gen$1(this, function* () {
|
|
3342
|
+
const intent = transaction.intents?.get(1);
|
|
3343
|
+
if (!intent) return yield* require_dist.left(new TransactingError$1({ message: "No intent found at segment 1; expected an intent built by rotateUtxos" }));
|
|
3344
|
+
if (intent.dustActions !== void 0 && intent.dustActions.registrations.length > 0) return yield* require_dist.left(new TransactingError$1({ message: "Intent at segment 1 already has a dust registration attached" }));
|
|
3345
|
+
return yield* require_dist.ledgerTry(() => {
|
|
3346
|
+
const receiver = dustReceiverAddress ? dustReceiverAddress.data : void 0;
|
|
3347
|
+
const dustRegistration = new _midnightntwrk_ledger_v9.DustRegistration(SignatureMarker$1.signature, nightVerifyingKey, receiver, feePayment);
|
|
3348
|
+
const dustActions = new _midnightntwrk_ledger_v9.DustActions(SignatureMarker$1.signature, ProofMarker$1.preProof, currentTime, [], [dustRegistration]);
|
|
3349
|
+
const newIntent = _midnightntwrk_ledger_v9.Intent.deserialize(SignatureMarker$1.signature, ProofMarker$1.preProof, BindingMarker$1.preBinding, intent.serialize());
|
|
3350
|
+
newIntent.dustActions = dustActions;
|
|
3351
|
+
const newTransaction = _midnightntwrk_ledger_v9.Transaction.deserialize(SignatureMarker$1.signature, ProofMarker$1.preProof, BindingMarker$1.preBinding, transaction.serialize());
|
|
3352
|
+
newTransaction.intents = newTransaction.intents.set(1, newIntent);
|
|
3353
|
+
return newTransaction;
|
|
3354
|
+
});
|
|
3355
|
+
});
|
|
3356
|
+
}
|
|
3357
|
+
addDustRegistrationSignature(transaction, signatureData) {
|
|
3358
|
+
return require_dist.gen$1(this, function* () {
|
|
3359
|
+
const intent = transaction.intents?.get(1);
|
|
3360
|
+
if (!intent) return yield* require_dist.left(new TransactingError$1({ message: "No intent found in the transaction intents with segment = 1" }));
|
|
3361
|
+
const { dustActions } = intent;
|
|
3362
|
+
if (!dustActions) return yield* require_dist.left(new TransactingError$1({ message: "No dustActions found in intent" }));
|
|
3363
|
+
const [registration, ...restRegistrations] = dustActions.registrations;
|
|
3364
|
+
if (!registration) return yield* require_dist.left(new TransactingError$1({ message: "No registrations found in dustActions" }));
|
|
3365
|
+
return yield* require_dist.ledgerTry(() => {
|
|
3366
|
+
const signature = new _midnightntwrk_ledger_v9.SignatureEnabled(signatureData);
|
|
3367
|
+
const registrationWithSignature = new _midnightntwrk_ledger_v9.DustRegistration(signature.instance, registration.nightKey, registration.dustAddress, registration.allowFeePayment, signature);
|
|
3368
|
+
const newDustActions = new _midnightntwrk_ledger_v9.DustActions(signature.instance, ProofMarker$1.preProof, dustActions.ctime, dustActions.spends, [registrationWithSignature, ...restRegistrations]);
|
|
3369
|
+
const newIntent = _midnightntwrk_ledger_v9.Intent.deserialize(signature.instance, ProofMarker$1.preProof, BindingMarker$1.preBinding, intent.serialize());
|
|
3370
|
+
newIntent.dustActions = newDustActions;
|
|
3371
|
+
const newTransaction = _midnightntwrk_ledger_v9.Transaction.deserialize(signature.instance, ProofMarker$1.preProof, BindingMarker$1.preBinding, transaction.serialize());
|
|
3372
|
+
newTransaction.intents = newTransaction.intents.set(1, newIntent);
|
|
3373
|
+
return newTransaction;
|
|
3374
|
+
});
|
|
3375
|
+
});
|
|
3376
|
+
}
|
|
3377
|
+
addDustGenerationSignature(transaction, signatureData) {
|
|
3378
|
+
return require_dist.gen$1(this, function* () {
|
|
3379
|
+
const intent = transaction.intents?.get(1);
|
|
3380
|
+
if (!intent) return yield* require_dist.left(new TransactingError$1({ message: "No intent found in the transaction intents with segment = 1" }));
|
|
3381
|
+
const { dustActions, guaranteedUnshieldedOffer, fallibleUnshieldedOffer } = intent;
|
|
3382
|
+
if (!dustActions) return yield* require_dist.left(new TransactingError$1({ message: "No dustActions found in intent" }));
|
|
3383
|
+
if (!guaranteedUnshieldedOffer) return yield* require_dist.left(new TransactingError$1({ message: "No guaranteedUnshieldedOffer found in intent" }));
|
|
3384
|
+
const [registration, ...restRegistrations] = dustActions.registrations;
|
|
3385
|
+
if (!registration) return yield* require_dist.left(new TransactingError$1({ message: "No registrations found in dustActions" }));
|
|
3386
|
+
return yield* require_dist.ledgerTry(() => {
|
|
3387
|
+
const signature = new _midnightntwrk_ledger_v9.SignatureEnabled(signatureData);
|
|
3388
|
+
const registrationWithSignature = new _midnightntwrk_ledger_v9.DustRegistration(signature.instance, registration.nightKey, registration.dustAddress, registration.allowFeePayment, signature);
|
|
3389
|
+
const newDustActions = new _midnightntwrk_ledger_v9.DustActions(signature.instance, ProofMarker$1.preProof, dustActions.ctime, dustActions.spends, [registrationWithSignature, ...restRegistrations]);
|
|
3390
|
+
const newIntent = _midnightntwrk_ledger_v9.Intent.deserialize(signature.instance, ProofMarker$1.preProof, BindingMarker$1.preBinding, intent.serialize());
|
|
3391
|
+
newIntent.dustActions = newDustActions;
|
|
3392
|
+
const guaranteedSignatures = Array.from({ length: guaranteedUnshieldedOffer.inputs.length }, (_, i) => guaranteedUnshieldedOffer.signatures.at(i) ?? signature);
|
|
3393
|
+
newIntent.guaranteedUnshieldedOffer = guaranteedUnshieldedOffer.addSignatures(guaranteedSignatures);
|
|
3394
|
+
if (fallibleUnshieldedOffer) {
|
|
3395
|
+
const fallibleSignatures = Array.from({ length: fallibleUnshieldedOffer.inputs.length }, (_, i) => fallibleUnshieldedOffer.signatures.at(i) ?? signature);
|
|
3396
|
+
newIntent.fallibleUnshieldedOffer = fallibleUnshieldedOffer.addSignatures(fallibleSignatures);
|
|
3397
|
+
}
|
|
3398
|
+
const newTransaction = _midnightntwrk_ledger_v9.Transaction.deserialize(signature.instance, ProofMarker$1.preProof, BindingMarker$1.preBinding, transaction.serialize());
|
|
3399
|
+
newTransaction.intents = newTransaction.intents.set(1, newIntent);
|
|
3400
|
+
return newTransaction;
|
|
3401
|
+
});
|
|
3402
|
+
});
|
|
3403
|
+
}
|
|
3404
|
+
calculateFee(transaction, ledgerParams) {
|
|
3405
|
+
return transaction.feesWithMargin(ledgerParams, this.costParams.feeBlocksMargin) + (this.costParams.additionalFeeOverhead ?? 0n);
|
|
3406
|
+
}
|
|
3407
|
+
dryRunFee(recipeInputs, transactions, secretKey, state, ttl, currentTime, ledgerParams) {
|
|
3408
|
+
const network = this.networkId;
|
|
3409
|
+
const [spends] = CoreWallet$1.spendCoins(state, secretKey, recipeInputs, currentTime);
|
|
3410
|
+
const intent = _midnightntwrk_ledger_v9.Intent.new(ttl);
|
|
3411
|
+
intent.dustActions = new _midnightntwrk_ledger_v9.DustActions(SignatureMarker$1.signature, ProofMarker$1.preProof, currentTime, [...spends], []);
|
|
3412
|
+
const [first, ...rest] = transactions.map((tx) => tx.eraseProofs());
|
|
3413
|
+
const mergedExisting = first ? rest.reduce((acc, tx) => acc.merge(tx), first) : void 0;
|
|
3414
|
+
const segmentId = mergedExisting ? require_dist.getOrElse(findAvailableSegmentId(mergedExisting), () => 1) : 1;
|
|
3415
|
+
const erasedBalancing = _midnightntwrk_ledger_v9.Transaction.fromParts(network).addIntent({
|
|
3416
|
+
tag: "specific",
|
|
3417
|
+
value: segmentId
|
|
3418
|
+
}, intent).eraseProofs();
|
|
3419
|
+
const mergedTx = mergedExisting ? mergedExisting.merge(erasedBalancing) : erasedBalancing;
|
|
3420
|
+
return this.calculateFee(mergedTx, ledgerParams);
|
|
3421
|
+
}
|
|
3422
|
+
static feeImbalance(transaction, totalFee) {
|
|
3423
|
+
const [_, imbalance] = transaction.imbalances(0, totalFee).entries().find(([tt, _]) => tt.tag === "dust") ?? [];
|
|
3424
|
+
return imbalance ?? 0n;
|
|
3425
|
+
}
|
|
3426
|
+
computeBalancingRecipe(secretKey, state, transactions, ttl, currentTime, ledgerParams) {
|
|
3427
|
+
const initialFees = transactions.reduce((total, transaction) => total + TransactingCapabilityImplementation.feeImbalance(transaction, this.calculateFee(transaction, ledgerParams)), 0n);
|
|
3428
|
+
const dust = this.getCoins().getAvailableCoinsWithGeneratedDust(state, currentTime);
|
|
3429
|
+
return require_dist.pipe(require_dist.iterate({
|
|
3430
|
+
currentFee: initialFees,
|
|
3431
|
+
recipeInputs: [],
|
|
3432
|
+
converged: false
|
|
3433
|
+
}, {
|
|
3434
|
+
while: (s) => !s.converged,
|
|
3435
|
+
body: ({ currentFee }) => require_dist.try_({
|
|
3436
|
+
try: () => {
|
|
3437
|
+
const recipeInputs = require_dist.getBalanceRecipe({
|
|
3438
|
+
coins: dust.map((coin) => ({
|
|
3439
|
+
type: "dust",
|
|
3440
|
+
value: coin.value,
|
|
3441
|
+
token: coin.token
|
|
3442
|
+
})),
|
|
3443
|
+
initialImbalances: require_dist.Imbalances.fromEntry("dust", currentFee),
|
|
3444
|
+
feeTokenType: "dust",
|
|
3445
|
+
coinSelection: this.getCoinSelection(),
|
|
3446
|
+
transactionCostModel: {
|
|
3447
|
+
inputFeeOverhead: 0n,
|
|
3448
|
+
outputFeeOverhead: 0n
|
|
3449
|
+
},
|
|
3450
|
+
createOutput: (coin) => coin,
|
|
3451
|
+
isCoinEqual: (a, b) => a.token.nonce === b.token.nonce
|
|
3452
|
+
}).inputs.map(({ token, value }) => ({
|
|
3453
|
+
token,
|
|
3454
|
+
value
|
|
3455
|
+
}));
|
|
3456
|
+
const newFee = this.dryRunFee(recipeInputs, transactions, secretKey, state, ttl, currentTime, ledgerParams);
|
|
3457
|
+
return {
|
|
3458
|
+
currentFee: newFee,
|
|
3459
|
+
recipeInputs,
|
|
3460
|
+
converged: newFee <= recipeInputs.reduce((sum, input) => sum + input.value, 0n)
|
|
3461
|
+
};
|
|
3462
|
+
},
|
|
3463
|
+
catch: (err) => {
|
|
3464
|
+
if (err instanceof require_dist.InsufficientFundsError) return new InsufficientFundsError$1({
|
|
3465
|
+
message: err.message,
|
|
3466
|
+
tokenType: err.tokenType
|
|
3467
|
+
});
|
|
3468
|
+
else return new OtherWalletError$1({
|
|
3469
|
+
message: err instanceof Error ? err.message : "Dust balancing failed",
|
|
3470
|
+
cause: err
|
|
3471
|
+
});
|
|
3472
|
+
}
|
|
3473
|
+
})
|
|
3474
|
+
}), require_dist.either$1, require_dist.runSync, require_dist.map$6(({ currentFee, recipeInputs }) => ({
|
|
3475
|
+
fee: currentFee,
|
|
3476
|
+
recipeInputs: distributeFeeAcrossInputs(recipeInputs, currentFee)
|
|
3477
|
+
})));
|
|
3478
|
+
}
|
|
3479
|
+
estimateFee(secretKey, state, transactions, ttl, currentTime, ledgerParams) {
|
|
3480
|
+
return require_dist.pipe(this.computeBalancingRecipe(secretKey, state, transactions, ttl, currentTime, ledgerParams), require_dist.map$6(({ fee }) => fee));
|
|
3481
|
+
}
|
|
3482
|
+
balanceTransactions(secretKey, state, transactions, ttl, currentTime, ledgerParams) {
|
|
3483
|
+
const networkId = this.networkId;
|
|
3484
|
+
return require_dist.pipe(this.computeBalancingRecipe(secretKey, state, transactions, ttl, currentTime, ledgerParams), require_dist.flatMap$4(({ recipeInputs }) => {
|
|
3485
|
+
return require_dist.ledgerTry(() => {
|
|
3486
|
+
const intent = _midnightntwrk_ledger_v9.Intent.new(ttl);
|
|
3487
|
+
const [spends, updatedState] = CoreWallet$1.spendCoins(state, secretKey, recipeInputs, currentTime);
|
|
3488
|
+
intent.dustActions = new _midnightntwrk_ledger_v9.DustActions(SignatureMarker$1.signature, ProofMarker$1.preProof, currentTime, [...spends], []);
|
|
3489
|
+
const [first, ...rest] = transactions.map((tx) => tx.eraseProofs());
|
|
3490
|
+
const mergedExisting = first ? rest.reduce((acc, tx) => acc.merge(tx), first) : void 0;
|
|
3491
|
+
const segmentId = mergedExisting ? require_dist.getOrElse(findAvailableSegmentId(mergedExisting), () => 1) : 1;
|
|
3492
|
+
return [_midnightntwrk_ledger_v9.Transaction.fromParts(networkId).addIntent({
|
|
3493
|
+
tag: "specific",
|
|
3494
|
+
value: segmentId
|
|
3495
|
+
}, intent), updatedState];
|
|
3496
|
+
});
|
|
3497
|
+
}));
|
|
3498
|
+
}
|
|
3499
|
+
revertTransaction(state, transaction) {
|
|
3500
|
+
return require_dist.try_$1({
|
|
3501
|
+
try: () => CoreWallet$1.revertTransaction(state, transaction),
|
|
3502
|
+
catch: (err) => {
|
|
3503
|
+
return new OtherWalletError$1({
|
|
3504
|
+
message: `Error while reverting transaction ${transaction.identifiers().at(0)}`,
|
|
3505
|
+
cause: err
|
|
3506
|
+
});
|
|
3507
|
+
}
|
|
3508
|
+
});
|
|
3509
|
+
}
|
|
3510
|
+
};
|
|
3511
|
+
//#endregion
|
|
3512
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/TransactionHistory.js
|
|
3513
|
+
const DustUtxoInfoSchema = require_dist.Struct({
|
|
3514
|
+
initialValue: require_dist.BigInt$,
|
|
3515
|
+
nonce: require_dist.BigInt$,
|
|
3516
|
+
seq: require_dist.Number$,
|
|
3517
|
+
backingNight: require_dist.String$,
|
|
3518
|
+
mtIndex: require_dist.BigInt$
|
|
3519
|
+
});
|
|
3520
|
+
const DustSectionSchema = require_dist.Struct({
|
|
3521
|
+
receivedUtxos: require_dist.Array$(DustUtxoInfoSchema),
|
|
3522
|
+
spentUtxos: require_dist.Array$(DustUtxoInfoSchema)
|
|
3523
|
+
});
|
|
3524
|
+
require_dist.extendEntrySchema({ dust: require_dist.optional(DustSectionSchema) });
|
|
3525
|
+
const utxoEquals = require_dist.equivalence(DustUtxoInfoSchema);
|
|
3526
|
+
const mergeDustSections = (existing, incoming) => ({
|
|
3527
|
+
receivedUtxos: require_dist.unionWith(existing.receivedUtxos, incoming.receivedUtxos, utxoEquals),
|
|
3528
|
+
spentUtxos: require_dist.unionWith(existing.spentUtxos, incoming.spentUtxos, utxoEquals)
|
|
3529
|
+
});
|
|
3530
|
+
const convertQualifiedDustOutput = (utxo) => ({
|
|
3531
|
+
initialValue: utxo.initialValue,
|
|
3532
|
+
nonce: utxo.nonce,
|
|
3533
|
+
seq: utxo.seq,
|
|
3534
|
+
backingNight: utxo.backingNight,
|
|
3535
|
+
mtIndex: utxo.mtIndex
|
|
3536
|
+
});
|
|
3537
|
+
const convertUpdateToFinalizedInput = (changes, metadata, protocolVersion) => ({
|
|
3538
|
+
hash: changes.source,
|
|
3539
|
+
protocolVersion,
|
|
3540
|
+
status: metadata.status,
|
|
3541
|
+
identifiers: metadata.identifiers,
|
|
3542
|
+
fees: metadata.fees,
|
|
3543
|
+
finalizedBlock: {
|
|
3544
|
+
hash: metadata.block.hash,
|
|
3545
|
+
height: metadata.block.height,
|
|
3546
|
+
timestamp: new Date(metadata.block.timestamp)
|
|
3547
|
+
},
|
|
3548
|
+
dust: {
|
|
3549
|
+
receivedUtxos: changes.receivedUtxos.map(convertQualifiedDustOutput),
|
|
3550
|
+
spentUtxos: changes.spentUtxos.map(convertQualifiedDustOutput)
|
|
3551
|
+
}
|
|
3552
|
+
});
|
|
3553
|
+
const gotFinalizedDust = (txHistoryStorage, input) => require_dist.tryPromise({
|
|
3554
|
+
try: () => txHistoryStorage.gotFinalized(input),
|
|
3555
|
+
catch: (e) => new TransactionHistoryError$1({
|
|
3556
|
+
message: `Failed to record finalized history entry for ${input.hash}`,
|
|
3557
|
+
cause: e
|
|
3558
|
+
})
|
|
3559
|
+
});
|
|
3560
|
+
const makeDefaultTransactionHistoryService = (config, _getContext) => {
|
|
3561
|
+
const txHistoryStorage = config.txHistoryStorage;
|
|
3562
|
+
const queryClientLayer = require_dist.layer$1({ url: config.indexerClientConnection.indexerHttpUrl });
|
|
3563
|
+
const retryWindow = config.transactionDetailsRetryWindow ?? require_dist.minutes(2);
|
|
3564
|
+
return {
|
|
3565
|
+
put: (changes, metadata, protocolVersion) => gotFinalizedDust(txHistoryStorage, convertUpdateToFinalizedInput(changes, metadata, protocolVersion)),
|
|
3566
|
+
getTransactionDetails: (hash) => require_dist.gen(function* () {
|
|
3567
|
+
const result = yield* (yield* require_dist.TransactionHistoryDetail)({ transactionHash: hash });
|
|
3568
|
+
const tx = yield* require_dist.head$1(result.transactions).pipe(require_dist.orElseFail(() => new TransactionHistoryError$1({ message: `Indexer has not yet indexed transaction ${hash}` })));
|
|
3569
|
+
const rawStatus = tx.__typename === "RegularTransaction" ? tx.transactionResult.status : void 0;
|
|
3570
|
+
const status = rawStatus === "FAILURE" || rawStatus === "PARTIAL_SUCCESS" ? rawStatus : "SUCCESS";
|
|
3571
|
+
const identifiers = tx.__typename === "RegularTransaction" ? tx.identifiers : [];
|
|
3572
|
+
const fees = tx.__typename === "RegularTransaction" ? BigInt(tx.fees.paidFees) : null;
|
|
3573
|
+
return {
|
|
3574
|
+
hash: tx.hash,
|
|
3575
|
+
block: {
|
|
3576
|
+
hash: tx.block.hash,
|
|
3577
|
+
height: tx.block.height,
|
|
3578
|
+
timestamp: tx.block.timestamp
|
|
3579
|
+
},
|
|
3580
|
+
status,
|
|
3581
|
+
identifiers,
|
|
3582
|
+
fees
|
|
3583
|
+
};
|
|
3584
|
+
}).pipe(require_dist.provide(queryClientLayer), require_dist.scoped, require_dist.retry$1({
|
|
3585
|
+
schedule: require_dist.exponential(require_dist.seconds(1)).pipe(require_dist.either(require_dist.spaced(require_dist.seconds(10))), require_dist.jittered, require_dist.upTo(retryWindow)),
|
|
3586
|
+
while: (error) => error instanceof TransactionHistoryError$1
|
|
3587
|
+
}), require_dist.mapError$2((error) => error instanceof TransactionHistoryError$1 ? error : new TransactionHistoryError$1({
|
|
3588
|
+
message: `Failed to fetch transaction metadata for ${hash}`,
|
|
3589
|
+
cause: error
|
|
3590
|
+
})))
|
|
3591
|
+
};
|
|
3592
|
+
};
|
|
3593
|
+
//#endregion
|
|
3594
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/CoinsAndBalances.js
|
|
3595
|
+
const chooseCoin = (coins) => coins.filter((coin) => coin.value > 0n).toSorted((a, b) => Number(a.value - b.value)).at(0);
|
|
3596
|
+
const FAKE_NONCE = "0".repeat(64);
|
|
3597
|
+
const makeDefaultCoinsAndBalancesCapability = (_config, getContext) => {
|
|
3598
|
+
const getWalletBalance = (state, time) => {
|
|
3599
|
+
return state.state.walletBalance(time);
|
|
3600
|
+
};
|
|
3601
|
+
const getGenerationInfo = (state, coin) => {
|
|
3602
|
+
const info = state.state.generationInfo(coin);
|
|
3603
|
+
return info && info.dtime ? {
|
|
3604
|
+
...info,
|
|
3605
|
+
dtime: /* @__PURE__ */ new Date(+info.dtime)
|
|
3606
|
+
} : info;
|
|
3607
|
+
};
|
|
3608
|
+
const resolveTime = (state, time) => time ?? state.state.syncTime;
|
|
3609
|
+
const toFullInfo = (state, coins, time) => coins.flatMap((coin) => {
|
|
3610
|
+
const genInfo = getGenerationInfo(state, coin);
|
|
3611
|
+
return genInfo ? [{
|
|
3612
|
+
token: coin,
|
|
3613
|
+
...getFullDustInfo(state.state.params, genInfo, coin, time)
|
|
3614
|
+
}] : [];
|
|
3615
|
+
});
|
|
3616
|
+
const availableDustTokens = (state) => {
|
|
3617
|
+
const pendingSpends = new Set([...state.pendingDust.values()].map((coin) => coin.nonce));
|
|
3618
|
+
return require_dist.pipe(state.state.utxos, require_dist.filter$1((coin) => !pendingSpends.has(coin.nonce)));
|
|
3619
|
+
};
|
|
3620
|
+
const getAvailableCoins = (state, time) => toFullInfo(state, availableDustTokens(state), resolveTime(state, time));
|
|
3621
|
+
const getPendingCoins = (state, time) => toFullInfo(state, state.pendingDust, resolveTime(state, time));
|
|
3622
|
+
const getTotalCoins = (state, time) => {
|
|
3623
|
+
const effectiveTime = resolveTime(state, time);
|
|
3624
|
+
return [...getAvailableCoins(state, effectiveTime), ...getPendingCoins(state, effectiveTime)];
|
|
3625
|
+
};
|
|
3626
|
+
const getAvailableCoinsWithGeneratedDust = (state, currentTime) => getAvailableCoins(state, currentTime).map((info) => ({
|
|
3627
|
+
token: info.token,
|
|
3628
|
+
value: info.generatedNow
|
|
3629
|
+
}));
|
|
3630
|
+
const getFullDustInfo = (parameters, genInfo, coin, currentTime) => {
|
|
3631
|
+
const generatedValue = _midnightntwrk_ledger_v9.updatedValue(coin.ctime, coin.initialValue, genInfo, currentTime, parameters);
|
|
3632
|
+
return {
|
|
3633
|
+
dtime: genInfo.dtime,
|
|
3634
|
+
maxCap: genInfo.value * parameters.nightDustRatio,
|
|
3635
|
+
maxCapReachedAt: require_dist.addSeconds(coin.ctime, parameters.timeToCapSeconds),
|
|
3636
|
+
generatedNow: generatedValue,
|
|
3637
|
+
rate: genInfo.value * parameters.generationDecayRate
|
|
3638
|
+
};
|
|
3639
|
+
};
|
|
3640
|
+
const estimateDustGeneration = (state, nightUtxos, currentTime) => {
|
|
3641
|
+
const dustPublicKey = getContext().keysCapability.getPublicKey(state);
|
|
3642
|
+
return require_dist.pipe(nightUtxos, require_dist.map$3((utxo) => {
|
|
3643
|
+
const genInfo = fakeGenerationInfo(utxo, dustPublicKey);
|
|
3644
|
+
const fakeDustCoin = fakeDustToken(dustPublicKey, utxo);
|
|
3645
|
+
return {
|
|
3646
|
+
utxo,
|
|
3647
|
+
dust: getFullDustInfo(state.state.params, genInfo, fakeDustCoin, currentTime)
|
|
3648
|
+
};
|
|
3649
|
+
}));
|
|
3650
|
+
};
|
|
3651
|
+
/** Create a fake generation info for a given Utxo. It allows to estimate the Dust generation from it */
|
|
3652
|
+
const fakeGenerationInfo = (utxo, dustPublicKey) => {
|
|
3653
|
+
return {
|
|
3654
|
+
value: utxo.value,
|
|
3655
|
+
owner: dustPublicKey,
|
|
3656
|
+
nonce: FAKE_NONCE,
|
|
3657
|
+
dtime: void 0
|
|
3658
|
+
};
|
|
3659
|
+
};
|
|
3660
|
+
/** Create a fake dust coin for a given Utxo. It allows to estimate full details of the Dust generation from it */
|
|
3661
|
+
const fakeDustToken = (dustPublicKey, utxo) => ({
|
|
3662
|
+
initialValue: 0n,
|
|
3663
|
+
owner: dustPublicKey,
|
|
3664
|
+
nonce: 0n,
|
|
3665
|
+
seq: 0,
|
|
3666
|
+
ctime: utxo.ctime,
|
|
3667
|
+
backingNight: "",
|
|
3668
|
+
mtIndex: 0n
|
|
3669
|
+
});
|
|
3670
|
+
const splitNightUtxos = (utxos) => {
|
|
3671
|
+
const [guaranteed, fallible] = require_dist.pipe(utxos, require_dist.sort(require_dist.pipe(require_dist.bigint, require_dist.reverse, require_dist.mapInput((coin) => coin.dust.generatedNow))), require_dist.splitAt(1));
|
|
3672
|
+
return {
|
|
3673
|
+
guaranteed,
|
|
3674
|
+
fallible
|
|
3675
|
+
};
|
|
3676
|
+
};
|
|
3677
|
+
return {
|
|
3678
|
+
getWalletBalance,
|
|
3679
|
+
getAvailableCoins,
|
|
3680
|
+
getPendingCoins,
|
|
3681
|
+
getTotalCoins,
|
|
3682
|
+
getAvailableCoinsWithGeneratedDust,
|
|
3683
|
+
getGenerationInfo,
|
|
3684
|
+
estimateDustGeneration,
|
|
3685
|
+
splitNightUtxos
|
|
3686
|
+
};
|
|
3687
|
+
};
|
|
3688
|
+
//#endregion
|
|
3689
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/v2/V2Builder.js
|
|
3690
|
+
/**
|
|
3691
|
+
* Completes a builder configuration into the one the empty-wallet migration asks for.
|
|
3692
|
+
*
|
|
3693
|
+
* @remarks
|
|
3694
|
+
* The dust parameters are optional on the builder and required on the migration, and this is the single place that gap
|
|
3695
|
+
* is closed, so the fallback the unconfigured `build` takes and the one {@link V2Builder.withMigrationDefaults} states
|
|
3696
|
+
* explicitly cannot drift apart.
|
|
3697
|
+
*/
|
|
3698
|
+
const emptyWalletMigrationConfiguration = (configuration) => ({
|
|
3699
|
+
networkId: configuration.networkId,
|
|
3700
|
+
dustParameters: configuration.dustParameters ?? _midnightntwrk_ledger_v9.LedgerParameters.initialParameters().dust
|
|
3701
|
+
});
|
|
3702
|
+
var V2Builder = class V2Builder {
|
|
3703
|
+
#buildState;
|
|
3704
|
+
constructor(buildState = {}) {
|
|
3705
|
+
this.#buildState = buildState;
|
|
3706
|
+
}
|
|
3707
|
+
withDefaults() {
|
|
3708
|
+
return this.withDefaultTransactionType().withSyncDefaults().withSerializationDefaults().withTransactingDefaults().withCoinsAndBalancesDefaults().withTransactionHistoryDefaults().withKeysDefaults().withStartAuxDefaults().withCoinSelectionDefaults();
|
|
3709
|
+
}
|
|
3710
|
+
withTransactionType() {
|
|
3711
|
+
return new V2Builder({
|
|
3712
|
+
...this.#buildState,
|
|
3713
|
+
transactingCapability: void 0
|
|
3714
|
+
});
|
|
3715
|
+
}
|
|
3716
|
+
withDefaultTransactionType() {
|
|
3717
|
+
return this.withTransactionType();
|
|
3718
|
+
}
|
|
3719
|
+
withSyncDefaults() {
|
|
3720
|
+
return this.withSync(makeDefaultSyncService, makeDefaultSyncCapability);
|
|
3721
|
+
}
|
|
3722
|
+
withSync(syncService, syncCapability) {
|
|
3723
|
+
return new V2Builder({
|
|
3724
|
+
...this.#buildState,
|
|
3725
|
+
syncService,
|
|
3726
|
+
syncCapability,
|
|
3727
|
+
startAux: void 0
|
|
3728
|
+
});
|
|
3729
|
+
}
|
|
3730
|
+
withSerializationDefaults() {
|
|
3731
|
+
return this.withSerialization(makeDefaultV2SerializationCapability);
|
|
3732
|
+
}
|
|
3733
|
+
withSerialization(serializationCapability) {
|
|
3734
|
+
return new V2Builder({
|
|
3735
|
+
...this.#buildState,
|
|
3736
|
+
serializationCapability
|
|
3737
|
+
});
|
|
3738
|
+
}
|
|
3739
|
+
withTransactingDefaults() {
|
|
3740
|
+
return this.withTransacting(makeDefaultTransactingCapability);
|
|
3741
|
+
}
|
|
3742
|
+
withTransacting(transactingCapability) {
|
|
3743
|
+
return new V2Builder({
|
|
3744
|
+
...this.#buildState,
|
|
3745
|
+
transactingCapability
|
|
3746
|
+
});
|
|
3747
|
+
}
|
|
3748
|
+
withCoinSelection(coinSelection) {
|
|
3749
|
+
return new V2Builder({
|
|
3750
|
+
...this.#buildState,
|
|
3751
|
+
coinSelection
|
|
3752
|
+
});
|
|
3753
|
+
}
|
|
3754
|
+
withCoinSelectionDefaults() {
|
|
3755
|
+
return this.withCoinSelection(() => chooseCoin);
|
|
3756
|
+
}
|
|
3757
|
+
withCoinsAndBalancesDefaults() {
|
|
3758
|
+
return this.withCoinsAndBalances(makeDefaultCoinsAndBalancesCapability);
|
|
3759
|
+
}
|
|
3760
|
+
withCoinsAndBalances(coinsAndBalancesCapability) {
|
|
3761
|
+
return new V2Builder({
|
|
3762
|
+
...this.#buildState,
|
|
3763
|
+
coinsAndBalancesCapability
|
|
3764
|
+
});
|
|
3765
|
+
}
|
|
3766
|
+
withTransactionHistoryDefaults() {
|
|
3767
|
+
return this.withTransactionHistory(makeDefaultTransactionHistoryService);
|
|
3768
|
+
}
|
|
3769
|
+
withTransactionHistory(transactionHistoryService) {
|
|
3770
|
+
return new V2Builder({
|
|
3771
|
+
...this.#buildState,
|
|
3772
|
+
transactionHistoryService
|
|
3773
|
+
});
|
|
3774
|
+
}
|
|
3775
|
+
withKeysDefaults() {
|
|
3776
|
+
return this.withKeys(makeDefaultKeysCapability);
|
|
3777
|
+
}
|
|
3778
|
+
withKeys(keysCapability) {
|
|
3779
|
+
return new V2Builder({
|
|
3780
|
+
...this.#buildState,
|
|
3781
|
+
keysCapability
|
|
3782
|
+
});
|
|
3783
|
+
}
|
|
3784
|
+
/**
|
|
3785
|
+
* Uses the default migration: an empty wallet built from nothing.
|
|
3786
|
+
*
|
|
3787
|
+
* @remarks
|
|
3788
|
+
* This is what an unconfigured builder already does, so calling it changes no behaviour — it states the choice rather
|
|
3789
|
+
* than inheriting it. Registering this variant as the target of a real fork means calling
|
|
3790
|
+
* {@link V2Builder.withMigration} with {@link makeCrossLedgerMigration} instead.
|
|
3791
|
+
*
|
|
3792
|
+
* The parameters the empty dust state is valued against come from the builder configuration when it names them, and
|
|
3793
|
+
* from the ledger's initial parameters when it does not.
|
|
3794
|
+
*/
|
|
3795
|
+
withMigrationDefaults() {
|
|
3796
|
+
return this.withMigration((configuration) => makeEmptyWalletMigration(emptyWalletMigrationConfiguration(configuration)));
|
|
3797
|
+
}
|
|
3798
|
+
/**
|
|
3799
|
+
* Chooses how this variant produces its first state from the state that preceded it.
|
|
3800
|
+
*
|
|
3801
|
+
* @remarks
|
|
3802
|
+
* The strategy's input type becomes the variant's `TPreviousState`, which is what the runtime type-checks a
|
|
3803
|
+
* registration against: a variant declaring it migrates from a ledger-v8 dust wallet cannot be registered after one
|
|
3804
|
+
* that produces something else.
|
|
3805
|
+
*
|
|
3806
|
+
* The context the factory reads is a type parameter of the method, exactly as it is for every other capability here,
|
|
3807
|
+
* rather than the builder's own `TContext`. Naming `TContext` in an argument position would make the builder
|
|
3808
|
+
* invariant in it, and a chain that has not yet configured every capability — which is how the simulator-backed
|
|
3809
|
+
* variants are assembled — could then no longer be handed to {@link V2Builder.build}.
|
|
3810
|
+
* @example
|
|
3811
|
+
* ```typescript
|
|
3812
|
+
* const forkTarget = new V2Builder().withDefaults().withMigration(makeCrossLedgerMigration);
|
|
3813
|
+
* ```;
|
|
3814
|
+
*
|
|
3815
|
+
* @param migration Builds the migration from the configuration and the sibling capabilities.
|
|
3816
|
+
*/
|
|
3817
|
+
withMigration(migration) {
|
|
3818
|
+
const capabilities = this.#buildState;
|
|
3819
|
+
return new V2Builder({
|
|
3820
|
+
...capabilities,
|
|
3821
|
+
migration
|
|
3822
|
+
});
|
|
3823
|
+
}
|
|
3824
|
+
build(configuration) {
|
|
3825
|
+
const v2Context = this.#buildContextFromBuildState(configuration);
|
|
3826
|
+
const migration = this.#resolveMigration(configuration, () => v2Context);
|
|
3827
|
+
return {
|
|
3828
|
+
__polyTag__: V2Tag,
|
|
3829
|
+
coinsAndBalances: v2Context.coinsAndBalancesCapability,
|
|
3830
|
+
keys: v2Context.keysCapability,
|
|
3831
|
+
serialization: v2Context.serializationCapability,
|
|
3832
|
+
transactionHistory: v2Context.transactionHistoryService,
|
|
3833
|
+
startAux: this.#resolveStartAux(),
|
|
3834
|
+
start(context) {
|
|
3835
|
+
return require_dist.gen(function* () {
|
|
3836
|
+
return new RunningV2Variant(yield* require_dist.Scope, context, v2Context);
|
|
3837
|
+
});
|
|
3838
|
+
},
|
|
3839
|
+
migrateState: (previousState) => migration.migrate(previousState).pipe(require_dist.mapError$2((error) => new require_dist.WalletRuntimeError({
|
|
3840
|
+
message: "Failed to migrate dust wallet state into this variant",
|
|
3841
|
+
cause: error
|
|
3842
|
+
}))),
|
|
3843
|
+
deserializeState: (serialized) => {
|
|
3844
|
+
return v2Context.serializationCapability.deserialize(null, serialized);
|
|
3845
|
+
}
|
|
3846
|
+
};
|
|
3847
|
+
}
|
|
3848
|
+
/**
|
|
3849
|
+
* Uses the default derivation: this ledger version's own dust secret key, built from the seed.
|
|
3850
|
+
*
|
|
3851
|
+
* @remarks
|
|
3852
|
+
* Constrained to a builder whose sync is started with a `DustSecretKey`, because that is the only start-aux this
|
|
3853
|
+
* derivation can produce. A builder whose sync expects something else has to say how that is derived, or say
|
|
3854
|
+
* nothing and be refused at `build`.
|
|
3855
|
+
* @returns A builder that produces a variant able to start sync from a seed alone.
|
|
3856
|
+
*/
|
|
3857
|
+
withStartAuxDefaults() {
|
|
3858
|
+
return this.withStartAux({ fromSeed: (seed) => _midnightntwrk_ledger_v9.DustSecretKey.fromSeed(seed) });
|
|
3859
|
+
}
|
|
3860
|
+
/**
|
|
3861
|
+
* Chooses how this variant derives the key material its synchronization is started with from a seed.
|
|
3862
|
+
*
|
|
3863
|
+
* @param startAux The derivation.
|
|
3864
|
+
* @returns A builder that produces a variant able to start sync from a seed alone.
|
|
3865
|
+
*/
|
|
3866
|
+
withStartAux(startAux) {
|
|
3867
|
+
return new V2Builder({
|
|
3868
|
+
...this.#buildState,
|
|
3869
|
+
startAux
|
|
3870
|
+
});
|
|
3871
|
+
}
|
|
3872
|
+
/**
|
|
3873
|
+
* Resolves the configured derivation, refusing a builder that never stated one.
|
|
3874
|
+
*
|
|
3875
|
+
* @remarks
|
|
3876
|
+
* Kept out of the structural completeness check because it is typed rather than merely present: a builder whose sync
|
|
3877
|
+
* expects one kind of key material and whose derivation produces another is a wallet that would be silently handed
|
|
3878
|
+
* key objects of the wrong shape at the first migration.
|
|
3879
|
+
*/
|
|
3880
|
+
#resolveStartAux() {
|
|
3881
|
+
const configured = this.#buildState.startAux;
|
|
3882
|
+
if (configured === void 0) throw new Error("Not all components are configured in V2Builder: startAux");
|
|
3883
|
+
return configured;
|
|
3884
|
+
}
|
|
3885
|
+
/**
|
|
3886
|
+
* Resolves the configured migration, or the empty-wallet fallback when none was configured.
|
|
3887
|
+
*
|
|
3888
|
+
* @remarks
|
|
3889
|
+
* The fallback is written as a nullary function on purpose. It ignores whatever preceded it — it builds an empty
|
|
3890
|
+
* wallet from nothing — which makes it a valid migration from _any_ previous state, but a `StateMigration<null>`
|
|
3891
|
+
* value could only be widened to `StateMigration<TPreviousState>` through a cast. Declaring no parameter says the
|
|
3892
|
+
* same thing to the type system without one.
|
|
3893
|
+
*/
|
|
3894
|
+
#resolveMigration(configuration, getContext) {
|
|
3895
|
+
const configured = this.#buildState.migration;
|
|
3896
|
+
return configured === void 0 ? { migrate: () => makeEmptyWalletMigration(emptyWalletMigrationConfiguration(configuration)).migrate(null) } : configured(configuration, getContext);
|
|
3897
|
+
}
|
|
3898
|
+
#buildContextFromBuildState(configuration) {
|
|
3899
|
+
if (!isBuildStateFull(this.#buildState)) throw new Error("Not all components are configured in V2 Builder");
|
|
3900
|
+
const { syncCapability, syncService, transactingCapability, serializationCapability, coinSelection, coinsAndBalancesCapability, keysCapability, transactionHistoryService } = this.#buildState;
|
|
3901
|
+
const getContext = () => context;
|
|
3902
|
+
const context = {
|
|
3903
|
+
serializationCapability: serializationCapability(configuration, getContext),
|
|
3904
|
+
syncCapability: syncCapability(configuration, getContext),
|
|
3905
|
+
syncService: syncService(configuration, getContext),
|
|
3906
|
+
transactingCapability: transactingCapability(configuration, getContext),
|
|
3907
|
+
coinsAndBalancesCapability: coinsAndBalancesCapability(configuration, getContext),
|
|
3908
|
+
keysCapability: keysCapability(configuration, getContext),
|
|
3909
|
+
coinSelection: coinSelection(configuration, getContext),
|
|
3910
|
+
transactionHistoryService: transactionHistoryService(configuration, getContext)
|
|
3911
|
+
};
|
|
3912
|
+
return context;
|
|
3913
|
+
}
|
|
3914
|
+
};
|
|
3915
|
+
const isBuildStateFull = (buildState) => {
|
|
3916
|
+
return [
|
|
3917
|
+
"syncService",
|
|
3918
|
+
"syncCapability",
|
|
3919
|
+
"transactingCapability",
|
|
3920
|
+
"coinSelection",
|
|
3921
|
+
"serializationCapability",
|
|
3922
|
+
"coinsAndBalancesCapability",
|
|
3923
|
+
"keysCapability",
|
|
3924
|
+
"transactionHistoryService"
|
|
3925
|
+
].every((key) => typeof buildState[key] == "function");
|
|
3926
|
+
};
|
|
3927
|
+
//#endregion
|
|
3928
|
+
//#region ../../packages/module/passport-account/node_modules/@midnightntwrk/wallet-sdk-dust-wallet/dist/DustWallet.js
|
|
3929
|
+
/**
|
|
3930
|
+
* A dust wallet that registers a variant either side of a protocol boundary and follows the chain across it.
|
|
3931
|
+
*
|
|
3932
|
+
* @remarks
|
|
3933
|
+
* One wallet, two ledger versions. Before the boundary the V1 variant reads the chain with the ledger version that
|
|
3934
|
+
* produced it; from the boundary the V2 variant does, having been handed identity and a place in the timeline and
|
|
3935
|
+
* nothing else — the dust itself is re-discovered from the indexer's replay, which is what
|
|
3936
|
+
* `test/forkSimulation.test.ts` proves. Which variant is running is the runtime's business, not the application's:
|
|
3937
|
+
* the wallet's public API speaks ledger-v9 throughout, and where the two sides genuinely differ — the key material
|
|
3938
|
+
* each variant's synchronization needs — the wallet resolves it per variant from what it retained.
|
|
3939
|
+
*
|
|
3940
|
+
* `DustWallet(configuration)` at the bottom is how this package ships it. `CustomForkingDustWallet` is the same wallet
|
|
3941
|
+
* over builders the caller chooses, and `SingleVariantDustWallet.ts` is the composition that gives up the crossing to
|
|
3942
|
+
* run one variant only.
|
|
3943
|
+
*/
|
|
3944
|
+
const asV8DustParameters = (parameters) => new _midnight_ntwrk_ledger_v8.DustParameters(parameters.nightDustRatio, parameters.generationDecayRate, parameters.dustGracePeriodSeconds);
|
|
3945
|
+
/**
|
|
3946
|
+
* The same dust rates, as ledger-v9's parameters object.
|
|
3947
|
+
*
|
|
3948
|
+
* @remarks
|
|
3949
|
+
* The mirror of {@link asV8DustParameters}, and needed for the same reason: an empty state of either variant is
|
|
3950
|
+
* parameterised, and the rates a caller names are plain numbers rather than either ledger's object. Ordinarily the
|
|
3951
|
+
* ledger-v9 side's empty state is the migration's business; a wallet that starts on V2 because the chain said so has
|
|
3952
|
+
* no migration to get one from, and builds its own here.
|
|
3953
|
+
* @param parameters The rates to express.
|
|
3954
|
+
* @returns The same generation and decay rates, as a ledger-v9 `DustParameters`.
|
|
3955
|
+
*/
|
|
3956
|
+
const asV9DustParameters = (parameters) => new _midnightntwrk_ledger_v9.DustParameters(parameters.nightDustRatio, parameters.generationDecayRate, parameters.dustGracePeriodSeconds);
|
|
3957
|
+
/**
|
|
3958
|
+
* Builds a dust wallet class over a variant either side of a protocol boundary.
|
|
3959
|
+
*
|
|
3960
|
+
* @remarks
|
|
3961
|
+
* The boundary is `configuration.forks.v9` and nothing else: the V1 variant is registered from the minimum supported
|
|
3962
|
+
* version and the ledger-v9 one from the fork version, so the version at which the runtime hands over and the version
|
|
3963
|
+
* at which each variant stops applying are the same number, taken from one place.
|
|
3964
|
+
*
|
|
3965
|
+
* Each variant is built from its own configuration, which for dust is load-bearing rather than tidy — see
|
|
3966
|
+
* {@link SelfConfiguredDustVariant}.
|
|
3967
|
+
* @example
|
|
3968
|
+
* ```typescript
|
|
3969
|
+
* const Wallet = CustomForkingDustWallet(
|
|
3970
|
+
* { forks },
|
|
3971
|
+
* { builder: new V1Builder().withDefaults(), configuration: v1Configuration },
|
|
3972
|
+
* { builder: new V2Builder().withDefaults().withMigration(...), configuration: v2Configuration },
|
|
3973
|
+
* );
|
|
3974
|
+
* const wallet = Wallet.startWithSeed(seed, dustParameters);
|
|
3975
|
+
* ```;
|
|
3976
|
+
*
|
|
3977
|
+
* @param configuration What the wallet layer needs: where the boundary lies.
|
|
3978
|
+
* @param v1 The variant that reads the chain below the boundary, with the configuration it is built from.
|
|
3979
|
+
* @param v2 The variant that reads it from the boundary, with the configuration it is built from.
|
|
3980
|
+
* @returns The wallet class.
|
|
3981
|
+
*/
|
|
3982
|
+
function CustomForkingDustWallet(configuration, v1, v2) {
|
|
3983
|
+
const v1Builder = v1.builder;
|
|
3984
|
+
const v2Builder = v2.builder;
|
|
3985
|
+
const BaseWallet = require_dist.WalletBuilder.init().withVariant(require_dist.MinSupportedVersion, v1Builder, v1.configuration).withVariant(configuration.forks.v9, v2Builder, v2.configuration).build();
|
|
3986
|
+
const variants = BaseWallet.allVariantsRecord();
|
|
3987
|
+
/** What the rates are when a caller names none: the ledger's own initial parameters. */
|
|
3988
|
+
const defaultRates = _midnightntwrk_ledger_v9.LedgerParameters.initialParameters().dust;
|
|
3989
|
+
/** Nothing retained: never started, or stopped. */
|
|
3990
|
+
const noKeys = {
|
|
3991
|
+
v8: require_dist.none(),
|
|
3992
|
+
v9: require_dist.none()
|
|
3993
|
+
};
|
|
3994
|
+
/** Both sides, derived from one seed. */
|
|
3995
|
+
const keysFromSeed = (seed) => ({
|
|
3996
|
+
v8: require_dist.some(variants[V1Tag].variant.startAux.fromSeed(seed)),
|
|
3997
|
+
v9: require_dist.some(variants[V2Tag].variant.startAux.fromSeed(seed))
|
|
3998
|
+
});
|
|
3999
|
+
/**
|
|
4000
|
+
* What a variant can be started with, or why it cannot be.
|
|
4001
|
+
*
|
|
4002
|
+
* @remarks
|
|
4003
|
+
* Two different failures, deliberately distinguished: a wallet that was never started (or has been stopped) holds
|
|
4004
|
+
* nothing at all, while one started with the other side's key object holds something it must not use here.
|
|
4005
|
+
*/
|
|
4006
|
+
const auxFor = (retained, side, variantTag) => require_dist.fromOption(side, () => new require_dist.MissingStartAuxError({
|
|
4007
|
+
message: require_dist.isNone(retained.v8) && require_dist.isNone(retained.v9) ? "This wallet holds no key material: it has not been started, or it has been stopped. Start it before asking it to synchronize or to pay a fee." : `This wallet holds key material of the other protocol version only, which the variant ${String(variantTag)} cannot use: a Dust secret key belongs to one ledger version's runtime. Start this wallet with material that answers for either side — startWithSeed(seed), or startWithKeys({ v8, v9 }).`,
|
|
4008
|
+
variantTag
|
|
4009
|
+
}));
|
|
4010
|
+
const v8Aux = (retained) => auxFor(retained, retained.v8, V1Tag);
|
|
4011
|
+
const v9Aux = (retained) => auxFor(retained, retained.v9, V2Tag);
|
|
4012
|
+
/**
|
|
4013
|
+
* The protocol versions each variant owns, and the version a transaction it builds is stamped with.
|
|
4014
|
+
*
|
|
4015
|
+
* @remarks
|
|
4016
|
+
* The stamp is the floor of the variant's epoch: every decision it is later read for asks which side of the boundary
|
|
4017
|
+
* the bytes belong to, and the floor answers that the same way as any other version in the same epoch.
|
|
4018
|
+
*/
|
|
4019
|
+
const v8Epoch = require_dist.epochOf(require_dist.MinSupportedVersion, configuration.forks.v9);
|
|
4020
|
+
const v9Epoch = require_dist.epochOf(configuration.forks.v9, configuration.forks.v9);
|
|
4021
|
+
const [v8Stamp] = v8Epoch;
|
|
4022
|
+
const [v9Stamp] = v9Epoch;
|
|
4023
|
+
/** Reads a transaction built before the boundary, refusing one built after it. */
|
|
4024
|
+
const v8Tx = (handle) => require_dist.toEffect(require_dist.WalletTransaction.unwrapWithin(handle, v8Epoch));
|
|
4025
|
+
/** Reads a transaction built from the boundary, refusing one built before it. */
|
|
4026
|
+
const v9Tx = (handle) => require_dist.toEffect(require_dist.WalletTransaction.unwrapWithin(handle, v9Epoch));
|
|
4027
|
+
/**
|
|
4028
|
+
* How long a start waits for the chain to say which version it is on.
|
|
4029
|
+
*
|
|
4030
|
+
* @remarks
|
|
4031
|
+
* Short, because what is being bought is small: the alternative to an answer is the hand-over this wallet has always
|
|
4032
|
+
* done, which costs one migration and no correctness on a chain that produces events. It is a ceiling rather than a
|
|
4033
|
+
* typical cost — an unreachable indexer refuses a connection long before this — and it exists so that a probe which
|
|
4034
|
+
* neither answers nor fails cannot hold a start open indefinitely.
|
|
4035
|
+
*/
|
|
4036
|
+
const probeTimeout = require_dist.seconds(5);
|
|
4037
|
+
/**
|
|
4038
|
+
* The variant the chain's current version belongs to, or nothing.
|
|
4039
|
+
*
|
|
4040
|
+
* @remarks
|
|
4041
|
+
* Nothing covers every way the question can fail to produce an answer, and they are deliberately not distinguished:
|
|
4042
|
+
* no probe configured, a probe that rejected, a probe that outlived the wallet's patience, or a version no
|
|
4043
|
+
* registered variant claims. Each means the same thing to a caller — start where a wallet with no history starts —
|
|
4044
|
+
* and none of them is a reason to fail.
|
|
4045
|
+
*/
|
|
4046
|
+
const probedStart = configuration.chainVersionProbe === void 0 ? require_dist.succeedNone : require_dist.pipe(require_dist.tryPromise(configuration.chainVersionProbe), require_dist.timeout(probeTimeout), require_dist.map$2((version) => require_dist.map$5(BaseWallet.variantFor(version), (variant) => ({
|
|
4047
|
+
version,
|
|
4048
|
+
variant
|
|
4049
|
+
}))), require_dist.orElseSucceed(() => require_dist.none()));
|
|
4050
|
+
/**
|
|
4051
|
+
* A fresh state of the variant a probed start begins at, recording the version the chain reported.
|
|
4052
|
+
*
|
|
4053
|
+
* @remarks
|
|
4054
|
+
* Built exactly as the head-variant boot path builds its own — an empty state of that variant, valued against that
|
|
4055
|
+
* ledger version's rebuild of the rates the caller named — and then annotated with the observed version, which is
|
|
4056
|
+
* what keeps a variant from starting outside its own activation range and signalling backwards on sight.
|
|
4057
|
+
*/
|
|
4058
|
+
const freshStateAt = (variant, keys, rates, version) => require_dist.getVersionedVariantTag(variant) === V2Tag ? CoreWallet$1.withProtocolVersion(CoreWallet$1.initEmpty(asV9DustParameters(rates), keys.v9, configuration.networkId), version) : CoreWallet.withProtocolVersion(CoreWallet.initEmpty(asV8DustParameters(rates), keys.v8, configuration.networkId), version);
|
|
4059
|
+
return class ForkingDustWalletImplementation extends BaseWallet {
|
|
4060
|
+
static configuration = configuration;
|
|
4061
|
+
/**
|
|
4062
|
+
* Starts at the variant the chain says it is on, or at the head variant when it does not say.
|
|
4063
|
+
*
|
|
4064
|
+
* @remarks
|
|
4065
|
+
* The second branch is the whole of this wallet's previous behaviour, unchanged and reached whenever the chain was
|
|
4066
|
+
* not asked or did not answer: the V1 variant, an empty state valued against the ledger-v8 rebuild of the rates
|
|
4067
|
+
* the caller named, and a hand-over on the first batch that reports a version it does not own.
|
|
4068
|
+
* @param keys One ledger version's dust key per side of the boundary, since either side may be the one that runs.
|
|
4069
|
+
* @param rates The rates the caller named, which whichever empty state is built is valued against.
|
|
4070
|
+
* @returns The started wallet.
|
|
4071
|
+
*/
|
|
4072
|
+
static #startProbed(keys, rates) {
|
|
4073
|
+
return require_dist.pipe(probedStart, require_dist.map$2(require_dist.match$1({
|
|
4074
|
+
onNone: () => ForkingDustWalletImplementation.startFirst(ForkingDustWalletImplementation, CoreWallet.initEmpty(asV8DustParameters(rates), keys.v8, configuration.networkId)),
|
|
4075
|
+
onSome: ({ version, variant }) => ForkingDustWalletImplementation.startAtVariant(ForkingDustWalletImplementation, variant, freshStateAt(variant, keys, rates, version))
|
|
4076
|
+
})), require_dist.runPromise$1);
|
|
4077
|
+
}
|
|
4078
|
+
static async startWithSeed(seed, dustParameters = defaultRates) {
|
|
4079
|
+
const derived = keysFromSeed(require_dist.WalletSeed(seed));
|
|
4080
|
+
const wallet = await ForkingDustWalletImplementation.#startProbed({
|
|
4081
|
+
v8: require_dist.getOrThrow(derived.v8),
|
|
4082
|
+
v9: require_dist.getOrThrow(derived.v9)
|
|
4083
|
+
}, dustParameters);
|
|
4084
|
+
wallet.#retainKeys(derived);
|
|
4085
|
+
return wallet;
|
|
4086
|
+
}
|
|
4087
|
+
static async startWithKeys(keys, dustParameters = defaultRates) {
|
|
4088
|
+
const wallet = await ForkingDustWalletImplementation.#startProbed(keys, dustParameters);
|
|
4089
|
+
wallet.#retainKeys({
|
|
4090
|
+
v8: require_dist.some(keys.v8),
|
|
4091
|
+
v9: require_dist.some(keys.v9)
|
|
4092
|
+
});
|
|
4093
|
+
return wallet;
|
|
4094
|
+
}
|
|
4095
|
+
static tryRestore(serializedState) {
|
|
4096
|
+
return variantForSnapshot(serializedState, (version) => ForkingDustWalletImplementation.variantFor(version), require_dist.head(ForkingDustWalletImplementation.allVariants())).pipe(require_dist.flatMap$4((variant) => {
|
|
4097
|
+
const deserialized = variant.variant.deserializeState(serializedState);
|
|
4098
|
+
return require_dist.map$6(deserialized, (state) => ForkingDustWalletImplementation.startAtVariant(ForkingDustWalletImplementation, variant, state));
|
|
4099
|
+
}));
|
|
4100
|
+
}
|
|
4101
|
+
static restore(serializedState) {
|
|
4102
|
+
return require_dist.getOrThrow$1(ForkingDustWalletImplementation.tryRestore(serializedState));
|
|
4103
|
+
}
|
|
4104
|
+
state;
|
|
4105
|
+
/**
|
|
4106
|
+
* What the application started this wallet with, kept so synchronization can be started again.
|
|
4107
|
+
*
|
|
4108
|
+
* @remarks
|
|
4109
|
+
* A migration starts a fresh variant whose sync has never run, and sync needs key material that is deliberately
|
|
4110
|
+
* absent from anything the wallet serializes. A retained seed answers for both variants; a retained key object
|
|
4111
|
+
* answers only for the ledger-v9 one, which is the ledger version this wallet's public API speaks. Cleared by
|
|
4112
|
+
* {@link stop} so a stopped wallet cannot be resurrected by a late activation.
|
|
4113
|
+
*/
|
|
4114
|
+
#retainedKeys = require_dist.unsafeMake(noKeys);
|
|
4115
|
+
/** Remembers key material for both sides of the boundary. */
|
|
4116
|
+
#retainKeys(keys) {
|
|
4117
|
+
require_dist.set(this.#retainedKeys, keys).pipe(require_dist.runSync);
|
|
4118
|
+
}
|
|
4119
|
+
/**
|
|
4120
|
+
* Starts synchronization on a variant that has just become current, with key material it can use.
|
|
4121
|
+
*
|
|
4122
|
+
* @param running The variant to start.
|
|
4123
|
+
* @param auxFor That variant's own resolution of what it can be started with.
|
|
4124
|
+
*/
|
|
4125
|
+
#resumeSyncOn(running, keysFor) {
|
|
4126
|
+
return require_dist.get$1(this.#retainedKeys).pipe(require_dist.flatMap$1((retained) => require_dist.isNone(retained.v8) && require_dist.isNone(retained.v9) ? require_dist._void : require_dist.toEffect(keysFor(retained)).pipe(require_dist.flatMap$1((aux) => running.startSyncInBackground(aux)))));
|
|
4127
|
+
}
|
|
4128
|
+
/** One synchronization step on a variant, with key material it can use. */
|
|
4129
|
+
#stepSyncOn(running, keysFor) {
|
|
4130
|
+
return require_dist.get$1(this.#retainedKeys).pipe(require_dist.flatMap$1((retained) => require_dist.isNone(retained.v8) && require_dist.isNone(retained.v9) ? require_dist._void : require_dist.toEffect(keysFor(retained)).pipe(require_dist.flatMap$1((aux) => running.sync(aux)))));
|
|
4131
|
+
}
|
|
4132
|
+
/**
|
|
4133
|
+
* Whether the activation watcher has been registered.
|
|
4134
|
+
*
|
|
4135
|
+
* @remarks
|
|
4136
|
+
* Registration is per wallet, not per `start`: watchers accumulate, so registering on every call would restart sync
|
|
4137
|
+
* once per historical `start` on the next activation. Flipped with `getAndSet` so concurrent `start` calls cannot
|
|
4138
|
+
* both observe it unset.
|
|
4139
|
+
*/
|
|
4140
|
+
#watcherRegistered = require_dist.unsafeMake(false);
|
|
4141
|
+
constructor(runtime, scope) {
|
|
4142
|
+
super(runtime, scope);
|
|
4143
|
+
this.state = this.rawState.pipe(rxjs.map((emission) => emission.variantTag === V2Tag ? DustWalletState.fromVariant(variants[V2Tag].variant, emission) : DustWalletState.fromVariant(variants[V1Tag].variant, emission)), rxjs.shareReplay({
|
|
4144
|
+
refCount: true,
|
|
4145
|
+
bufferSize: 1
|
|
4146
|
+
}));
|
|
4147
|
+
}
|
|
4148
|
+
/**
|
|
4149
|
+
* Everything a start does once the wallet holds its key material: watch for the next variant, synchronize on this
|
|
4150
|
+
* one.
|
|
4151
|
+
*
|
|
4152
|
+
* @remarks
|
|
4153
|
+
* The same work whichever start was called — what the three differ in is only what they retained a moment earlier —
|
|
4154
|
+
* so it is stated once. The watcher is registered before the first dispatch and only once per wallet:
|
|
4155
|
+
* `onVariantActivation` resolves only after its subscription is live, so an activation racing a start is queued
|
|
4156
|
+
* rather than missed, and watchers accumulate, so registering per call would restart synchronization once per
|
|
4157
|
+
* historical start.
|
|
4158
|
+
*
|
|
4159
|
+
* Both branches of the dispatch resolve their key from what was retained rather than from what the caller passed,
|
|
4160
|
+
* because the variant that is current is not the caller's to know: a wallet restored below the boundary is on the
|
|
4161
|
+
* ledger-v8 one whatever the application holds.
|
|
4162
|
+
*/
|
|
4163
|
+
#startSynchronizing() {
|
|
4164
|
+
return require_dist.gen(this, function* () {
|
|
4165
|
+
if (!(yield* require_dist.getAndSet(this.#watcherRegistered, true))) yield* this.runtime.onVariantActivation({
|
|
4166
|
+
[V1Tag]: (v1) => this.#resumeSyncOn(v1, v8Aux),
|
|
4167
|
+
[V2Tag]: (v2) => this.#resumeSyncOn(v2, v9Aux)
|
|
4168
|
+
});
|
|
4169
|
+
yield* this.runtime.dispatch({
|
|
4170
|
+
[V1Tag]: (v1) => this.#resumeSyncOn(v1, v8Aux),
|
|
4171
|
+
[V2Tag]: (v2) => this.#resumeSyncOn(v2, v9Aux)
|
|
4172
|
+
});
|
|
4173
|
+
});
|
|
4174
|
+
}
|
|
4175
|
+
/**
|
|
4176
|
+
* Starts background synchronization on whichever variant is current, and keeps the key for the next one.
|
|
4177
|
+
*
|
|
4178
|
+
* @remarks
|
|
4179
|
+
* The key is ledger-v9's, so it is retained against that variant alone and answers for it alone. A wallet still on
|
|
4180
|
+
* the V1 variant is started from whatever it holds for _that_ side — which a wallet built from a seed, or from
|
|
4181
|
+
* both versions' keys, can always answer and one holding only this cannot.
|
|
4182
|
+
*
|
|
4183
|
+
* That is the position of a wallet restored from a snapshot written below the boundary: a snapshot carries no key
|
|
4184
|
+
* material, so this key leaves it with nothing the running variant can use, and it says so rather than pretending
|
|
4185
|
+
* to have started. {@link ForkingDustWallet.startWithSeed} and {@link ForkingDustWallet.startWithKeys} are the same
|
|
4186
|
+
* wallet started with material that answers for either side.
|
|
4187
|
+
* @param secretKey The ledger-v9's dust secret key.
|
|
4188
|
+
*/
|
|
4189
|
+
start(secretKey) {
|
|
4190
|
+
return require_dist.gen(this, function* () {
|
|
4191
|
+
yield* require_dist.update(this.#retainedKeys, (retained) => ({
|
|
4192
|
+
...retained,
|
|
4193
|
+
v9: require_dist.some(secretKey)
|
|
4194
|
+
}));
|
|
4195
|
+
yield* this.#startSynchronizing();
|
|
4196
|
+
}).pipe(require_dist.runPromise$1);
|
|
4197
|
+
}
|
|
4198
|
+
startWithSeed(seed) {
|
|
4199
|
+
return require_dist.gen(this, function* () {
|
|
4200
|
+
yield* require_dist.set(this.#retainedKeys, keysFromSeed(require_dist.WalletSeed(seed)));
|
|
4201
|
+
yield* this.#startSynchronizing();
|
|
4202
|
+
}).pipe(require_dist.runPromise$1);
|
|
4203
|
+
}
|
|
4204
|
+
startWithKeys(keys) {
|
|
4205
|
+
return require_dist.gen(this, function* () {
|
|
4206
|
+
yield* require_dist.set(this.#retainedKeys, {
|
|
4207
|
+
v8: require_dist.some(keys.v8),
|
|
4208
|
+
v9: require_dist.some(keys.v9)
|
|
4209
|
+
});
|
|
4210
|
+
yield* this.#startSynchronizing();
|
|
4211
|
+
}).pipe(require_dist.runPromise$1);
|
|
4212
|
+
}
|
|
4213
|
+
async stop() {
|
|
4214
|
+
require_dist.set(this.#retainedKeys, noKeys).pipe(require_dist.runSync);
|
|
4215
|
+
await super.stop();
|
|
4216
|
+
}
|
|
4217
|
+
/**
|
|
4218
|
+
* Runs one synchronization step on whichever variant is current.
|
|
4219
|
+
*
|
|
4220
|
+
* @remarks
|
|
4221
|
+
* Available on both sides of the boundary: the V1 variant is stepped with a key derived from what the wallet
|
|
4222
|
+
* retained, exactly as background synchronization is.
|
|
4223
|
+
* @param secretKey The ledger-v9's dust secret key.
|
|
4224
|
+
*/
|
|
4225
|
+
stepSync(secretKey) {
|
|
4226
|
+
return this.runtime.dispatch({
|
|
4227
|
+
[V1Tag]: (v1) => this.#stepSyncOn(v1, v8Aux),
|
|
4228
|
+
[V2Tag]: (v2) => v2.sync(secretKey)
|
|
4229
|
+
}).pipe(require_dist.runPromise$1);
|
|
4230
|
+
}
|
|
4231
|
+
/**
|
|
4232
|
+
* The key material the variant that is current can use, from what this wallet retained.
|
|
4233
|
+
*
|
|
4234
|
+
* @remarks
|
|
4235
|
+
* Fee payment selects dust the wallet owns, so it needs the same secret synchronization does. A wallet that was
|
|
4236
|
+
* never started, or one holding a key object of the other ledger version, has none the current variant can use
|
|
4237
|
+
* and says so by name.
|
|
4238
|
+
*/
|
|
4239
|
+
#requireAux(keysFor) {
|
|
4240
|
+
return require_dist.get$1(this.#retainedKeys).pipe(require_dist.flatMap$1((retained) => require_dist.toEffect(keysFor(retained))));
|
|
4241
|
+
}
|
|
4242
|
+
createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress) {
|
|
4243
|
+
return this.runtime.dispatch({
|
|
4244
|
+
[V1Tag]: (v1) => require_dist.toEffect(require_v8Signatures.lowerSignatureVerifyingKey(nightVerifyingKey)).pipe(require_dist.flatMap$1((key) => v1.createDustGenerationTransaction(currentTime, ttl, nightUtxos, key, dustReceiverAddress)), require_dist.map$2((tx) => require_dist.WalletTransaction.adopt("Unproven", tx, v8Stamp))),
|
|
4245
|
+
[V2Tag]: (v2) => v2.createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress).pipe(require_dist.map$2((tx) => require_dist.WalletTransaction.adopt("Unproven", tx, v9Stamp)))
|
|
4246
|
+
}).pipe(require_dist.runPromise$1);
|
|
4247
|
+
}
|
|
4248
|
+
/**
|
|
4249
|
+
* Splits Night UTxOs into the ones a registration puts in its guaranteed and fallible sections.
|
|
4250
|
+
*
|
|
4251
|
+
* @remarks
|
|
4252
|
+
* Available on both sides of the boundary, and deliberately not part of the seam above: it takes and returns plain
|
|
4253
|
+
* data — UTxOs, dust generation readings, a fee amount — and touches no transaction at all, so there is nothing
|
|
4254
|
+
* here that needs proving and nothing the V1 variant cannot answer.
|
|
4255
|
+
*/
|
|
4256
|
+
splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration) {
|
|
4257
|
+
return this.runtime.dispatch({
|
|
4258
|
+
[V1Tag]: (v1) => v1.splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration),
|
|
4259
|
+
[V2Tag]: (v2) => v2.splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration)
|
|
4260
|
+
}).pipe(require_dist.runPromise$1);
|
|
4261
|
+
}
|
|
4262
|
+
attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
4263
|
+
return this.runtime.dispatch({
|
|
4264
|
+
[V1Tag]: (v1) => require_dist.all([v8Tx(transaction), require_dist.toEffect(require_v8Signatures.lowerSignatureVerifyingKey(nightVerifyingKey))]).pipe(require_dist.flatMap$1(([tx, key]) => v1.attachDustRegistration(tx, currentTime, key, dustReceiverAddress, feePayment)), require_dist.map$2((tx) => require_dist.WalletTransaction.adopt("Unproven", tx, v8Stamp))),
|
|
4265
|
+
[V2Tag]: (v2) => v9Tx(transaction).pipe(require_dist.flatMap$1((tx) => v2.attachDustRegistration(tx, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment)), require_dist.map$2((tx) => require_dist.WalletTransaction.adopt("Unproven", tx, v9Stamp)))
|
|
4266
|
+
}).pipe(require_dist.runPromise$1);
|
|
4267
|
+
}
|
|
4268
|
+
addDustGenerationSignature(transaction, signature) {
|
|
4269
|
+
return this.runtime.dispatch({
|
|
4270
|
+
[V1Tag]: (v1) => require_dist.all([v8Tx(transaction), require_dist.toEffect(require_v8Signatures.lowerSignature(signature))]).pipe(require_dist.flatMap$1(([tx, lowered]) => v1.addDustGenerationSignature(tx, lowered)), require_dist.map$2((tx) => require_dist.WalletTransaction.adopt("Unproven", tx, v8Stamp))),
|
|
4271
|
+
[V2Tag]: (v2) => v9Tx(transaction).pipe(require_dist.flatMap$1((tx) => v2.addDustGenerationSignature(tx, signature)), require_dist.map$2((tx) => require_dist.WalletTransaction.adopt("Unproven", tx, v9Stamp)))
|
|
4272
|
+
}).pipe(require_dist.runPromise$1);
|
|
4273
|
+
}
|
|
4274
|
+
addDustRegistrationSignature(transaction, signature) {
|
|
4275
|
+
return this.runtime.dispatch({
|
|
4276
|
+
[V1Tag]: (v1) => require_dist.all([v8Tx(transaction), require_dist.toEffect(require_v8Signatures.lowerSignature(signature))]).pipe(require_dist.flatMap$1(([tx, lowered]) => v1.addDustRegistrationSignature(tx, lowered)), require_dist.map$2((tx) => require_dist.WalletTransaction.adopt("Unproven", tx, v8Stamp))),
|
|
4277
|
+
[V2Tag]: (v2) => v9Tx(transaction).pipe(require_dist.flatMap$1((tx) => v2.addDustRegistrationSignature(tx, signature)), require_dist.map$2((tx) => require_dist.WalletTransaction.adopt("Unproven", tx, v9Stamp)))
|
|
4278
|
+
}).pipe(require_dist.runPromise$1);
|
|
4279
|
+
}
|
|
4280
|
+
calculateFee(transactions) {
|
|
4281
|
+
return this.runtime.dispatch({
|
|
4282
|
+
[V1Tag]: (v1) => require_dist.forEach(transactions, v8Tx).pipe(require_dist.flatMap$1((txs) => v1.calculateFee(txs))),
|
|
4283
|
+
[V2Tag]: (v2) => require_dist.forEach(transactions, v9Tx).pipe(require_dist.flatMap$1((txs) => v2.calculateFee(txs)))
|
|
4284
|
+
}).pipe(require_dist.runPromise$1);
|
|
4285
|
+
}
|
|
4286
|
+
estimateFee(transactions, ttl, currentTime) {
|
|
4287
|
+
const effectiveTtl = ttl ?? new Date(Date.now() + 3600 * 1e3);
|
|
4288
|
+
return this.runtime.dispatch({
|
|
4289
|
+
[V1Tag]: (v1) => require_dist.all([this.#requireAux(v8Aux), require_dist.forEach(transactions, v8Tx)]).pipe(require_dist.flatMap$1(([key, txs]) => v1.estimateFee(key, txs, effectiveTtl, currentTime))),
|
|
4290
|
+
[V2Tag]: (v2) => require_dist.all([this.#requireAux(v9Aux), require_dist.forEach(transactions, v9Tx)]).pipe(require_dist.flatMap$1(([key, txs]) => v2.estimateFee(key, txs, effectiveTtl, currentTime)))
|
|
4291
|
+
}).pipe(require_dist.runPromise$1);
|
|
4292
|
+
}
|
|
4293
|
+
balanceTransactions(transactions, ttl, currentTime) {
|
|
4294
|
+
return this.runtime.dispatch({
|
|
4295
|
+
[V1Tag]: (v1) => require_dist.all([this.#requireAux(v8Aux), require_dist.forEach(transactions, v8Tx)]).pipe(require_dist.flatMap$1(([key, txs]) => v1.balanceTransactions(key, txs, ttl, currentTime)), require_dist.map$2(({ transaction, blockData }) => ({
|
|
4296
|
+
transaction: require_dist.WalletTransaction.adopt("Unproven", transaction, v8Stamp),
|
|
4297
|
+
blockData
|
|
4298
|
+
}))),
|
|
4299
|
+
[V2Tag]: (v2) => require_dist.all([this.#requireAux(v9Aux), require_dist.forEach(transactions, v9Tx)]).pipe(require_dist.flatMap$1(([key, txs]) => v2.balanceTransactions(key, txs, ttl, currentTime)), require_dist.map$2(({ transaction, blockData }) => ({
|
|
4300
|
+
transaction: require_dist.WalletTransaction.adopt("Unproven", transaction, v9Stamp),
|
|
4301
|
+
blockData
|
|
4302
|
+
})))
|
|
4303
|
+
}).pipe(require_dist.runPromise$1);
|
|
4304
|
+
}
|
|
4305
|
+
/**
|
|
4306
|
+
* Un-records a transaction this wallet paid the fee for, releasing the dust it had booked.
|
|
4307
|
+
*
|
|
4308
|
+
* @remarks
|
|
4309
|
+
* A transaction built on the other side of the boundary cannot have had its fee paid by the current variant, so
|
|
4310
|
+
* there is no dust of it to release and this resolves having done nothing. That is the one place a version
|
|
4311
|
+
* mismatch is not an error: the facade reverts all three wallets together when a submission fails, and a refusal
|
|
4312
|
+
* here would strand that whole path over a transaction this wallet was never holding anything for.
|
|
4313
|
+
* @param transaction The transaction to un-record.
|
|
4314
|
+
*/
|
|
4315
|
+
revertTransaction(transaction) {
|
|
4316
|
+
return this.runtime.dispatch({
|
|
4317
|
+
[V1Tag]: (v1) => require_dist.match$2(require_dist.WalletTransaction.unwrapWithin(transaction, v8Epoch), {
|
|
4318
|
+
onLeft: () => require_dist._void,
|
|
4319
|
+
onRight: (tx) => v1.revertTransaction(tx)
|
|
4320
|
+
}),
|
|
4321
|
+
[V2Tag]: (v2) => require_dist.match$2(require_dist.WalletTransaction.unwrapWithin(transaction, v9Epoch), {
|
|
4322
|
+
onLeft: () => require_dist._void,
|
|
4323
|
+
onRight: (tx) => v2.revertTransaction(tx)
|
|
4324
|
+
})
|
|
4325
|
+
}).pipe(require_dist.runPromise$1);
|
|
4326
|
+
}
|
|
4327
|
+
waitForSyncedState(allowedGap = 0n) {
|
|
4328
|
+
return rxjs.firstValueFrom(this.state.pipe(rxjs.filter((state) => state.state.progress.isCompleteWithin(allowedGap))));
|
|
4329
|
+
}
|
|
4330
|
+
async waitForGeneratedDust(nightUtxos, requiredAmount, clock, opts) {
|
|
4331
|
+
if (nightUtxos.length === 0) throw Error("At least one Night UTXO is required.");
|
|
4332
|
+
if (requiredAmount <= 0n) return;
|
|
4333
|
+
const timeoutMs = opts?.timeoutMs ?? 3e5;
|
|
4334
|
+
await rxjs.firstValueFrom(rxjs.combineLatest([this.state, rxjs.timer(0, 1e3)]).pipe(rxjs.filter(([dustState]) => claimableFeePayment(dustState, nightUtxos, clock.now()) >= requiredAmount), rxjs.timeout({ first: timeoutMs })));
|
|
4335
|
+
}
|
|
4336
|
+
serializeState() {
|
|
4337
|
+
return rxjs.firstValueFrom(this.state).then((state) => state.serialize());
|
|
4338
|
+
}
|
|
4339
|
+
getAddress() {
|
|
4340
|
+
return rxjs.firstValueFrom(this.state).then((state) => state.address);
|
|
4341
|
+
}
|
|
4342
|
+
};
|
|
4343
|
+
}
|
|
4344
|
+
/**
|
|
4345
|
+
* Builds the dust wallet this package ships: the default variant either side of `configuration.forks.v9`.
|
|
4346
|
+
*
|
|
4347
|
+
* @remarks
|
|
4348
|
+
* Both variants read the chain through the indexer's dust event subscription and record transaction history in the same
|
|
4349
|
+
* storage. Each is built from the same application configuration, because what they ask for happens to coincide —
|
|
4350
|
+
* with one exception the type system cannot police: `dustParameters` names a ledger type, and the two ledgers'
|
|
4351
|
+
* `DustParameters` are structurally identical, so it is passed only to the variant it belongs to.
|
|
4352
|
+
*
|
|
4353
|
+
* **The V1 variant syncs by event replay only.** The projections fast-sync path is a ledger-v9 capability: it needs
|
|
4354
|
+
* four `DustLocalState` APIs that no published ledger-v8 has. That is a permanent property of the V1 variant, not a
|
|
4355
|
+
* gap to be closed.
|
|
4356
|
+
*
|
|
4357
|
+
* **Fee-paying operations work on either side of the boundary**: the active variant answers with its own ledger's
|
|
4358
|
+
* objects, and every result travels as a handle stamped with the epoch that built it.
|
|
4359
|
+
*
|
|
4360
|
+
* **The chain is asked where it is before a variant is chosen.** The indexer this wallet already syncs from answers
|
|
4361
|
+
* which protocol version the chain is on, so a start on a chain past the boundary begins on V2 rather than handing
|
|
4362
|
+
* over immediately. An application that would rather ask something else — a cache, a value it already holds —
|
|
4363
|
+
* supplies its own `chainVersionProbe`; one whose chain cannot be reached loses nothing, because the answer is
|
|
4364
|
+
* best-effort and its absence is the behaviour this wallet had before.
|
|
4365
|
+
* @param configuration What the wallet and both its variants are built from, including where the boundary lies.
|
|
4366
|
+
* @returns The wallet class.
|
|
4367
|
+
*/
|
|
4368
|
+
function DustWallet(configuration) {
|
|
4369
|
+
const dustParameters = configuration.dustParameters ?? _midnightntwrk_ledger_v9.LedgerParameters.initialParameters().dust;
|
|
4370
|
+
return CustomForkingDustWallet({
|
|
4371
|
+
...configuration,
|
|
4372
|
+
chainVersionProbe: configuration.chainVersionProbe ?? require_dist.makeIndexerChainVersionProbe(configuration)
|
|
4373
|
+
}, {
|
|
4374
|
+
builder: new V1Builder().withDefaults(),
|
|
4375
|
+
configuration: {
|
|
4376
|
+
...configuration,
|
|
4377
|
+
dustParameters: asV8DustParameters(dustParameters)
|
|
4378
|
+
}
|
|
4379
|
+
}, {
|
|
4380
|
+
builder: new V2Builder().withDefaults().withMigration(() => makeCrossLedgerMigration({ dustParameters })),
|
|
4381
|
+
configuration
|
|
4382
|
+
});
|
|
4383
|
+
}
|
|
4384
|
+
//#endregion
|
|
4385
|
+
exports.BackgroundRepeat = BackgroundRepeat;
|
|
4386
|
+
exports.CustomDustWallet = CustomDustWallet;
|
|
4387
|
+
exports.CustomForkingDustWallet = CustomForkingDustWallet;
|
|
4388
|
+
exports.DustSectionSchema = DustSectionSchema;
|
|
4389
|
+
exports.DustSectionSchema$1 = DustSectionSchema;
|
|
4390
|
+
exports.DustWallet = DustWallet;
|
|
4391
|
+
exports.DustWalletState = DustWalletState;
|
|
4392
|
+
exports.SecretKeysResource = SecretKeysResource;
|
|
4393
|
+
exports.UnsupportedSnapshotVersionError = UnsupportedSnapshotVersionError;
|
|
4394
|
+
exports.annotateVersion = annotateVersion;
|
|
4395
|
+
exports.asV8DustParameters = asV8DustParameters;
|
|
4396
|
+
exports.asV9DustParameters = asV9DustParameters;
|
|
4397
|
+
exports.claimableFeePayment = claimableFeePayment;
|
|
4398
|
+
exports.createDustUtxoUpdates = createDustUtxoUpdates;
|
|
4399
|
+
exports.doEventlessSync = doEventlessSync;
|
|
4400
|
+
exports.makeDefaultSyncCapability = makeDefaultSyncCapability;
|
|
4401
|
+
exports.makeDefaultSyncService = makeDefaultSyncService;
|
|
4402
|
+
exports.makeEventLessSyncCapability = makeEventLessSyncCapability;
|
|
4403
|
+
exports.makeEventLessSyncService = makeEventLessSyncService;
|
|
4404
|
+
exports.makeIndexerSyncService = makeIndexerSyncService;
|
|
4405
|
+
exports.makeSimulatorSyncCapability = makeSimulatorSyncCapability;
|
|
4406
|
+
exports.makeSimulatorSyncService = makeSimulatorSyncService;
|
|
4407
|
+
exports.matchedDustSpends = matchedDustSpends;
|
|
4408
|
+
exports.mergeDustSections = mergeDustSections;
|
|
4409
|
+
exports.mergeDustSections$1 = mergeDustSections;
|
|
4410
|
+
exports.nullifierPhaseAppliedIndex = nullifierPhaseAppliedIndex;
|
|
4411
|
+
exports.nullifierPhaseProgress = nullifierPhaseProgress;
|
|
4412
|
+
exports.peekProtocolVersion = peekProtocolVersion;
|
|
4413
|
+
exports.splitAtVersionBoundary = splitAtVersionBoundary;
|