@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,1182 @@
|
|
|
1
|
+
import "./_web-crypto-random-bytes-Bo-GTcRS.js";
|
|
2
|
+
import "./_polyfill-buffer-patch-yNxN4d5E.js";
|
|
3
|
+
import "./libsodium-wrappers-BhbOA8dQ.js";
|
|
4
|
+
import "./codecs-Dc1Krpbt.js";
|
|
5
|
+
import { t as SecretBox } from "./secret-box-DUR0ACYz.js";
|
|
6
|
+
import { _ as CardanoRewardAccount, d as utxoKey, n as filterSpendableUtxos, r as getEligibleCollateralUtxo, s as isCardanoAddressOfSupportedNetwork, t as createInputResolver } from "./util-Cp5cZkfK.js";
|
|
7
|
+
import { t as ByteArray } from "./bytes.vo-BB7_4JK6.js";
|
|
8
|
+
import { t as BigNumber } from "./bignum.vo-CEXOIew0.js";
|
|
9
|
+
import { n as Ok$1, t as Err$1 } from "./asyncoption-CruEYOBI.js";
|
|
10
|
+
import { t as firstStateOfStatus } from "./first-state-of-status-unPynOuM.js";
|
|
11
|
+
import "./retry-config-Dmgt28wM.js";
|
|
12
|
+
import { t as ActivityType } from "./activity-type-GsJGWs-3.js";
|
|
13
|
+
import { t as CardanoNetworkId } from "./cardano-network-id.vo-Cfpvbod9.js";
|
|
14
|
+
import { r as LOVELACE_TOKEN_ID } from "./const-BJfIK_G-.js";
|
|
15
|
+
import { n as TransactionBuilder, s as InputSelectionError } from "./TransactionBuilder-bp2aMDhg.js";
|
|
16
|
+
import { t as applyVkeyWitnesses } from "./apply-vkey-witnesses-BKx3lcs0.js";
|
|
17
|
+
import { t as refuseExtensionAccount } from "./account-guards-D9Lu5T3W.js";
|
|
18
|
+
import { t as unwrapProviderResult } from "./unwrap-provider-result-BZSiwabU.js";
|
|
19
|
+
import { InMemoryKeyAgent, KeyPurpose, util } from "@laceio/cardano/key-management";
|
|
20
|
+
import { SodiumBip32Ed25519 } from "@laceio/cardano/crypto";
|
|
21
|
+
import { Cardano, Serialization, metadatum } from "@laceio/cardano/core";
|
|
22
|
+
import { HexBlob } from "@laceio/cardano/util";
|
|
23
|
+
import { catchError, combineLatest, concat, exhaustMap, filter, firstValueFrom, forkJoin, from, groupBy, map, merge, mergeMap, of, switchMap, take, throwError, timeout, timer } from "rxjs";
|
|
24
|
+
import { computeMinimumCoinQuantity, tokenBundleSizeExceedsLimit } from "@laceio/cardano/tx-construction";
|
|
25
|
+
//#region ../../packages/contract/cardano-context/src/value-objects/cardano-testnet-id.vo.ts
|
|
26
|
+
const CARDANO_CHAIN_ID_BY_TESTNET = {
|
|
27
|
+
preprod: Cardano.ChainIds.Preprod,
|
|
28
|
+
preview: Cardano.ChainIds.Preview,
|
|
29
|
+
sanchonet: Cardano.ChainIds.Sanchonet
|
|
30
|
+
};
|
|
31
|
+
const PREPROD_MAGIC = Number(Cardano.ChainIds.Preprod.networkMagic);
|
|
32
|
+
const PREVIEW_MAGIC = Number(Cardano.ChainIds.Preview.networkMagic);
|
|
33
|
+
const SANCHONET_MAGIC = Number(Cardano.ChainIds.Sanchonet.networkMagic);
|
|
34
|
+
const getCardanoTestnetIdByNetworkMagic = (networkMagic) => {
|
|
35
|
+
const magic = Number(networkMagic);
|
|
36
|
+
if (magic === PREPROD_MAGIC) return "preprod";
|
|
37
|
+
if (magic === PREVIEW_MAGIC) return "preview";
|
|
38
|
+
if (magic === SANCHONET_MAGIC) return "sanchonet";
|
|
39
|
+
};
|
|
40
|
+
const getCardanoChainIdByTestnetId = (id) => CARDANO_CHAIN_ID_BY_TESTNET[id];
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region ../../packages/module/blockchain-cardano/src/store/composer/resolve-validity-interval.ts
|
|
43
|
+
/** Two hours, matching the send flow's window (`build-tx.ts`). */
|
|
44
|
+
const DEFAULT_VALIDITY_SECONDS = 7200;
|
|
45
|
+
/**
|
|
46
|
+
* The era covering `slot`: the last summary that has already started.
|
|
47
|
+
* Summaries arrive oldest-first, so this walks forward while the next
|
|
48
|
+
* era's start is still at or below the slot.
|
|
49
|
+
*/
|
|
50
|
+
const eraSummaryAtSlot = (eraSummaries, slot) => {
|
|
51
|
+
let index = 0;
|
|
52
|
+
while (index + 1 < eraSummaries.length && eraSummaries[index + 1].start.slot <= slot) index++;
|
|
53
|
+
return eraSummaries[index];
|
|
54
|
+
};
|
|
55
|
+
const secondsToSlots = (seconds, slotLengthMs) => Math.ceil(seconds * 1e3 / slotLengthMs);
|
|
56
|
+
/**
|
|
57
|
+
* Convert a tip-relative duration into the absolute slots a Cardano
|
|
58
|
+
* validity interval needs.
|
|
59
|
+
*
|
|
60
|
+
* @throws If the era summaries are missing/unusable, or the requested
|
|
61
|
+
* window is not a positive, coherent interval.
|
|
62
|
+
*/
|
|
63
|
+
const resolveValidityInterval = ({ tipSlot, eraSummaries, validitySeconds = DEFAULT_VALIDITY_SECONDS, validityStartSeconds }) => {
|
|
64
|
+
if (eraSummaries.length === 0) throw new Error("Cannot resolve a validity interval: no Cardano era summaries available");
|
|
65
|
+
if (!Number.isFinite(validitySeconds) || validitySeconds <= 0) throw new Error(`Validity window must be a positive number of seconds, got ${validitySeconds}`);
|
|
66
|
+
const { slotLength } = eraSummaryAtSlot(eraSummaries, tipSlot).parameters;
|
|
67
|
+
if (!Number.isFinite(slotLength) || slotLength <= 0) throw new Error(`Era summary reports an unusable slot length: ${slotLength}`);
|
|
68
|
+
const invalidHereafter = Cardano.Slot(tipSlot + secondsToSlots(validitySeconds, slotLength));
|
|
69
|
+
if (validityStartSeconds === void 0) return { invalidHereafter };
|
|
70
|
+
if (!Number.isFinite(validityStartSeconds) || validityStartSeconds < 0) throw new Error(`Validity start must be a non-negative number of seconds, got ${validityStartSeconds}`);
|
|
71
|
+
const invalidBefore = Cardano.Slot(tipSlot + secondsToSlots(validityStartSeconds, slotLength));
|
|
72
|
+
if (invalidBefore >= invalidHereafter) throw new Error(`Validity window is empty: start slot ${invalidBefore} is not before end slot ${invalidHereafter}`);
|
|
73
|
+
return {
|
|
74
|
+
invalidBefore,
|
|
75
|
+
invalidHereafter
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region ../../packages/module/blockchain-cardano/src/store/composer/build-composer-tx.ts
|
|
80
|
+
/** Failure with a code the side-effect maps to actionable copy. */
|
|
81
|
+
const fail = (message, code) => Object.assign(new Error(message), { code });
|
|
82
|
+
const utxoRefKey = (txIn) => `${txIn.txId}#${txIn.index}`;
|
|
83
|
+
/**
|
|
84
|
+
* An address from the request, as the SDK's payment address.
|
|
85
|
+
*
|
|
86
|
+
* The SDK's own constructor throws an UNCODED `InvalidStringError`, which would
|
|
87
|
+
* reach the side-effect as a build fault rather than as the request mistake it
|
|
88
|
+
* is — a bech32 the user mistyped would then read as "we couldn't build your
|
|
89
|
+
* transaction" instead of "check what you entered".
|
|
90
|
+
*
|
|
91
|
+
* @param what - names the address in the message, since a request may carry
|
|
92
|
+
* several and the failure has to say which one is unusable.
|
|
93
|
+
*/
|
|
94
|
+
const toPaymentAddress = (value, what) => {
|
|
95
|
+
try {
|
|
96
|
+
return Cardano.PaymentAddress(value);
|
|
97
|
+
} catch {
|
|
98
|
+
throw fail(`${what} is not a Cardano address: "${value}"`, "invalid-address");
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Quantities cross the slice boundary as decimal strings, so a malformed
|
|
103
|
+
* one is a request error rather than a programming error — parse it into
|
|
104
|
+
* a coded failure instead of letting `BigInt` throw an uncoded SyntaxError.
|
|
105
|
+
*/
|
|
106
|
+
const toQuantity = (value, what) => {
|
|
107
|
+
if (!/^-?\d+$/.test(value)) throw fail(`${what} is not a whole number: "${value}"`, "invalid-output");
|
|
108
|
+
return BigInt(value);
|
|
109
|
+
};
|
|
110
|
+
const toValue = (output) => {
|
|
111
|
+
const coins = toQuantity(output.lovelace, `Lovelace amount for the output to ${output.address}`);
|
|
112
|
+
if (coins < 0n) throw fail(`Output to ${output.address} requests a negative amount of lovelace`, "invalid-output");
|
|
113
|
+
if (!output.assets || output.assets.length === 0) return { coins };
|
|
114
|
+
const assets = /* @__PURE__ */ new Map();
|
|
115
|
+
for (const asset of output.assets) {
|
|
116
|
+
const quantity = toQuantity(asset.quantity, `Quantity for asset ${asset.assetId}`);
|
|
117
|
+
if (quantity <= 0n) throw fail(`Asset ${asset.assetId} requests a non-positive quantity`, "invalid-output");
|
|
118
|
+
const assetId = asset.assetId;
|
|
119
|
+
assets.set(assetId, (assets.get(assetId) ?? 0n) + quantity);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
coins,
|
|
123
|
+
assets
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Raise the output's lovelace to the protocol minimum for its size when
|
|
128
|
+
* the request is below it. An assets-only output can therefore ask for
|
|
129
|
+
* `'0'` and still be spendable.
|
|
130
|
+
*/
|
|
131
|
+
const withMinimumCoin = (address, value, params) => {
|
|
132
|
+
if (tokenBundleSizeExceedsLimit(params.maxValueSize)(value.assets)) throw fail(`Output to ${address} exceeds the maximum token bundle size`, "invalid-output");
|
|
133
|
+
const minimumCoin = BigInt(computeMinimumCoinQuantity(params.coinsPerUtxoByte)({
|
|
134
|
+
address,
|
|
135
|
+
value
|
|
136
|
+
}));
|
|
137
|
+
return value.coins >= minimumCoin ? value : {
|
|
138
|
+
...value,
|
|
139
|
+
coins: minimumCoin
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
const parseMetadata = (request) => {
|
|
143
|
+
if (!request.metadata || request.metadata.length === 0) return void 0;
|
|
144
|
+
const blob = /* @__PURE__ */ new Map();
|
|
145
|
+
for (const entry of request.metadata) {
|
|
146
|
+
if (!/^\d+$/.test(entry.label)) throw fail(`Metadata label "${entry.label}" is not a non-negative integer`, "invalid-metadata");
|
|
147
|
+
let parsed;
|
|
148
|
+
try {
|
|
149
|
+
parsed = JSON.parse(entry.json);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
throw fail(`Metadata for label ${entry.label} is not valid JSON: ${error.message}`, "invalid-metadata");
|
|
152
|
+
}
|
|
153
|
+
blob.set(BigInt(entry.label), metadatum.jsonToMetadatum(parsed));
|
|
154
|
+
}
|
|
155
|
+
return blob;
|
|
156
|
+
};
|
|
157
|
+
const resolveSelectedInputs = (request, spendableUtxos) => {
|
|
158
|
+
if (!request.selectedInputs || request.selectedInputs.length === 0) return [];
|
|
159
|
+
const byRef = new Map(spendableUtxos.map((utxo) => [utxoRefKey(utxo[0]), utxo]));
|
|
160
|
+
return request.selectedInputs.map((ref) => {
|
|
161
|
+
const utxo = byRef.get(`${ref.txId}#${ref.index}`);
|
|
162
|
+
if (!utxo) throw fail(`Selected input ${ref.txId}#${ref.index} is not among the account's spendable UTxOs`, "input-unavailable");
|
|
163
|
+
return utxo;
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* The balancer's own failure type is the only signal that the account cannot
|
|
168
|
+
* cover what was asked for — an unaffordable amount is a request mistake, not a
|
|
169
|
+
* build fault, and only the coded form reaches the copy that says so.
|
|
170
|
+
*
|
|
171
|
+
* Tagged rather than replaced: the reported name and message stay the
|
|
172
|
+
* balancer's, which is what names the shortfall for a diagnostic.
|
|
173
|
+
*/
|
|
174
|
+
const codeInputSelectionFailure = async (build) => {
|
|
175
|
+
try {
|
|
176
|
+
return await build;
|
|
177
|
+
} catch (error) {
|
|
178
|
+
if (error instanceof InputSelectionError) throw Object.assign(error, { code: "insufficient-funds" });
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const buildComposerTx = async ({ request, changeAddress, networkMagic, protocolParameters, spendableUtxos, tipSlot, eraSummaries }) => {
|
|
183
|
+
if (request.outputs.length === 0) throw fail("A composed transaction needs at least one output", "no-outputs");
|
|
184
|
+
if (spendableUtxos.length === 0) throw fail("The account has no spendable UTxOs to fund this transaction", "no-utxos");
|
|
185
|
+
const validityInterval = resolveValidityInterval({
|
|
186
|
+
tipSlot,
|
|
187
|
+
eraSummaries,
|
|
188
|
+
validitySeconds: request.validitySeconds,
|
|
189
|
+
validityStartSeconds: request.validityStartSeconds
|
|
190
|
+
});
|
|
191
|
+
const selectedInputs = resolveSelectedInputs(request, spendableUtxos);
|
|
192
|
+
const selectedReferences = new Set(selectedInputs.map((utxo) => utxoRefKey(utxo[0])));
|
|
193
|
+
const coverUtxos = spendableUtxos.filter((utxo) => !selectedReferences.has(utxoRefKey(utxo[0])));
|
|
194
|
+
const builder = new TransactionBuilder(networkMagic, protocolParameters).setChangeAddress(changeAddress).setUnspentOutputs(coverUtxos).setValidityInterval(validityInterval);
|
|
195
|
+
for (const utxo of selectedInputs) builder.addInput(utxo);
|
|
196
|
+
const metadataBlob = parseMetadata(request);
|
|
197
|
+
if (metadataBlob) for (const [label, value] of metadataBlob) builder.setMetadata(label, value);
|
|
198
|
+
for (const output of request.outputs) {
|
|
199
|
+
const address = toPaymentAddress(output.address, "The address of an output");
|
|
200
|
+
builder.addOutput({
|
|
201
|
+
address,
|
|
202
|
+
value: withMinimumCoin(address, toValue(output), protocolParameters)
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
const transaction = await codeInputSelectionFailure(builder.build());
|
|
206
|
+
return {
|
|
207
|
+
cbor: transaction.toCbor(),
|
|
208
|
+
txId: transaction.getId(),
|
|
209
|
+
fee: transaction.toCore().body.fee
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
//#endregion
|
|
213
|
+
//#region ../../packages/module/blockchain-cardano/src/store/composer/build-side-effect.ts
|
|
214
|
+
const GENERIC_BUILD_ERROR_KEYS$1 = {
|
|
215
|
+
title: "v2.composer.build.error.title",
|
|
216
|
+
subtitle: "v2.composer.build.error.subtitle"
|
|
217
|
+
};
|
|
218
|
+
const BUILD_ERROR_KEYS_BY_CODE$1 = {
|
|
219
|
+
"no-utxos": {
|
|
220
|
+
title: "v2.composer.build.error.no-utxos.title",
|
|
221
|
+
subtitle: "v2.composer.build.error.no-utxos.subtitle"
|
|
222
|
+
},
|
|
223
|
+
"no-outputs": {
|
|
224
|
+
title: "v2.composer.build.error.invalid-request.title",
|
|
225
|
+
subtitle: "v2.composer.build.error.invalid-request.subtitle"
|
|
226
|
+
},
|
|
227
|
+
"invalid-output": {
|
|
228
|
+
title: "v2.composer.build.error.invalid-request.title",
|
|
229
|
+
subtitle: "v2.composer.build.error.invalid-request.subtitle"
|
|
230
|
+
},
|
|
231
|
+
"invalid-metadata": {
|
|
232
|
+
title: "v2.composer.build.error.invalid-request.title",
|
|
233
|
+
subtitle: "v2.composer.build.error.invalid-request.subtitle"
|
|
234
|
+
},
|
|
235
|
+
"input-unavailable": {
|
|
236
|
+
title: "v2.composer.build.error.invalid-request.title",
|
|
237
|
+
subtitle: "v2.composer.build.error.invalid-request.subtitle"
|
|
238
|
+
},
|
|
239
|
+
"invalid-address": {
|
|
240
|
+
title: "v2.composer.build.error.invalid-request.title",
|
|
241
|
+
subtitle: "v2.composer.build.error.invalid-request.subtitle"
|
|
242
|
+
},
|
|
243
|
+
"insufficient-funds": {
|
|
244
|
+
title: "v2.composer.build.error.invalid-request.title",
|
|
245
|
+
subtitle: "v2.composer.build.error.invalid-request.subtitle"
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
const failure$1 = (error, code) => ({
|
|
249
|
+
success: false,
|
|
250
|
+
error: {
|
|
251
|
+
name: error.name,
|
|
252
|
+
message: error.message
|
|
253
|
+
},
|
|
254
|
+
errorTranslationKeys: (code ? BUILD_ERROR_KEYS_BY_CODE$1[code] : void 0) ?? GENERIC_BUILD_ERROR_KEYS$1
|
|
255
|
+
});
|
|
256
|
+
const buildComposition = async (state, stateObservables, dependencies) => {
|
|
257
|
+
try {
|
|
258
|
+
const { accountId, request } = state;
|
|
259
|
+
const cardano = dependencies.txExecutorCardano;
|
|
260
|
+
const cardanoContext = stateObservables.cardanoContext;
|
|
261
|
+
const [networkMagic, protocolParameters, tip, eraSummaries, accountUtxos, unspendableUtxos, addresses] = await Promise.all([
|
|
262
|
+
firstValueFrom(cardano.cardanoNetworkMagic$),
|
|
263
|
+
firstValueFrom(cardanoContext.selectProtocolParameters$),
|
|
264
|
+
firstValueFrom(cardanoContext.selectTip$),
|
|
265
|
+
firstValueFrom(cardanoContext.selectEraSummaries$),
|
|
266
|
+
firstValueFrom(cardano.cardanoAccountUtxos$),
|
|
267
|
+
firstValueFrom(cardano.cardanoAccountUnspendableUtxos$),
|
|
268
|
+
firstValueFrom(cardano.cardanoAddresses$)
|
|
269
|
+
]);
|
|
270
|
+
if (networkMagic === void 0) throw new Error("Cardano network magic not available");
|
|
271
|
+
if (!protocolParameters) throw new Error("Cardano protocol parameters not available");
|
|
272
|
+
if (!tip) throw new Error("Cardano chain tip not available");
|
|
273
|
+
if (!eraSummaries) throw new Error("Cardano era summaries not available");
|
|
274
|
+
refuseExtensionAccount(accountId, addresses);
|
|
275
|
+
const primary = addresses.filter((address) => address.accountId === accountId && address.blockchainName === "Cardano")[0];
|
|
276
|
+
if (!primary) throw new Error("No Cardano addresses found for account");
|
|
277
|
+
const result = await buildComposerTx({
|
|
278
|
+
request,
|
|
279
|
+
changeAddress: toPaymentAddress(request.changeAddress ?? primary.address, "The change address"),
|
|
280
|
+
networkMagic,
|
|
281
|
+
protocolParameters,
|
|
282
|
+
spendableUtxos: filterSpendableUtxos(accountUtxos[accountId] ?? [], unspendableUtxos[accountId] ?? []),
|
|
283
|
+
tipSlot: Number(tip.slot),
|
|
284
|
+
eraSummaries
|
|
285
|
+
});
|
|
286
|
+
return {
|
|
287
|
+
success: true,
|
|
288
|
+
serializedTx: result.cbor,
|
|
289
|
+
txId: result.txId,
|
|
290
|
+
fees: [{
|
|
291
|
+
tokenId: LOVELACE_TOKEN_ID,
|
|
292
|
+
amount: BigNumber(result.fee)
|
|
293
|
+
}]
|
|
294
|
+
};
|
|
295
|
+
} catch (error) {
|
|
296
|
+
return failure$1(error instanceof Error ? error : new Error(String(error)), error.code);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
const makeComposerBuilding = () => (_, stateObservables, dependencies) => firstStateOfStatus(stateObservables.composerFlow.selectState$, "Building").pipe(switchMap((state) => from(buildComposition(state, stateObservables, dependencies)).pipe(map((result) => dependencies.actions.composerFlow.buildCompleted({
|
|
300
|
+
accountId: state.accountId,
|
|
301
|
+
result
|
|
302
|
+
})))));
|
|
303
|
+
//#endregion
|
|
304
|
+
//#region ../../packages/module/blockchain-cardano/src/store/composer-flow-side-effects.ts
|
|
305
|
+
const composerFlowSideEffects = [makeComposerBuilding()];
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region ../../packages/module/blockchain-cardano/src/store/dependencies.ts
|
|
308
|
+
const initializeDependencies = async (_, { logger }) => ({ cardanoInMemorySigning: { signTransaction: (props) => forkJoin([from(SodiumBip32Ed25519.create()), from(util.createTxInKeyPathMap(props.tx.body().toCore(), props.knownAddresses, createInputResolver(props.utxo)))]).pipe(mergeMap(([bip32Ed25519, txInKeyPathMap]) => {
|
|
309
|
+
const encryptedRootPrivateKeyBytes = ByteArray.fromHex(props.encryptedRootPrivateKey);
|
|
310
|
+
return from(new InMemoryKeyAgent({
|
|
311
|
+
accountIndex: props.accountIndex,
|
|
312
|
+
chainId: props.chainId,
|
|
313
|
+
encryptedRootPrivateKeyBytes: [...encryptedRootPrivateKeyBytes],
|
|
314
|
+
extendedAccountPublicKey: props.extendedAccountPublicKey,
|
|
315
|
+
getPassphrase: async () => props.authSecret,
|
|
316
|
+
purpose: KeyPurpose.STANDARD
|
|
317
|
+
}, {
|
|
318
|
+
bip32Ed25519,
|
|
319
|
+
logger,
|
|
320
|
+
rootPrivateKeyEncryption: SecretBox.isSealed(encryptedRootPrivateKeyBytes) ? {
|
|
321
|
+
encrypt: SecretBox.seal,
|
|
322
|
+
decrypt: SecretBox.open
|
|
323
|
+
} : void 0
|
|
324
|
+
}).signTransaction(props.tx.body(), {
|
|
325
|
+
knownAddresses: props.knownAddresses,
|
|
326
|
+
txInKeyPathMap,
|
|
327
|
+
scripts: props.tx.toCore().witness.scripts
|
|
328
|
+
})).pipe(map((signatures) => {
|
|
329
|
+
const witnessSet = props.tx.witnessSet();
|
|
330
|
+
applyVkeyWitnesses(witnessSet, signatures);
|
|
331
|
+
props.tx.setWitnessSet(witnessSet);
|
|
332
|
+
return Ok$1(props.tx);
|
|
333
|
+
}));
|
|
334
|
+
}), catchError((error) => of(Err$1({
|
|
335
|
+
code: "SIGNING_FAILED",
|
|
336
|
+
message: error.message
|
|
337
|
+
})))) } });
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region ../../packages/lib/cnight-dust-designation/src/constants.ts
|
|
340
|
+
const LOVELACE_FOR_REGISTRATION = 1586080n;
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region ../../packages/lib/cnight-dust-designation/src/errors.ts
|
|
343
|
+
const Ok = (value) => ({
|
|
344
|
+
ok: true,
|
|
345
|
+
value
|
|
346
|
+
});
|
|
347
|
+
const Err = (error) => ({
|
|
348
|
+
ok: false,
|
|
349
|
+
error
|
|
350
|
+
});
|
|
351
|
+
//#endregion
|
|
352
|
+
//#region ../../packages/lib/cnight-dust-designation/src/value-objects/network-id.vo.ts
|
|
353
|
+
const CardanoDustNetwork = {
|
|
354
|
+
mainnet: "mainnet",
|
|
355
|
+
testnet: "testnet",
|
|
356
|
+
fromNetworkMagic: (networkMagic) => networkMagic === 764824073 ? CardanoDustNetwork.mainnet : CardanoDustNetwork.testnet,
|
|
357
|
+
toNetworkId: (network) => network === CardanoDustNetwork.mainnet ? 1 : 0
|
|
358
|
+
};
|
|
359
|
+
//#endregion
|
|
360
|
+
//#region ../../packages/lib/cnight-dust-designation/src/cnight-asset.ts
|
|
361
|
+
const TESTNET_CNIGHT_POLICY_ID = Cardano.PolicyId("d2dbff622e509dda256fedbd31ef6e9fd98ed49ad91d5c0e07f68af1");
|
|
362
|
+
const TESTNET_CNIGHT_ASSET_NAME = Cardano.AssetName("");
|
|
363
|
+
const MAINNET_CNIGHT_POLICY_ID = Cardano.PolicyId("0691b2fecca1ac4f53cb6dfb00b7013e561d1f34403b957cbb5af1fa");
|
|
364
|
+
/** "NIGHT" in hex — the mainnet cNIGHT token is named NIGHT. */
|
|
365
|
+
const MAINNET_CNIGHT_ASSET_NAME = Cardano.AssetName("4e49474854");
|
|
366
|
+
const getCnightAssetId = (network) => {
|
|
367
|
+
const policyId = network === CardanoDustNetwork.mainnet ? MAINNET_CNIGHT_POLICY_ID : TESTNET_CNIGHT_POLICY_ID;
|
|
368
|
+
const assetName = network === CardanoDustNetwork.mainnet ? MAINNET_CNIGHT_ASSET_NAME : TESTNET_CNIGHT_ASSET_NAME;
|
|
369
|
+
return Cardano.AssetId.fromParts(policyId, assetName);
|
|
370
|
+
};
|
|
371
|
+
//#endregion
|
|
372
|
+
//#region ../../packages/lib/cnight-dust-designation/src/scripts/mainnet.ts
|
|
373
|
+
const CNIGHT_GENERATES_DUST_MAINNET_CBOR = "590c8401010029800aba4aba2aba1aba0aab9faab9eaab9dab9cab9a488888888a60022a6600492119657870656374205b782c202e2e726573745d203d206c69737400168a9980124929657870656374205b506169722822222c2031295d203d20746f6b656e73207c3e20746f5f706169727300168a9980124936657870656374206275696c74696e2e6c656e6774685f6f665f62797465617272617928647573745f6164647265737329203c3d20333300168a998012495365787065637420447573744d617070696e67446174756d207b20635f77616c6c65742c20647573745f61646472657373207d203d0a2020202020202020202020202020202020206f75747075745f646174756d00168a998012493065787065637420447573744d617070696e67446174756d207b20635f77616c6c65742c202e2e207d203d20646174756d00164888896600330013009375401f2300d300e001911919800800801912cc00400629422b3001300330100018a518998010011808800a0144039370e90004dc3a40052232330010010032259800800c026264b300130040018800c4cc00c00cc04800900b1808000a01c9b874801122222229800980a003cc040dd51809803c88966002600e60246ea800e264646600200200844b30010018a508acc004cdc79bae30190010038a51899801001180d000a026405c6eb8c058c04cdd5001c4cc0200048cdd798098008022020911192cc004c020006264b3001001801c4c966002003004802401200913259800980d801c01a00a80c0dd7000a0363018001405860286ea80122b300130070018992cc00400600713259800800c01200900480244c9660026036007006802a030375c00280d8c060005016180a1baa0048012022404460246ea800d22223322323298009bab301b0019bac301b301c301c0019bac301b007980b9baa0039bac301b0049bab301b0024888889660026024007133225980099baf30230104c103d87980008acc00401a2a6603c9211b657870656374205b696e7075742c202e2e5d203d20696e7075747300168992cc0040062b300130153020375400313259800800c06e264b30010018992cc00400603b13259800800c07a03d01e80f44c966002605400719800802456600266e24dc6800a408519800802403601c80a2040811a03e809a03e8138dd7000a05430270014094604e00501c80e40720388140c09400502318109baa00180d203c80d406a03501a409864b300132330010010082259800800c528456600266ebcc098c08cdd51813000801c528c4cc008008c09c00502020488992cc00400603b13259800981380144c96600266e3d220100375c6046005159800980b800c4c8c96600264b30010018a99812a48130657870656374205b5f2c202e2e6e66745d203d2076616c7565207c3e20746f5f64696374207c3e20746f5f70616972730016899baf374c60560026e98cc0a4cdd81ba9009374c6605266ec13010140004c010101004bd6f7b63025eb7bdb1810281bab30290018992cc004c060c098dd5000c4c0a8c09cdd5000c54cc09524012165787065637420496e6c696e65446174756d28646174756d29203d20646174756d001640906052605400315330244901266578706563742069735f73696e676c65746f6e2876616c75652c20706f6c6963792c202222290016408c6052604a6ea8cc05c0248cdd7981498131baa30293026375400200466e95200233026375200c97ae080fa04280fa042375a604600301e4090604a0028118dd5981099801002119b8f375c6042002009153301f49016b6578706563740a202020206c6973742e616e79280a202020202020696e707574732c0a202020202020666e28696e7075743a20496e70757429207b20696e7075742e6f75747075745f7265666572656e6365203d3d206f6e655f73686f745f726566207d2c0a202020202900164078604660406ea8c08c01902144c96600266ebcdd31981199bb04c10140003750653001001804520004004444b30010028800c660020073028002acc004cdd7981398121baa302730243754603460486ea8c09c008012266e0000520018800a042400c81292f5bded8c0604266004008466e3cdd71810800802456600330013371e0069111c0691b2fecca1ac4f53cb6dfb00b7013e561d1f34403b957cbb5af1fa00a50a5140791980099b8f003489076d61696e6e657400a50a51407914a080f2294101e19ba548008cc088dd480125eb8101d1bae3021301e375401244646600200200644b300100180f44c96600260080031001899801801981380120403025001408d1598009807801c4c9660026024603c6ea800626464944ca6002003007802a002222598008014400633001003981380156600266ebcc098c08cdd5181318119baa301930233754604c00400b159800800c54cc0852413f657870656374205b4f7574707574207b20616464726573732c2076616c75652c20646174756d2c202e2e207d2c202e2e726573745d203d206f757470757473001689919912cc004cdd7981498131baa30290030088992cc0040062a6604a920133657870656374205b5f2c202e2e6e66745f69645d203d2076616c7565207c3e20746f5f64696374207c3e20746f5f706169727300168acc004cdd79ba6302b0010088992cc004c064c09cdd5000c4c966002003159800980e98141baa0018992cc00400604713259800800c4c9660020030258992cc00400604d026813409a264b300130320038cc0040122b3001337126e3400520428acc006600200901580b20388804c54cc0b12413b65787065637420636865636b5f6175746828635f77616c6c65742c2065787472615f7369676e61746f726965732c207769746864726177616c7329001640ad02840ad027406d02740bc6eb80050321817800a05a302f002812409204902440c0605a0028158c0a4dd5000c089026408a045022811205c302b3028375400315330264912865787065637420496e6c696e65446174756d286f75747075745f646174756d29203d20646174756d001640946054605600715330254901266578706563742061735f64617461286e66745f696429203d3d2065787065637465645f6e6674001640908140dd59814801454cc09124012d65787065637420616464726573732e7061796d656e745f63726564656e7469616c203d3d206f776e5f637265640016408c6050002605000460466ea8c09800502444005020200640906e98cc084cdd81811180f9baa0014c0103a14001004bd6f7b630454cc07524012265787065637420536372697074286f776e5f6861736829203d206f776e5f63726564001640706042603c6ea80262b3001301100389919912cc004c054c080dd5000c4c966002003159800980b18109baa0018992cc00400603713259800800c4c96600200301d8992cc00400603d01e80f407a264b3001302b0038cc004012264b3001301b3027375400313259800cc00401a021011405d15980099b880014800229462b30013301e01123375e60520020071301d0018a5040988132294102619192cc004c074c0a4dd5000c5200089bad302d302a37540028138c966002603a60526ea80062980103d87a8000899198008009bab302e302b375400444b30010018a6103d87a8000899192cc004cdc8a45000018acc004cdc7a44100001899ba548000cc0c0c0b80092f5c114c0103d87a800040ad133004004303200340ac6eb8c0b0004c0bc00502d204e323300100100d2259800800c5300103d87a8000899192cc004cdc8802800c56600266e3c014006266e9520003302f302d0024bd7045300103d87a800040a9133004004303100340a86eb8c0ac004c0b800502c1bae302b3028375400315330264919165787065637420536372697074286f776e5f686173682920617320736372697074203d0a202020202020202020206d7573745f66696e6428696e707574732c20666e28696e70757429207b20696e7075742e6f75747075745f7265666572656e6365203d3d206f7574707574207d292e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c001640946054604e6ea8c0a8c09cdd5180e98139baa3301900d23375e605660506ea800402603e80a203e8140dd7000a05630280014098605000501c80e40720388148c09800502418111baa00180d203e80d406a03501a409c604860426ea80062a6603e9211a65787065637420536f6d6528646174756d29203d20646174756d00164078604400260446046002603c6ea80262b30013370e9003001c5660026024603a6ea8c084c088c078dd5004c528c5901b45901b2036406c80d8603660360026034603400460306030006602e603000845268a99803a491856616c696461746f722072657475726e65642066616c7365001365640181";
|
|
374
|
+
//#endregion
|
|
375
|
+
//#region ../../packages/lib/cnight-dust-designation/src/scripts/testnet.ts
|
|
376
|
+
const CNIGHT_GENERATES_DUST_TESTNET_CBOR = "590c6801010029800aba4aba2aba1aba0aab9faab9eaab9dab9cab9a488888888a60022a6600492119657870656374205b782c202e2e726573745d203d206c69737400168a9980124929657870656374205b506169722822222c2031295d203d20746f6b656e73207c3e20746f5f706169727300168a9980124936657870656374206275696c74696e2e6c656e6774685f6f665f62797465617272617928647573745f6164647265737329203c3d20333300168a998012495365787065637420447573744d617070696e67446174756d207b20635f77616c6c65742c20647573745f61646472657373207d203d0a2020202020202020202020202020202020206f75747075745f646174756d00168a998012493065787065637420447573744d617070696e67446174756d207b20635f77616c6c65742c202e2e207d203d20646174756d00164888896600330013009375401f2300d300e001911919800800801912cc00400629422b3001300330100018a518998010011808800a0144039370e90004dc3a40052232330010010032259800800c026264b300130040018800c4cc00c00cc04800900b1808000a01c9b874801122222229800980a003cc040dd51809803c88966002600e60246ea800e264646600200200844b30010018a508acc004cdc79bae30190010038a51899801001180d000a026405c6eb8c058c04cdd5001c4cc0200048cdd798098008022020911192cc004c020006264b3001001801c4c966002003004802401200913259800980d801c01a00a80c0dd7000a0363018001405860286ea80122b300130070018992cc00400600713259800800c01200900480244c9660026036007006802a030375c00280d8c060005016180a1baa0048012022404460246ea800d22223322323298009bab301b0019bac301b301c301c0019bac301b007980b9baa0039bac301b0049bab301b0024888889660026024007133225980099baf30230104c103d87980008acc00401a2a6603c9211b657870656374205b696e7075742c202e2e5d203d20696e7075747300168992cc0040062b300130153020375400313259800800c06e264b30010018992cc00400603b13259800800c07a03d01e80f44c966002605400719800802456600266e24dc6800a408519800802403601c80a2040811a03e809a03e8138dd7000a05430270014094604e00501c80e40720388140c09400502318109baa00180d203c80d406a03501a409864b300132330010010082259800800c528456600266ebcc098c08cdd51813000801c528c4cc008008c09c00502020488992cc00400603b13259800981380144c96600266e3d220100375c6046005159800980b800c4c8c96600264b30010018a99812a48130657870656374205b5f2c202e2e6e66745d203d2076616c7565207c3e20746f5f64696374207c3e20746f5f70616972730016899baf374c60560026e98cc0a4cdd81ba9009374c6605266ec13010140004c010101004bd6f7b63025eb7bdb1810281bab30290018992cc004c060c098dd5000c4c0a8c09cdd5000c54cc09524012165787065637420496e6c696e65446174756d28646174756d29203d20646174756d001640906052605400315330244901266578706563742069735f73696e676c65746f6e2876616c75652c20706f6c6963792c202222290016408c6052604a6ea8cc05c0248cdd7981498131baa30293026375400200466e95200233026375200c97ae080fa04280fa042375a604600301e4090604a0028118dd5981099801002119b8f375c6042002009153301f49016b6578706563740a202020206c6973742e616e79280a202020202020696e707574732c0a202020202020666e28696e7075743a20496e70757429207b20696e7075742e6f75747075745f7265666572656e6365203d3d206f6e655f73686f745f726566207d2c0a202020202900164078604660406ea8c08c01902144c96600266ebcdd31981199bb04c10140003750653001001804520004004444b30010028800c660020073028002acc004cdd7981398121baa302730243754603460486ea8c09c008012266e0000520018800a042400c81292f5bded8c0604266004008466e3cdd7181080080246600266e3c00d22011cd2dbff622e509dda256fedbd31ef6e9fd98ed49ad91d5c0e07f68af100a50a51407914a080f0cdd2a4004660446ea40092f5c080e8dd71810980f1baa0092232330010010032259800800c07a264b300130040018800c4cc00c00cc09c0090201812800a0468acc004c03c00e264b30013012301e3754003132324a2653001001803c0150011112cc00400a200319800801cc09c00ab30013375e604c60466ea8c098c08cdd5180c98119baa30260020058acc0040062a660429213f657870656374205b4f7574707574207b20616464726573732c2076616c75652c20646174756d2c202e2e207d2c202e2e726573745d203d206f757470757473001689919912cc004cdd7981498131baa30290030088992cc0040062a6604a920133657870656374205b5f2c202e2e6e66745f69645d203d2076616c7565207c3e20746f5f64696374207c3e20746f5f706169727300168acc004cdd79ba6302b0010088992cc004c064c09cdd5000c4c966002003159800980e98141baa0018992cc00400604713259800800c4c9660020030258992cc00400604d026813409a264b300130320038cc0040122b3001337126e3400520428acc006600200901580b20388804c54cc0b12413b65787065637420636865636b5f6175746828635f77616c6c65742c2065787472615f7369676e61746f726965732c207769746864726177616c7329001640ad02840ad027406d02740bc6eb80050321817800a05a302f002812409204902440c0605a0028158c0a4dd5000c089026408a045022811205c302b3028375400315330264912865787065637420496e6c696e65446174756d286f75747075745f646174756d29203d20646174756d001640946054605600715330254901266578706563742061735f64617461286e66745f696429203d3d2065787065637465645f6e6674001640908140dd59814801454cc09124012d65787065637420616464726573732e7061796d656e745f63726564656e7469616c203d3d206f776e5f637265640016408c6050002605000460466ea8c09800502444005020200640906e98cc084cdd81811180f9baa0014c0103a14001004bd6f7b630454cc07524012265787065637420536372697074286f776e5f6861736829203d206f776e5f63726564001640706042603c6ea80262b3001301100389919912cc004c054c080dd5000c4c966002003159800980b18109baa0018992cc00400603713259800800c4c96600200301d8992cc00400603d01e80f407a264b3001302b0038cc004012264b3001301b3027375400313259800cc00401a021011405d15980099b880014800229462b30013301e01123375e60520020071301d0018a5040988132294102619192cc004c074c0a4dd5000c5200089bad302d302a37540028138c966002603a60526ea80062980103d87a8000899198008009bab302e302b375400444b30010018a6103d87a8000899192cc004cdc8a45000018acc004cdc7a44100001899ba548000cc0c0c0b80092f5c114c0103d87a800040ad133004004303200340ac6eb8c0b0004c0bc00502d204e323300100100d2259800800c5300103d87a8000899192cc004cdc8802800c56600266e3c014006266e9520003302f302d0024bd7045300103d87a800040a9133004004303100340a86eb8c0ac004c0b800502c1bae302b3028375400315330264919165787065637420536372697074286f776e5f686173682920617320736372697074203d0a202020202020202020206d7573745f66696e6428696e707574732c20666e28696e70757429207b20696e7075742e6f75747075745f7265666572656e6365203d3d206f7574707574207d292e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c001640946054604e6ea8c0a8c09cdd5180e98139baa3301900d23375e605660506ea800402603e80a203e8140dd7000a05630280014098605000501c80e40720388148c09800502418111baa00180d203e80d406a03501a409c604860426ea80062a6603e9211a65787065637420536f6d6528646174756d29203d20646174756d00164078604400260446046002603c6ea80262b30013370e9003001c5660026024603a6ea8c084c088c078dd5004c528c5901b45901b2036406c80d8603660360026034603400460306030006602e603000845268a99803a491856616c696461746f722072657475726e65642066616c7365001365640181";
|
|
377
|
+
//#endregion
|
|
378
|
+
//#region ../../packages/lib/cnight-dust-designation/src/scripts/index.ts
|
|
379
|
+
const cborWrapHexBytes = (payloadHex) => {
|
|
380
|
+
const lengthBytes = payloadHex.length / 2;
|
|
381
|
+
let header;
|
|
382
|
+
if (lengthBytes < 24) header = (64 | lengthBytes).toString(16).padStart(2, "0");
|
|
383
|
+
else if (lengthBytes < 256) header = "58" + lengthBytes.toString(16).padStart(2, "0");
|
|
384
|
+
else if (lengthBytes < 65536) header = "59" + lengthBytes.toString(16).padStart(4, "0");
|
|
385
|
+
else if (lengthBytes < 4294967296) header = "5a" + lengthBytes.toString(16).padStart(8, "0");
|
|
386
|
+
else throw new Error(`script too large to CBOR-wrap (${lengthBytes} bytes)`);
|
|
387
|
+
return header + payloadHex;
|
|
388
|
+
};
|
|
389
|
+
const getDustGeneratorScriptCbor = (network) => HexBlob(cborWrapHexBytes(network === CardanoDustNetwork.mainnet ? CNIGHT_GENERATES_DUST_MAINNET_CBOR : CNIGHT_GENERATES_DUST_TESTNET_CBOR));
|
|
390
|
+
const getDustGeneratorPlutusV3Script = (network) => Serialization.PlutusV3Script.fromCbor(getDustGeneratorScriptCbor(network));
|
|
391
|
+
//#endregion
|
|
392
|
+
//#region ../../packages/lib/cnight-dust-designation/src/plutus/datum.ts
|
|
393
|
+
const encodeCWallet = (cWallet) => {
|
|
394
|
+
const fields = new Serialization.PlutusList();
|
|
395
|
+
const hashBytes = cWallet.kind === "verificationKey" ? cWallet.stakeKeyHash : cWallet.scriptHash;
|
|
396
|
+
fields.add(Serialization.PlutusData.newBytes(hashBytes));
|
|
397
|
+
const alternative = cWallet.kind === "verificationKey" ? 0n : 1n;
|
|
398
|
+
return Serialization.PlutusData.newConstrPlutusData(new Serialization.ConstrPlutusData(alternative, fields));
|
|
399
|
+
};
|
|
400
|
+
const encodeDustMappingDatum = (value) => {
|
|
401
|
+
const fields = new Serialization.PlutusList();
|
|
402
|
+
fields.add(encodeCWallet(value.cWallet));
|
|
403
|
+
fields.add(Serialization.PlutusData.newBytes(value.dustAddress));
|
|
404
|
+
return Serialization.PlutusData.newConstrPlutusData(new Serialization.ConstrPlutusData(0n, fields));
|
|
405
|
+
};
|
|
406
|
+
const dustMappingDatumToCbor = (value) => encodeDustMappingDatum(value).toCbor();
|
|
407
|
+
var CardanoStakeKeyHashError = class extends Error {
|
|
408
|
+
code;
|
|
409
|
+
constructor(message) {
|
|
410
|
+
super(message);
|
|
411
|
+
this.name = "CardanoStakeKeyHashError";
|
|
412
|
+
this.code = "invalid-length";
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
const CardanoStakeKeyHash = (bytes) => {
|
|
416
|
+
if (bytes.length !== 28) throw new CardanoStakeKeyHashError(`CardanoStakeKeyHash expects 28 bytes, got ${bytes.length}`);
|
|
417
|
+
return bytes;
|
|
418
|
+
};
|
|
419
|
+
CardanoStakeKeyHash.toHex = (hash) => Array.from(hash).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
420
|
+
CardanoStakeKeyHash.fromHex = (hex) => {
|
|
421
|
+
const normalised = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
422
|
+
if (normalised.length !== 56) throw new CardanoStakeKeyHashError(`CardanoStakeKeyHash hex expects 56 chars, got ${normalised.length}`);
|
|
423
|
+
if (!/^[0-9a-fA-F]+$/.test(normalised)) throw new CardanoStakeKeyHashError(`CardanoStakeKeyHash hex contains non-hex characters: ${hex}`);
|
|
424
|
+
const bytes = new Uint8Array(28);
|
|
425
|
+
for (let index = 0; index < bytes.length; index++) bytes[index] = parseInt(normalised.slice(index * 2, index * 2 + 2), 16);
|
|
426
|
+
return CardanoStakeKeyHash(bytes);
|
|
427
|
+
};
|
|
428
|
+
var MidnightCoinPubkeyError = class extends Error {
|
|
429
|
+
code;
|
|
430
|
+
constructor(code, message) {
|
|
431
|
+
super(message);
|
|
432
|
+
this.name = "MidnightCoinPubkeyError";
|
|
433
|
+
this.code = code;
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
const MidnightCoinPubkey = (bytes) => {
|
|
437
|
+
if (bytes.length > 33) throw new MidnightCoinPubkeyError("invalid-length", `MidnightCoinPubkey accepts at most 33 bytes, got ${bytes.length}`);
|
|
438
|
+
return bytes;
|
|
439
|
+
};
|
|
440
|
+
MidnightCoinPubkey.toHex = (pubkey) => Array.from(pubkey).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region ../../packages/lib/cnight-dust-designation/src/plutus/datum-decode.ts
|
|
443
|
+
const decodeDustMappingDatum = (cbor) => {
|
|
444
|
+
let data;
|
|
445
|
+
try {
|
|
446
|
+
data = Serialization.PlutusData.fromCbor(HexBlob(cbor.toString()));
|
|
447
|
+
} catch {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
const outer = data.asConstrPlutusData();
|
|
451
|
+
if (!outer || outer.getAlternative() !== 0n) return void 0;
|
|
452
|
+
const fields = outer.getData();
|
|
453
|
+
if (fields.getLength() !== 2) return void 0;
|
|
454
|
+
const cWalletData = fields.get(0).asConstrPlutusData();
|
|
455
|
+
if (!cWalletData) return void 0;
|
|
456
|
+
const cWalletFields = cWalletData.getData();
|
|
457
|
+
if (cWalletFields.getLength() !== 1) return void 0;
|
|
458
|
+
const credBytes = cWalletFields.get(0).asBoundedBytes();
|
|
459
|
+
if (!credBytes || credBytes.length !== 28) return void 0;
|
|
460
|
+
let cWallet;
|
|
461
|
+
if (cWalletData.getAlternative() === 0n) cWallet = {
|
|
462
|
+
kind: "verificationKey",
|
|
463
|
+
stakeKeyHash: CardanoStakeKeyHash(credBytes)
|
|
464
|
+
};
|
|
465
|
+
else if (cWalletData.getAlternative() === 1n) cWallet = {
|
|
466
|
+
kind: "script",
|
|
467
|
+
scriptHash: credBytes
|
|
468
|
+
};
|
|
469
|
+
else return;
|
|
470
|
+
const dustBytes = fields.get(1).asBoundedBytes();
|
|
471
|
+
if (!dustBytes || dustBytes.length > 33) return void 0;
|
|
472
|
+
let dustAddress;
|
|
473
|
+
try {
|
|
474
|
+
dustAddress = MidnightCoinPubkey(dustBytes);
|
|
475
|
+
} catch {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
return {
|
|
479
|
+
cWallet,
|
|
480
|
+
dustAddress
|
|
481
|
+
};
|
|
482
|
+
};
|
|
483
|
+
/**
|
|
484
|
+
* True when the datum's c_wallet VerificationKey hash matches the
|
|
485
|
+
* given stake-key-hash. Used by the designation-detection hook to
|
|
486
|
+
* find the active account's registration UTxO among the script
|
|
487
|
+
* address's outputs.
|
|
488
|
+
*/
|
|
489
|
+
const datumMatchesStakeKey = (datum, stakeKeyHash) => {
|
|
490
|
+
if (datum.cWallet.kind !== "verificationKey") return false;
|
|
491
|
+
if (datum.cWallet.stakeKeyHash.length !== stakeKeyHash.length) return false;
|
|
492
|
+
for (let index = 0; index < stakeKeyHash.length; index++) if (datum.cWallet.stakeKeyHash[index] !== stakeKeyHash[index]) return false;
|
|
493
|
+
return true;
|
|
494
|
+
};
|
|
495
|
+
//#endregion
|
|
496
|
+
//#region ../../packages/lib/cnight-dust-designation/src/plutus/redeemer.ts
|
|
497
|
+
const emptyConstr = (alternative) => Serialization.PlutusData.newConstrPlutusData(new Serialization.ConstrPlutusData(alternative, new Serialization.PlutusList()));
|
|
498
|
+
const dustActionCreate = () => emptyConstr(0n);
|
|
499
|
+
const dustActionBurn = () => emptyConstr(1n);
|
|
500
|
+
const dataVoid = () => emptyConstr(0n);
|
|
501
|
+
const dustActionCreateCbor = () => dustActionCreate().toCbor();
|
|
502
|
+
const dustActionBurnCbor = () => dustActionBurn().toCbor();
|
|
503
|
+
const dataVoidCbor = () => dataVoid().toCbor();
|
|
504
|
+
//#endregion
|
|
505
|
+
//#region ../../packages/lib/cnight-dust-designation/src/plutus/script-address.ts
|
|
506
|
+
const getDustGeneratorScriptHash = (network) => getDustGeneratorPlutusV3Script(network).hash();
|
|
507
|
+
const getDustGeneratorPaymentAddress = (network) => {
|
|
508
|
+
const scriptHash = getDustGeneratorScriptHash(network);
|
|
509
|
+
const networkId = CardanoDustNetwork.toNetworkId(network);
|
|
510
|
+
const credential = {
|
|
511
|
+
type: Cardano.CredentialType.ScriptHash,
|
|
512
|
+
hash: scriptHash
|
|
513
|
+
};
|
|
514
|
+
return Cardano.EnterpriseAddress.fromCredentials(networkId, credential).toAddress().toBech32();
|
|
515
|
+
};
|
|
516
|
+
const getDustGeneratorRewardAccount = (network) => {
|
|
517
|
+
const scriptHash = getDustGeneratorScriptHash(network);
|
|
518
|
+
const networkId = CardanoDustNetwork.toNetworkId(network);
|
|
519
|
+
const credential = {
|
|
520
|
+
type: Cardano.CredentialType.ScriptHash,
|
|
521
|
+
hash: scriptHash
|
|
522
|
+
};
|
|
523
|
+
return Cardano.RewardAddress.fromCredentials(networkId, credential).toAddress().toBech32();
|
|
524
|
+
};
|
|
525
|
+
const getDustMappingNftPolicyId = (network) => Cardano.PolicyId(getDustGeneratorScriptHash(network));
|
|
526
|
+
/**
|
|
527
|
+
* The DUST-mapping NFT minted by the validator has policy = script
|
|
528
|
+
* hash and asset_name = empty bytestring. This is the on-chain
|
|
529
|
+
* identifier callers query for to determine "is this account
|
|
530
|
+
* designated?".
|
|
531
|
+
*/
|
|
532
|
+
const getDustMappingNftAssetId = (network) => Cardano.AssetId.fromParts(getDustMappingNftPolicyId(network), Cardano.AssetName(""));
|
|
533
|
+
//#endregion
|
|
534
|
+
//#region ../../packages/lib/cnight-dust-designation/src/dust-address-decode.ts
|
|
535
|
+
const COMPACT_MODE_1_MIN = 64n;
|
|
536
|
+
const COMPACT_MODE_2_MIN = 1n << 14n;
|
|
537
|
+
const COMPACT_MODE_3_MIN = 1n << 30n;
|
|
538
|
+
const BLS12_381_SCALAR_MODULUS = BigInt("0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001");
|
|
539
|
+
const leBytesToScalar = (bytes) => {
|
|
540
|
+
let scalar = 0n;
|
|
541
|
+
for (let index = bytes.length - 1; index >= 0; index--) scalar = scalar << 8n | BigInt(bytes[index]);
|
|
542
|
+
return scalar;
|
|
543
|
+
};
|
|
544
|
+
/**
|
|
545
|
+
* Why `payload` is not the canonical (minimal) SCALE-compact encoding of an
|
|
546
|
+
* in-field BLS12-381 scalar, or `undefined` when it is.
|
|
547
|
+
*
|
|
548
|
+
* Minimality is ours to enforce: neither the Midnight SDK codec nor the
|
|
549
|
+
* midnight-node pallet checks it, and a padded encoding's claimability is
|
|
550
|
+
* unknown — so a non-canonical target must never reach the datum.
|
|
551
|
+
*
|
|
552
|
+
* Returns a reason instead of throwing so each boundary can surface it in its
|
|
553
|
+
* own channel: this file throws at the address-string input boundary, the
|
|
554
|
+
* blueprint builder returns `Err` at the datum-write boundary.
|
|
555
|
+
*/
|
|
556
|
+
const canonicalDustPayloadDefect = (payload) => {
|
|
557
|
+
if (payload.length === 0) return "empty payload";
|
|
558
|
+
const header = payload[0];
|
|
559
|
+
const mode = header & 3;
|
|
560
|
+
let scalar;
|
|
561
|
+
if (mode === 0) {
|
|
562
|
+
if (payload.length !== 1) return `single-byte mode declared, ${payload.length}-byte payload`;
|
|
563
|
+
scalar = BigInt(header >> 2);
|
|
564
|
+
} else if (mode === 1) {
|
|
565
|
+
if (payload.length !== 2) return `two-byte mode declared, ${payload.length}-byte payload`;
|
|
566
|
+
scalar = BigInt(header >> 2) + (BigInt(payload[1]) << 6n);
|
|
567
|
+
if (scalar < COMPACT_MODE_1_MIN) return `${scalar} fits a shorter mode`;
|
|
568
|
+
} else if (mode === 2) {
|
|
569
|
+
if (payload.length !== 4) return `four-byte mode declared, ${payload.length}-byte payload`;
|
|
570
|
+
scalar = BigInt(header >> 2) + (BigInt(payload[1]) << 6n) + (BigInt(payload[2]) << 14n) + (BigInt(payload[3]) << 22n);
|
|
571
|
+
if (scalar < COMPACT_MODE_2_MIN) return `${scalar} fits a shorter mode`;
|
|
572
|
+
} else {
|
|
573
|
+
const declaredScalarBytes = (header >> 2) + 4;
|
|
574
|
+
if (payload.length !== declaredScalarBytes + 1) return `${declaredScalarBytes}-byte scalar declared, ${payload.length - 1} bytes present`;
|
|
575
|
+
if (payload[payload.length - 1] === 0) return "most significant scalar byte is zero";
|
|
576
|
+
scalar = leBytesToScalar(payload.subarray(1));
|
|
577
|
+
if (scalar < COMPACT_MODE_3_MIN) return `${scalar} fits a shorter mode`;
|
|
578
|
+
}
|
|
579
|
+
return scalar >= BLS12_381_SCALAR_MODULUS ? "scalar is outside the BLS12-381 field" : void 0;
|
|
580
|
+
};
|
|
581
|
+
//#endregion
|
|
582
|
+
//#region ../../packages/lib/cnight-dust-designation/src/builders/build-night-designation-tx.ts
|
|
583
|
+
const NFT_ASSET_NAME = Cardano.AssetName("");
|
|
584
|
+
const computeScriptOutputLovelace = ({ scriptAddress, nftAsset, datumCbor, coinsPerUtxoByte }) => {
|
|
585
|
+
const datum = Serialization.PlutusData.fromCbor(datumCbor).toCore();
|
|
586
|
+
const representativeOutput = {
|
|
587
|
+
address: scriptAddress,
|
|
588
|
+
value: {
|
|
589
|
+
coins: LOVELACE_FOR_REGISTRATION,
|
|
590
|
+
assets: new Map([[nftAsset, 1n]])
|
|
591
|
+
},
|
|
592
|
+
datum
|
|
593
|
+
};
|
|
594
|
+
const minCoin = computeMinimumCoinQuantity(coinsPerUtxoByte)(representativeOutput);
|
|
595
|
+
return minCoin < 1586080n ? LOVELACE_FOR_REGISTRATION : minCoin;
|
|
596
|
+
};
|
|
597
|
+
const dustPubkeyError = (dustPubkey) => {
|
|
598
|
+
if (dustPubkey.length > 33) return {
|
|
599
|
+
code: "dust-address-too-long",
|
|
600
|
+
message: `dust_address exceeds the on-chain 33-byte limit enforced by the validator.`,
|
|
601
|
+
actualBytes: dustPubkey.length,
|
|
602
|
+
maxBytes: 33
|
|
603
|
+
};
|
|
604
|
+
const defect = canonicalDustPayloadDefect(dustPubkey);
|
|
605
|
+
return defect === void 0 ? void 0 : {
|
|
606
|
+
code: "invalid-dust-payload",
|
|
607
|
+
message: `dust_address is not a canonical SCALE-compact payload (${defect}).`
|
|
608
|
+
};
|
|
609
|
+
};
|
|
610
|
+
const buildNightDesignationTxBlueprint = (params) => {
|
|
611
|
+
if (params.cnightUtxos.length === 0) return Err({
|
|
612
|
+
code: "no-cnight",
|
|
613
|
+
message: "No cNIGHT in this account."
|
|
614
|
+
});
|
|
615
|
+
const scriptAddress = getDustGeneratorPaymentAddress(params.network);
|
|
616
|
+
const scriptRewardAccount = getDustGeneratorRewardAccount(params.network);
|
|
617
|
+
const nftPolicyId = getDustMappingNftPolicyId(params.network);
|
|
618
|
+
const nftAsset = getDustMappingNftAssetId(params.network);
|
|
619
|
+
const scriptCbor = getDustGeneratorScriptCbor(params.network);
|
|
620
|
+
const requiredSigners = {
|
|
621
|
+
paymentKeyHash: params.paymentKeyHash,
|
|
622
|
+
stakeKeyHash: params.stakeKeyHash
|
|
623
|
+
};
|
|
624
|
+
if (params.action.kind === "register") {
|
|
625
|
+
const dustError = dustPubkeyError(params.action.dustPubkey);
|
|
626
|
+
if (dustError) return Err(dustError);
|
|
627
|
+
const datumCbor = dustMappingDatumToCbor({
|
|
628
|
+
cWallet: {
|
|
629
|
+
kind: "verificationKey",
|
|
630
|
+
stakeKeyHash: params.stakeKeyHash
|
|
631
|
+
},
|
|
632
|
+
dustAddress: params.action.dustPubkey
|
|
633
|
+
});
|
|
634
|
+
return Ok({
|
|
635
|
+
network: params.network,
|
|
636
|
+
scriptAddress,
|
|
637
|
+
scriptRewardAccount,
|
|
638
|
+
dustMappingNftAssetId: nftAsset,
|
|
639
|
+
forcedInputs: params.cnightUtxos,
|
|
640
|
+
scriptOutput: {
|
|
641
|
+
address: scriptAddress,
|
|
642
|
+
lovelace: computeScriptOutputLovelace({
|
|
643
|
+
scriptAddress,
|
|
644
|
+
nftAsset,
|
|
645
|
+
datumCbor,
|
|
646
|
+
coinsPerUtxoByte: params.coinsPerUtxoByte
|
|
647
|
+
}),
|
|
648
|
+
nftAsset,
|
|
649
|
+
nftQuantity: 1n,
|
|
650
|
+
inlineDatumCbor: datumCbor
|
|
651
|
+
},
|
|
652
|
+
mint: {
|
|
653
|
+
policyId: nftPolicyId,
|
|
654
|
+
assetName: NFT_ASSET_NAME,
|
|
655
|
+
quantity: 1n,
|
|
656
|
+
redeemerCbor: dustActionCreateCbor()
|
|
657
|
+
},
|
|
658
|
+
spendRedeemer: null,
|
|
659
|
+
withdrawal: null,
|
|
660
|
+
requiredSigners,
|
|
661
|
+
scriptCbor
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
if (params.action.kind === "update") {
|
|
665
|
+
const dustError = dustPubkeyError(params.action.dustPubkey);
|
|
666
|
+
if (dustError) return Err(dustError);
|
|
667
|
+
const datumCbor = dustMappingDatumToCbor({
|
|
668
|
+
cWallet: {
|
|
669
|
+
kind: "verificationKey",
|
|
670
|
+
stakeKeyHash: params.stakeKeyHash
|
|
671
|
+
},
|
|
672
|
+
dustAddress: params.action.dustPubkey
|
|
673
|
+
});
|
|
674
|
+
return Ok({
|
|
675
|
+
network: params.network,
|
|
676
|
+
scriptAddress,
|
|
677
|
+
scriptRewardAccount,
|
|
678
|
+
dustMappingNftAssetId: nftAsset,
|
|
679
|
+
forcedInputs: [...params.cnightUtxos, params.action.registrationUtxo],
|
|
680
|
+
scriptOutput: {
|
|
681
|
+
address: scriptAddress,
|
|
682
|
+
lovelace: computeScriptOutputLovelace({
|
|
683
|
+
scriptAddress,
|
|
684
|
+
nftAsset,
|
|
685
|
+
datumCbor,
|
|
686
|
+
coinsPerUtxoByte: params.coinsPerUtxoByte
|
|
687
|
+
}),
|
|
688
|
+
nftAsset,
|
|
689
|
+
nftQuantity: 1n,
|
|
690
|
+
inlineDatumCbor: datumCbor
|
|
691
|
+
},
|
|
692
|
+
mint: null,
|
|
693
|
+
spendRedeemer: {
|
|
694
|
+
registrationUtxo: params.action.registrationUtxo,
|
|
695
|
+
redeemerCbor: dataVoidCbor()
|
|
696
|
+
},
|
|
697
|
+
withdrawal: {
|
|
698
|
+
rewardAccount: scriptRewardAccount,
|
|
699
|
+
lovelace: params.action.scriptWithdrawableLovelace,
|
|
700
|
+
redeemerCbor: dataVoidCbor()
|
|
701
|
+
},
|
|
702
|
+
requiredSigners,
|
|
703
|
+
scriptCbor
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
return Ok({
|
|
707
|
+
network: params.network,
|
|
708
|
+
scriptAddress,
|
|
709
|
+
scriptRewardAccount,
|
|
710
|
+
dustMappingNftAssetId: nftAsset,
|
|
711
|
+
forcedInputs: [...params.cnightUtxos, params.action.registrationUtxo],
|
|
712
|
+
scriptOutput: null,
|
|
713
|
+
mint: {
|
|
714
|
+
policyId: nftPolicyId,
|
|
715
|
+
assetName: NFT_ASSET_NAME,
|
|
716
|
+
quantity: -1n,
|
|
717
|
+
redeemerCbor: dustActionBurnCbor()
|
|
718
|
+
},
|
|
719
|
+
spendRedeemer: {
|
|
720
|
+
registrationUtxo: params.action.registrationUtxo,
|
|
721
|
+
redeemerCbor: dataVoidCbor()
|
|
722
|
+
},
|
|
723
|
+
withdrawal: null,
|
|
724
|
+
requiredSigners,
|
|
725
|
+
scriptCbor
|
|
726
|
+
});
|
|
727
|
+
};
|
|
728
|
+
//#endregion
|
|
729
|
+
//#region ../../packages/lib/cnight-dust-designation/src/value-objects/cardano-payment-key-hash.vo.ts
|
|
730
|
+
var CardanoPaymentKeyHashError = class extends Error {
|
|
731
|
+
code;
|
|
732
|
+
constructor(message) {
|
|
733
|
+
super(message);
|
|
734
|
+
this.name = "CardanoPaymentKeyHashError";
|
|
735
|
+
this.code = "invalid-length";
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
const CardanoPaymentKeyHash = (bytes) => {
|
|
739
|
+
if (bytes.length !== 28) throw new CardanoPaymentKeyHashError(`CardanoPaymentKeyHash expects 28 bytes, got ${bytes.length}`);
|
|
740
|
+
return bytes;
|
|
741
|
+
};
|
|
742
|
+
CardanoPaymentKeyHash.toHex = (hash) => Array.from(hash).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
743
|
+
CardanoPaymentKeyHash.fromHex = (hex) => {
|
|
744
|
+
const normalised = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
745
|
+
if (normalised.length !== 56) throw new CardanoPaymentKeyHashError(`CardanoPaymentKeyHash hex expects 56 chars, got ${normalised.length}`);
|
|
746
|
+
if (!/^[0-9a-fA-F]+$/.test(normalised)) throw new CardanoPaymentKeyHashError(`CardanoPaymentKeyHash hex contains non-hex characters: ${hex}`);
|
|
747
|
+
const bytes = new Uint8Array(28);
|
|
748
|
+
for (let index = 0; index < bytes.length; index++) bytes[index] = parseInt(normalised.slice(index * 2, index * 2 + 2), 16);
|
|
749
|
+
return CardanoPaymentKeyHash(bytes);
|
|
750
|
+
};
|
|
751
|
+
//#endregion
|
|
752
|
+
//#region ../../packages/module/blockchain-cardano/src/store/night-designation/account-key-hashes.ts
|
|
753
|
+
const hexToBytes = (hex) => {
|
|
754
|
+
if (hex.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex)) throw new Error(`Invalid hex string: "${hex}"`);
|
|
755
|
+
return Uint8Array.from((hex.match(/.{1,2}/g) ?? []).map((byte) => parseInt(byte, 16)));
|
|
756
|
+
};
|
|
757
|
+
/**
|
|
758
|
+
* Read the account's credentials off its primary Cardano address.
|
|
759
|
+
*
|
|
760
|
+
* Throws when the account has no Cardano address or its address carries no
|
|
761
|
+
* stake credential — an enterprise address cannot satisfy the validator's
|
|
762
|
+
* `check_auth`, so there is no designation to build or index for it.
|
|
763
|
+
*/
|
|
764
|
+
const resolveAccountKeyHashes = (addresses, accountId) => {
|
|
765
|
+
const primary = addresses.find((address) => address.accountId === accountId && address.blockchainName === "Cardano");
|
|
766
|
+
if (!primary) throw new Error("No Cardano addresses found for account");
|
|
767
|
+
const baseAddress = Cardano.Address.fromString(primary.address)?.asBase();
|
|
768
|
+
if (!baseAddress) throw new Error("Account address is not a base (payment+stake) address");
|
|
769
|
+
return {
|
|
770
|
+
primaryAddress: Cardano.PaymentAddress(primary.address),
|
|
771
|
+
paymentKeyHash: CardanoPaymentKeyHash(hexToBytes(baseAddress.getPaymentCredential().hash)),
|
|
772
|
+
stakeKeyHash: CardanoStakeKeyHash(hexToBytes(baseAddress.getStakeCredential().hash))
|
|
773
|
+
};
|
|
774
|
+
};
|
|
775
|
+
//#endregion
|
|
776
|
+
//#region ../../packages/module/blockchain-cardano/src/store/night-designation/build-night-designation-tx.ts
|
|
777
|
+
const toPlutusData = (cbor) => Serialization.PlutusData.fromCbor(cbor).toCore();
|
|
778
|
+
const toKeyHashHex = (bytes) => Array.from(bytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
779
|
+
const sameRef = (a, b) => a.txId === b.txId && a.index === b.index;
|
|
780
|
+
const buildNightDesignationTx = async (params, dependencies) => {
|
|
781
|
+
const blueprintResult = buildNightDesignationTxBlueprint({
|
|
782
|
+
network: params.network,
|
|
783
|
+
cnightUtxos: params.cnightUtxos,
|
|
784
|
+
stakeKeyHash: params.stakeKeyHash,
|
|
785
|
+
paymentKeyHash: params.paymentKeyHash,
|
|
786
|
+
action: params.action,
|
|
787
|
+
coinsPerUtxoByte: params.protocolParameters.coinsPerUtxoByte
|
|
788
|
+
});
|
|
789
|
+
if (!blueprintResult.ok) return blueprintResult;
|
|
790
|
+
const blueprint = blueprintResult.value;
|
|
791
|
+
const builder = new TransactionBuilder(dependencies.networkMagic, params.protocolParameters);
|
|
792
|
+
builder.setChangeAddress(params.changeAddress).setUnspentOutputs(dependencies.coverUtxos).setCollateralUtxos(dependencies.collateralUtxos).setCollateralChangeAddress(params.changeAddress).setPlutusContext({
|
|
793
|
+
costModels: params.protocolParameters.costModels,
|
|
794
|
+
txEvaluator: dependencies.txEvaluator,
|
|
795
|
+
inputResolver: dependencies.inputResolver
|
|
796
|
+
});
|
|
797
|
+
builder.attachScript({
|
|
798
|
+
__type: Cardano.ScriptType.Plutus,
|
|
799
|
+
version: Cardano.PlutusLanguageVersion.V3,
|
|
800
|
+
bytes: Serialization.PlutusV3Script.fromCbor(blueprint.scriptCbor).rawBytes()
|
|
801
|
+
});
|
|
802
|
+
const registrationRef = blueprint.spendRedeemer?.registrationUtxo[0];
|
|
803
|
+
for (const utxo of blueprint.forcedInputs) if (blueprint.spendRedeemer && registrationRef && sameRef(utxo[0], registrationRef)) builder.addInput(utxo, { redeemer: toPlutusData(blueprint.spendRedeemer.redeemerCbor) });
|
|
804
|
+
else builder.addInput(utxo);
|
|
805
|
+
if (blueprint.mint) {
|
|
806
|
+
const assetId = Cardano.AssetId.fromParts(blueprint.mint.policyId, blueprint.mint.assetName);
|
|
807
|
+
builder.mintAssets(new Map([[assetId, blueprint.mint.quantity]]), toPlutusData(blueprint.mint.redeemerCbor));
|
|
808
|
+
}
|
|
809
|
+
if (blueprint.scriptOutput) builder.addOutput({
|
|
810
|
+
address: blueprint.scriptOutput.address,
|
|
811
|
+
value: {
|
|
812
|
+
coins: blueprint.scriptOutput.lovelace,
|
|
813
|
+
assets: new Map([[blueprint.scriptOutput.nftAsset, blueprint.scriptOutput.nftQuantity]])
|
|
814
|
+
},
|
|
815
|
+
datum: toPlutusData(blueprint.scriptOutput.inlineDatumCbor)
|
|
816
|
+
});
|
|
817
|
+
if (blueprint.withdrawal) builder.addScriptWithdrawal(blueprint.withdrawal.rewardAccount, blueprint.withdrawal.lovelace, toPlutusData(blueprint.withdrawal.redeemerCbor));
|
|
818
|
+
builder.addRequiredSigner(toKeyHashHex(blueprint.requiredSigners.paymentKeyHash));
|
|
819
|
+
builder.addRequiredSigner(toKeyHashHex(blueprint.requiredSigners.stakeKeyHash));
|
|
820
|
+
builder.setValidityInterval({ invalidHereafter: params.ttlSlot });
|
|
821
|
+
const transaction = await builder.build();
|
|
822
|
+
const cbor = transaction.toCbor();
|
|
823
|
+
const fee = transaction.body().fee();
|
|
824
|
+
return Ok({
|
|
825
|
+
cbor,
|
|
826
|
+
txId: transaction.getId(),
|
|
827
|
+
fee
|
|
828
|
+
});
|
|
829
|
+
};
|
|
830
|
+
//#endregion
|
|
831
|
+
//#region ../../packages/module/blockchain-cardano/src/store/night-designation/bounded-ex-units-evaluator.ts
|
|
832
|
+
const BOUNDED_EX_UNITS_PER_REDEEMER = {
|
|
833
|
+
memory: 2e6,
|
|
834
|
+
steps: 7e8
|
|
835
|
+
};
|
|
836
|
+
/**
|
|
837
|
+
* A {@link TxEvaluator} that returns a fixed, conservative budget for
|
|
838
|
+
* every redeemer in the transaction (no network round-trip).
|
|
839
|
+
*/
|
|
840
|
+
const boundedExUnitsEvaluator = { evaluate: async (tx) => (tx.witness.redeemers ?? []).map((redeemer) => ({
|
|
841
|
+
purpose: redeemer.purpose,
|
|
842
|
+
index: redeemer.index,
|
|
843
|
+
budget: BOUNDED_EX_UNITS_PER_REDEEMER
|
|
844
|
+
})) };
|
|
845
|
+
//#endregion
|
|
846
|
+
//#region ../../packages/module/blockchain-cardano/src/store/night-designation/provider-ex-units-evaluator.ts
|
|
847
|
+
/**
|
|
848
|
+
* Padding on every evaluated budget. The builder rewrites the fee (and the
|
|
849
|
+
* change output that absorbs it) AFTER evaluation, so the script context the
|
|
850
|
+
* node executes is not byte-identical to the one it priced. Under-declaring
|
|
851
|
+
* fails phase-2 and forfeits the collateral, so the difference is paid for
|
|
852
|
+
* rather than gambled on.
|
|
853
|
+
*/
|
|
854
|
+
const EX_UNITS_MARGIN_PERCENT = 10;
|
|
855
|
+
const withMargin = (budget) => ({
|
|
856
|
+
memory: Math.ceil(budget.memory * (100 + EX_UNITS_MARGIN_PERCENT) / 100),
|
|
857
|
+
steps: Math.ceil(budget.steps * (100 + EX_UNITS_MARGIN_PERCENT) / 100)
|
|
858
|
+
});
|
|
859
|
+
/**
|
|
860
|
+
* A {@link TxEvaluator} that prices redeemers through the Cardano provider,
|
|
861
|
+
* leaving any redeemer the provider did not price on the fixed budget
|
|
862
|
+
* `boundedExUnitsEvaluator` assigns it.
|
|
863
|
+
*/
|
|
864
|
+
const createProviderExUnitsEvaluator = ({ cardanoProvider, chainId, logger }) => {
|
|
865
|
+
const evaluate = async (tx) => {
|
|
866
|
+
try {
|
|
867
|
+
const result = await firstValueFrom(cardanoProvider.evaluateTx({ tx: Serialization.Transaction.fromCore(tx).toCbor() }, { chainId }));
|
|
868
|
+
if (result.isOk()) return result.value;
|
|
869
|
+
logger.warn("cNIGHT designation: ex-units evaluation declined, using the bounded budget", result.error);
|
|
870
|
+
} catch (error) {
|
|
871
|
+
logger.warn("cNIGHT designation: ex-units evaluation failed, using the bounded budget", error);
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
return { evaluate: async (tx, resolvedInputs) => {
|
|
875
|
+
const bounded = await boundedExUnitsEvaluator.evaluate(tx, resolvedInputs);
|
|
876
|
+
if (bounded.length === 0) return bounded;
|
|
877
|
+
const evaluated = await evaluate(tx);
|
|
878
|
+
return bounded.map((entry) => {
|
|
879
|
+
const match = evaluated?.find((budget) => budget.purpose === entry.purpose && budget.index === entry.index);
|
|
880
|
+
return match ? {
|
|
881
|
+
...entry,
|
|
882
|
+
budget: withMargin(match.budget)
|
|
883
|
+
} : entry;
|
|
884
|
+
});
|
|
885
|
+
} };
|
|
886
|
+
};
|
|
887
|
+
//#endregion
|
|
888
|
+
//#region ../../packages/module/blockchain-cardano/src/store/night-designation/registration-utxo.ts
|
|
889
|
+
const decodeDatumOrSkip = (datum) => {
|
|
890
|
+
try {
|
|
891
|
+
return decodeDustMappingDatum(Serialization.PlutusData.fromCore(datum).toCbor());
|
|
892
|
+
} catch {
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
/**
|
|
897
|
+
* Pick the account's registration out of the UTxOs sitting at the dust
|
|
898
|
+
* generator's script address.
|
|
899
|
+
*
|
|
900
|
+
* A registration is identified by the singleton DUST-mapping NFT plus an
|
|
901
|
+
* inline `DustMappingDatum` whose `c_wallet` verification-key hash is the
|
|
902
|
+
* account's stake key hash. Undecodable datums belong to other accounts (or
|
|
903
|
+
* to a future datum revision) and are skipped rather than treated as errors.
|
|
904
|
+
*/
|
|
905
|
+
const findRegistrationUtxo = (scriptUtxos, nftAssetId, stakeKeyHash) => {
|
|
906
|
+
for (const utxo of scriptUtxos) {
|
|
907
|
+
const [, out] = utxo;
|
|
908
|
+
if (out.value.assets?.get(nftAssetId) !== 1n) continue;
|
|
909
|
+
if (!out.datum) continue;
|
|
910
|
+
const datum = decodeDatumOrSkip(out.datum);
|
|
911
|
+
if (datum && datumMatchesStakeKey(datum, stakeKeyHash)) return {
|
|
912
|
+
utxo,
|
|
913
|
+
datum
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
//#endregion
|
|
918
|
+
//#region ../../packages/module/blockchain-cardano/src/store/night-designation/build-side-effect.ts
|
|
919
|
+
const TTL_BUFFER_SLOTS = 7200;
|
|
920
|
+
const LIVE_PENDING_WINDOW_MS = TTL_BUFFER_SLOTS * 1e3 + 6e5;
|
|
921
|
+
const PENDING_READ_TIMEOUT_MS = 2e3;
|
|
922
|
+
const NO_PENDING_ACTIVITIES = [];
|
|
923
|
+
/**
|
|
924
|
+
* Only `designate` counts: an update/deregister with no confirmed marker
|
|
925
|
+
* already fails `no-registration-utxo`, and with one the scan already refuses
|
|
926
|
+
* a designate — so widening this over-blocks for no safety gain.
|
|
927
|
+
*/
|
|
928
|
+
const hasLivePendingDesignate = (pendingActivities) => pendingActivities.some((activity) => {
|
|
929
|
+
if (activity.blockchainSpecific?.Cardano?.nightDesignation?.action !== "designate") return false;
|
|
930
|
+
return Date.now() - activity.timestamp < LIVE_PENDING_WINDOW_MS;
|
|
931
|
+
});
|
|
932
|
+
const BUILD_ERROR_KEYS_BY_CODE = {
|
|
933
|
+
"already-registered": {
|
|
934
|
+
title: "v2.cnight-designation.build.error.already-registered.title",
|
|
935
|
+
subtitle: "v2.cnight-designation.build.error.already-registered.subtitle"
|
|
936
|
+
},
|
|
937
|
+
"no-cnight": {
|
|
938
|
+
title: "v2.cnight-designation.build.error.no-cnight.title",
|
|
939
|
+
subtitle: "v2.cnight-designation.build.error.no-cnight.subtitle"
|
|
940
|
+
},
|
|
941
|
+
"no-cardano-utxos": {
|
|
942
|
+
title: "v2.cnight-designation.build.error.no-cardano-utxos.title",
|
|
943
|
+
subtitle: "v2.cnight-designation.build.error.no-cardano-utxos.subtitle"
|
|
944
|
+
},
|
|
945
|
+
"no-registration-utxo": {
|
|
946
|
+
title: "v2.cnight-designation.build.error.no-registration-utxo.title",
|
|
947
|
+
subtitle: "v2.cnight-designation.build.error.no-registration-utxo.subtitle"
|
|
948
|
+
},
|
|
949
|
+
"script-stake-unregistered": {
|
|
950
|
+
title: "v2.cnight-designation.build.error.script-stake-unregistered.title",
|
|
951
|
+
subtitle: "v2.cnight-designation.build.error.script-stake-unregistered.subtitle"
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
const GENERIC_BUILD_ERROR_KEYS = {
|
|
955
|
+
title: "v2.cnight-designation.build.error.title",
|
|
956
|
+
subtitle: "v2.cnight-designation.build.error.subtitle"
|
|
957
|
+
};
|
|
958
|
+
const errorTranslationKeysForCode = (code) => (code ? BUILD_ERROR_KEYS_BY_CODE[code] : void 0) ?? GENERIC_BUILD_ERROR_KEYS;
|
|
959
|
+
const failure = (error, code) => ({
|
|
960
|
+
success: false,
|
|
961
|
+
error: {
|
|
962
|
+
name: error.name,
|
|
963
|
+
message: error.message
|
|
964
|
+
},
|
|
965
|
+
errorTranslationKeys: errorTranslationKeysForCode(code)
|
|
966
|
+
});
|
|
967
|
+
/**
|
|
968
|
+
* Resolve the rich cNIGHT action from the serializable `Building` state by
|
|
969
|
+
* scanning the script address for the registration UTxO whose inline datum is
|
|
970
|
+
* bound to the account's stake key. Every action needs that answer, not just
|
|
971
|
+
* update/deregister: Midnight honours neither of two registrations and the
|
|
972
|
+
* second revokes the first, so a designate over an existing one is refused
|
|
973
|
+
* here (`already-registered`) rather than signed. For update it also reads the
|
|
974
|
+
* script reward account so the withdrawal entry matches the amount the ledger
|
|
975
|
+
* will actually let the tx take.
|
|
976
|
+
*/
|
|
977
|
+
const resolveAction = async ({ state, network, stakeKeyHash, dependencies, chainId, pendingActivities }) => {
|
|
978
|
+
const dustPubkey = state.dustPubkeyHex === void 0 ? void 0 : MidnightCoinPubkey(hexToBytes(state.dustPubkeyHex));
|
|
979
|
+
const scriptAddress = getDustGeneratorPaymentAddress(network);
|
|
980
|
+
const registration = findRegistrationUtxo(await firstValueFrom(unwrapProviderResult(() => dependencies.cardanoProvider.getUtxosAtAddress({ address: scriptAddress }, { chainId }))), getDustMappingNftAssetId(network), stakeKeyHash);
|
|
981
|
+
if (state.action === "designate") {
|
|
982
|
+
if (registration) throw Object.assign(/* @__PURE__ */ new Error("This account already has a cNIGHT designation"), { code: "already-registered" });
|
|
983
|
+
if (hasLivePendingDesignate(pendingActivities)) throw Object.assign(/* @__PURE__ */ new Error("A cNIGHT designation for this account is still confirming"), { code: "already-registered" });
|
|
984
|
+
if (!dustPubkey) throw new Error("Missing dust pubkey for designate");
|
|
985
|
+
return {
|
|
986
|
+
kind: "register",
|
|
987
|
+
dustPubkey
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
if (!registration) throw Object.assign(/* @__PURE__ */ new Error("No cNIGHT designation registration found for this account"), { code: "no-registration-utxo" });
|
|
991
|
+
if (state.action === "deregister") return {
|
|
992
|
+
kind: "deregister",
|
|
993
|
+
registrationUtxo: registration.utxo
|
|
994
|
+
};
|
|
995
|
+
if (!dustPubkey) throw new Error("Missing dust pubkey for update");
|
|
996
|
+
const scriptRewardAccountInfo = await firstValueFrom(unwrapProviderResult(() => dependencies.cardanoProvider.getRewardAccountInfo({ rewardAccount: CardanoRewardAccount(getDustGeneratorRewardAccount(network)) }, { chainId })));
|
|
997
|
+
if (!scriptRewardAccountInfo.isRegistered) throw Object.assign(/* @__PURE__ */ new Error("The cNIGHT validator's reward account is not registered on this network"), { code: "script-stake-unregistered" });
|
|
998
|
+
return {
|
|
999
|
+
kind: "update",
|
|
1000
|
+
dustPubkey,
|
|
1001
|
+
registrationUtxo: registration.utxo,
|
|
1002
|
+
scriptWithdrawableLovelace: BigNumber.valueOf(scriptRewardAccountInfo.withdrawableAmount)
|
|
1003
|
+
};
|
|
1004
|
+
};
|
|
1005
|
+
const buildDesignation = async (state, dependencies, pendingActivities) => {
|
|
1006
|
+
try {
|
|
1007
|
+
const { accountId } = state;
|
|
1008
|
+
const cardano = dependencies.txExecutorCardano;
|
|
1009
|
+
const [chainId, allAccountUtxos, unspendableUtxos, cardanoAddresses] = await Promise.all([
|
|
1010
|
+
firstValueFrom(cardano.cardanoChainId$),
|
|
1011
|
+
firstValueFrom(cardano.cardanoAccountUtxos$),
|
|
1012
|
+
firstValueFrom(cardano.cardanoAccountUnspendableUtxos$),
|
|
1013
|
+
firstValueFrom(cardano.cardanoAddresses$)
|
|
1014
|
+
]);
|
|
1015
|
+
if (!chainId) throw new Error("Cardano chain id not available");
|
|
1016
|
+
refuseExtensionAccount(accountId, cardanoAddresses);
|
|
1017
|
+
const [protocolParameters, tip] = await Promise.all([firstValueFrom(unwrapProviderResult(() => dependencies.cardanoProvider.getProtocolParameters({ chainId }))), firstValueFrom(unwrapProviderResult(() => dependencies.cardanoProvider.getTip({ chainId })))]);
|
|
1018
|
+
const network = CardanoDustNetwork.fromNetworkMagic(chainId.networkMagic);
|
|
1019
|
+
const { primaryAddress, paymentKeyHash, stakeKeyHash } = resolveAccountKeyHashes(cardanoAddresses, accountId);
|
|
1020
|
+
const accountUtxos = allAccountUtxos[accountId] ?? [];
|
|
1021
|
+
const reservedUtxos = unspendableUtxos[accountId] ?? [];
|
|
1022
|
+
const spendable = filterSpendableUtxos(accountUtxos, reservedUtxos);
|
|
1023
|
+
const cnightAssetId = getCnightAssetId(network);
|
|
1024
|
+
const cnightUtxos = spendable.filter(([, out]) => out.value.assets?.has(cnightAssetId));
|
|
1025
|
+
const coverUtxos = spendable.filter(([, out]) => !out.value.assets?.has(cnightAssetId));
|
|
1026
|
+
const reservedKeys = new Set(reservedUtxos.map(utxoKey));
|
|
1027
|
+
const reservedCollateral = getEligibleCollateralUtxo(accountUtxos.filter((utxo) => reservedKeys.has(utxoKey(utxo)) && utxo[1].address === primaryAddress));
|
|
1028
|
+
const action = await resolveAction({
|
|
1029
|
+
state,
|
|
1030
|
+
network,
|
|
1031
|
+
stakeKeyHash,
|
|
1032
|
+
dependencies,
|
|
1033
|
+
chainId,
|
|
1034
|
+
pendingActivities
|
|
1035
|
+
});
|
|
1036
|
+
if (coverUtxos.length === 0) return failure(/* @__PURE__ */ new Error("No ADA-only UTxO available to cover fee and outputs"), "no-cardano-utxos");
|
|
1037
|
+
const result = await buildNightDesignationTx({
|
|
1038
|
+
network,
|
|
1039
|
+
action,
|
|
1040
|
+
cnightUtxos,
|
|
1041
|
+
paymentKeyHash,
|
|
1042
|
+
stakeKeyHash,
|
|
1043
|
+
changeAddress: primaryAddress,
|
|
1044
|
+
ttlSlot: Cardano.Slot(Number(tip.slot) + TTL_BUFFER_SLOTS),
|
|
1045
|
+
protocolParameters
|
|
1046
|
+
}, {
|
|
1047
|
+
networkMagic: chainId.networkMagic,
|
|
1048
|
+
coverUtxos,
|
|
1049
|
+
collateralUtxos: reservedCollateral ? [reservedCollateral] : coverUtxos,
|
|
1050
|
+
txEvaluator: createProviderExUnitsEvaluator({
|
|
1051
|
+
cardanoProvider: dependencies.cardanoProvider,
|
|
1052
|
+
chainId,
|
|
1053
|
+
logger: dependencies.logger
|
|
1054
|
+
}),
|
|
1055
|
+
inputResolver: createInputResolver([
|
|
1056
|
+
...cnightUtxos,
|
|
1057
|
+
...coverUtxos,
|
|
1058
|
+
...action.kind === "register" ? [] : [action.registrationUtxo]
|
|
1059
|
+
])
|
|
1060
|
+
});
|
|
1061
|
+
if (!result.ok) return failure(new Error(result.error.message), result.error.code);
|
|
1062
|
+
return {
|
|
1063
|
+
success: true,
|
|
1064
|
+
serializedTx: result.value.cbor,
|
|
1065
|
+
fees: [{
|
|
1066
|
+
tokenId: LOVELACE_TOKEN_ID,
|
|
1067
|
+
amount: BigNumber(result.value.fee)
|
|
1068
|
+
}]
|
|
1069
|
+
};
|
|
1070
|
+
} catch (error) {
|
|
1071
|
+
const code = error instanceof InputSelectionError ? "no-cardano-utxos" : error.code;
|
|
1072
|
+
return failure(error instanceof Error ? error : new Error(String(error)), code);
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
const makeNightDesignationBuilding = () => (_, stateObservables, dependencies) => firstStateOfStatus(stateObservables.nightDesignationFlow.selectState$, "Building").pipe(switchMap((state) => stateObservables.activities.selectPendingActivitiesByAccount$.pipe(map((byAccount) => byAccount[state.accountId] ?? NO_PENDING_ACTIVITIES), take(1), timeout({
|
|
1076
|
+
first: PENDING_READ_TIMEOUT_MS,
|
|
1077
|
+
with: () => of(NO_PENDING_ACTIVITIES)
|
|
1078
|
+
}), switchMap((pendingActivities) => from(buildDesignation(state, dependencies, pendingActivities)).pipe(map((result) => dependencies.actions.nightDesignationFlow.buildCompleted({
|
|
1079
|
+
accountId: state.accountId,
|
|
1080
|
+
result
|
|
1081
|
+
})))))));
|
|
1082
|
+
//#endregion
|
|
1083
|
+
//#region ../../packages/module/blockchain-cardano/src/store/night-designation/index-side-effect.ts
|
|
1084
|
+
/**
|
|
1085
|
+
* How long a refresh waits for the chain id and addresses it scans with.
|
|
1086
|
+
*
|
|
1087
|
+
* Only a bound, not a deadline: inputs that never arrive must resolve the entry
|
|
1088
|
+
* rather than leave it refreshing forever, with no way back to a retry.
|
|
1089
|
+
*/
|
|
1090
|
+
const INPUTS_TIMEOUT_MS = 2e4;
|
|
1091
|
+
const scanInputs$ = (accountId, cardano, inputsTimeoutMs) => combineLatest([cardano.cardanoChainId$, cardano.cardanoAddresses$]).pipe(filter((inputs) => {
|
|
1092
|
+
const [chainId, cardanoAddresses] = inputs;
|
|
1093
|
+
return chainId !== void 0 && cardanoAddresses.some((address) => address.accountId === accountId && isCardanoAddressOfSupportedNetwork(address, chainId));
|
|
1094
|
+
}), take(1), timeout({
|
|
1095
|
+
first: inputsTimeoutMs,
|
|
1096
|
+
with: () => throwError(() => /* @__PURE__ */ new Error("Cardano chain id / addresses never published"))
|
|
1097
|
+
}));
|
|
1098
|
+
const readSnapshot$ = ({ accountId, chainId, cardanoAddresses, dependencies }) => {
|
|
1099
|
+
const { stakeKeyHash } = resolveAccountKeyHashes(cardanoAddresses, accountId);
|
|
1100
|
+
const network = CardanoDustNetwork.fromNetworkMagic(chainId.networkMagic);
|
|
1101
|
+
return forkJoin([unwrapProviderResult(() => dependencies.cardanoProvider.getUtxosAtAddress({ address: getDustGeneratorPaymentAddress(network) }, { chainId })), unwrapProviderResult(() => dependencies.cardanoProvider.getRewardAccountInfo({ rewardAccount: CardanoRewardAccount(getDustGeneratorRewardAccount(network)) }, { chainId })).pipe(map((info) => info.isRegistered), catchError(() => of(void 0)))]).pipe(map(([scriptUtxos, isScriptStakeCredentialRegistered]) => {
|
|
1102
|
+
const registration = findRegistrationUtxo(scriptUtxos, getDustMappingNftAssetId(network), stakeKeyHash);
|
|
1103
|
+
return {
|
|
1104
|
+
scriptStakeCredentialRegistered: isScriptStakeCredentialRegistered,
|
|
1105
|
+
...registration === void 0 ? {} : { registration: {
|
|
1106
|
+
txId: String(registration.utxo[0].txId),
|
|
1107
|
+
outputIndex: registration.utxo[0].index,
|
|
1108
|
+
dustPubkeyHex: MidnightCoinPubkey.toHex(registration.datum.dustAddress)
|
|
1109
|
+
} }
|
|
1110
|
+
};
|
|
1111
|
+
}));
|
|
1112
|
+
};
|
|
1113
|
+
const makeNightDesignationIndexRefresh = ({ inputsTimeoutMs = INPUTS_TIMEOUT_MS } = {}) => ({ nightDesignationIndex: { refreshRequested$ } }, _stateObservables, dependencies) => refreshRequested$.pipe(groupBy(({ payload }) => payload.accountId), mergeMap((perAccount$) => perAccount$.pipe(exhaustMap(({ payload: { accountId } }) => scanInputs$(accountId, dependencies.txExecutorCardano, inputsTimeoutMs).pipe(switchMap(([chainId, cardanoAddresses]) => readSnapshot$({
|
|
1114
|
+
accountId,
|
|
1115
|
+
chainId,
|
|
1116
|
+
cardanoAddresses,
|
|
1117
|
+
dependencies
|
|
1118
|
+
})), map((snapshot) => dependencies.actions.nightDesignationIndex.refreshCompleted({
|
|
1119
|
+
accountId,
|
|
1120
|
+
snapshot
|
|
1121
|
+
})), catchError(() => of(dependencies.actions.nightDesignationIndex.refreshFailed({ accountId }))))))));
|
|
1122
|
+
/**
|
|
1123
|
+
* How long an entry may stay provisional before the index re-reads anyway.
|
|
1124
|
+
*
|
|
1125
|
+
* The wait is on the submitted transaction's activity, which a dropped
|
|
1126
|
+
* transaction or a stalled account sync can leave pending forever; without a
|
|
1127
|
+
* bound the entry would offer no designation control for the rest of the
|
|
1128
|
+
* session.
|
|
1129
|
+
*/
|
|
1130
|
+
const SETTLING_TIMEOUT_MS = 600 * 1e3;
|
|
1131
|
+
/**
|
|
1132
|
+
* Hold the index provisional from submission until the designation
|
|
1133
|
+
* transaction is on chain, then re-read it.
|
|
1134
|
+
*
|
|
1135
|
+
* `Success` is a SUBMIT result — the txId comes back from submission — so the
|
|
1136
|
+
* script address still answers for the state before the designation. Scanning
|
|
1137
|
+
* here would write "not designated" over an account that has just designated,
|
|
1138
|
+
* and every later read would repeat it. The entry is marked settling instead,
|
|
1139
|
+
* and the scan waits for that transaction's activity to stop being pending.
|
|
1140
|
+
*/
|
|
1141
|
+
const makeNightDesignationIndexSettling = ({ settlingTimeoutMs = SETTLING_TIMEOUT_MS } = {}) => (_, stateObservables, { actions }) => firstStateOfStatus(stateObservables.nightDesignationFlow.selectState$, "Success").pipe(mergeMap(({ accountId, txId }) => concat(of(actions.nightDesignationIndex.settlingStarted({
|
|
1142
|
+
accountId,
|
|
1143
|
+
txId
|
|
1144
|
+
})), merge(stateObservables.activities.selectAllMap$.pipe(filter((byAccount) => (byAccount[accountId] ?? []).some((activity) => activity.activityId === txId && activity.type !== ActivityType.Pending))), timer(settlingTimeoutMs)).pipe(take(1), mergeMap(() => from([actions.nightDesignationIndex.refreshRequested({ accountId }), actions.nightDesignationIndex.settlingEnded({ accountId })]))))));
|
|
1145
|
+
//#endregion
|
|
1146
|
+
//#region ../../packages/module/blockchain-cardano/src/store/sdk-extensions.ts
|
|
1147
|
+
const sdkExtensionSideEffects = [...[
|
|
1148
|
+
makeNightDesignationBuilding(),
|
|
1149
|
+
makeNightDesignationIndexRefresh(),
|
|
1150
|
+
makeNightDesignationIndexSettling()
|
|
1151
|
+
]];
|
|
1152
|
+
//#endregion
|
|
1153
|
+
//#region ../../packages/module/blockchain-cardano/src/store/side-effects.ts
|
|
1154
|
+
const mainnetMagic = Number(Cardano.NetworkMagics.Mainnet);
|
|
1155
|
+
const deriveCardanoTestnetOptions = (config) => {
|
|
1156
|
+
const blockfrostConfigs = config.cardanoProvider.blockfrostConfigs;
|
|
1157
|
+
return Object.keys(blockfrostConfigs ?? {}).map((key) => Number(key)).filter((magic) => magic !== mainnetMagic).map(getCardanoTestnetIdByNetworkMagic).filter((id) => Boolean(id)).map((id) => {
|
|
1158
|
+
return {
|
|
1159
|
+
id: CardanoNetworkId(getCardanoChainIdByTestnetId(id).networkMagic),
|
|
1160
|
+
label: id === "preprod" ? "v2.network-status.preprod" : id === "preview" ? "v2.network-status.preview" : "v2.network-status.preprod"
|
|
1161
|
+
};
|
|
1162
|
+
});
|
|
1163
|
+
};
|
|
1164
|
+
const registerCardanoTestnetOptions = (testnetOptions) => (_, { network: { selectTestnetOptions$ } }, { actions }) => selectTestnetOptions$.pipe(filter((options) => !options?.Cardano), map(() => actions.network.setTestnetOptions({
|
|
1165
|
+
blockchainName: "Cardano",
|
|
1166
|
+
options: testnetOptions
|
|
1167
|
+
})));
|
|
1168
|
+
const createCardanoSideEffects = (config) => {
|
|
1169
|
+
return [registerCardanoTestnetOptions(deriveCardanoTestnetOptions(config))];
|
|
1170
|
+
};
|
|
1171
|
+
//#endregion
|
|
1172
|
+
//#region ../../packages/module/blockchain-cardano/src/store/init.ts
|
|
1173
|
+
const redux = async (props, dependencies) => ({
|
|
1174
|
+
sideEffects: [
|
|
1175
|
+
...createCardanoSideEffects(props.runtime.config),
|
|
1176
|
+
...composerFlowSideEffects,
|
|
1177
|
+
...sdkExtensionSideEffects
|
|
1178
|
+
],
|
|
1179
|
+
sideEffectDependencies: await initializeDependencies(props, dependencies)
|
|
1180
|
+
});
|
|
1181
|
+
//#endregion
|
|
1182
|
+
export { redux as default };
|