From 4f87f703124a531fa416cf649623e07d6a1a7980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 28 Aug 2024 18:48:01 +0200 Subject: [PATCH 1/2] fix(#1845): fix submitting guardrail related governance actions --- CHANGELOG.md | 2 +- govtool/frontend/src/context/wallet.tsx | 193 +++++++++++++++++++++--- 2 files changed, 171 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 100733f56..8d7edc7ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ changes. ### Fixed -- +- Fix submitting treasury governance action [Issue 1845](https://github.com/IntersectMBO/govtool/issues/1845) ### Changed diff --git a/govtool/frontend/src/context/wallet.tsx b/govtool/frontend/src/context/wallet.tsx index db5b6e76e..f71fb17a4 100644 --- a/govtool/frontend/src/context/wallet.tsx +++ b/govtool/frontend/src/context/wallet.tsx @@ -51,6 +51,18 @@ import { ProtocolVersion, HardForkInitiationAction, ScriptHash, + PlutusScripts, + Redeemers, + Redeemer, + RedeemerTag, + PlutusData, + PlutusMap, + PlutusWitness, + PlutusScriptSource, + Int, + CostModel, + Language, + TxInputsBuilder, } from "@emurgo/cardano-serialization-lib-asmjs"; import { Buffer } from "buffer"; import { useNavigate } from "react-router-dom"; @@ -239,6 +251,7 @@ CardanoContext.displayName = "CardanoContext"; const CardanoProvider = (props: Props) => { const [isEnabled, setIsEnabled] = useState(false); + const [isGuardrailScriptUsed, setIsGuardrailScriptUsed] = useState(false); const [isEnableLoading, setIsEnableLoading] = useState(null); const [walletApi, setWalletApi] = useState( undefined, @@ -259,6 +272,7 @@ const CardanoProvider = (props: Props) => { changeAddress: undefined, usedAddress: undefined, }); + const [redeemers, setRedeemers] = useState([]); const { t } = useTranslation(); const epochParams = getItemFromLocalStorage(PROTOCOL_PARAMS_KEY); @@ -466,25 +480,40 @@ const CardanoProvider = (props: Props) => { PROTOCOL_PARAMS_KEY, ) as Protocol; + const exUnitPrices = ExUnitPrices.new( + UnitInterval.new( + BigNum.from_str(String(protocolParams.price_mem)), + BigNum.from_str(String("10000")), + ), + UnitInterval.new( + BigNum.from_str(String(protocolParams.price_step)), + BigNum.from_str(String("10000000")), + ), + ); + if (protocolParams) { - const txBuilder = TransactionBuilder.new( - TransactionBuilderConfigBuilder.new() - .fee_algo( - LinearFee.new( - BigNum.from_str(String(protocolParams.min_fee_a)), - BigNum.from_str(String(protocolParams.min_fee_b)), - ), - ) - .pool_deposit(BigNum.from_str(String(protocolParams.pool_deposit))) - .key_deposit(BigNum.from_str(String(protocolParams.key_deposit))) - .coins_per_utxo_byte( - BigNum.from_str(String(protocolParams.coins_per_utxo_size)), - ) - .max_value_size(protocolParams.max_val_size) - .max_tx_size(protocolParams.max_tx_size) - .prefer_pure_change(true) - .build(), - ); + const txConfigBuilder = TransactionBuilderConfigBuilder.new() + .fee_algo( + LinearFee.new( + BigNum.from_str(String(protocolParams.min_fee_a)), + BigNum.from_str(String(protocolParams.min_fee_b)), + ), + ) + .pool_deposit(BigNum.from_str(String(protocolParams.pool_deposit))) + .key_deposit(BigNum.from_str(String(protocolParams.key_deposit))) + .coins_per_utxo_byte( + BigNum.from_str(String(protocolParams.coins_per_utxo_size)), + ) + .max_value_size(protocolParams.max_val_size) + .max_tx_size(protocolParams.max_tx_size) + .prefer_pure_change(true); + + if (isGuardrailScriptUsed) { + txConfigBuilder.ex_unit_prices(exUnitPrices); + } + + const txBuilder = TransactionBuilder.new(txConfigBuilder.build()); + return txBuilder; } }, []); @@ -513,6 +542,7 @@ const CardanoProvider = (props: Props) => { try { const txBuilder = await initTransactionBuilder(); + const transactionWitnessSet = TransactionWitnessSet.new(); if (!txBuilder) { throw new Error(t("errors.appCannotCreateTransaction")); @@ -536,6 +566,51 @@ const CardanoProvider = (props: Props) => { txBuilder.set_voting_proposal_builder(govActionBuilder); } + if (isGuardrailScriptUsed) { + try { + const scripts = PlutusScripts.new(); + scripts.add( + PlutusScript.from_bytes_v3(Buffer.from(GUARDRAIL_SCRIPT, "hex")), + ); + transactionWitnessSet.set_plutus_scripts(scripts); + + const newRedeemers = Redeemers.new(); + redeemers.forEach((redeemer) => { + newRedeemers.add(redeemer); + }); + transactionWitnessSet.set_redeemers(newRedeemers); + + const costModels = Costmdls.new(); + const v1CostModels = CostModel.new(); + ( + epochParams?.cost_model?.costs?.PlutusV1 as number[] | undefined + )?.forEach((val, index) => { + v1CostModels.set(index, Int.new_i32(val)); + }); + costModels.insert(Language.new_plutus_v1(), v1CostModels); + + const v2CostModels = CostModel.new(); + ( + epochParams?.cost_model?.costs?.PlutusV2 as number[] | undefined + )?.forEach((val, index) => { + v2CostModels.set(index, Int.new_i32(val)); + }); + costModels.insert(Language.new_plutus_v2(), v2CostModels); + + const v3CostModels = CostModel.new(); + ( + epochParams?.cost_model?.costs?.PlutusV3 as number[] | undefined + )?.forEach((val, index) => { + v3CostModels.set(index, Int.new_i32(val)); + }); + costModels.insert(Language.new_plutus_v3(), v3CostModels); + + txBuilder.calc_script_data_hash(costModels); + } catch (e) { + console.error(e); + } + } + if ( !walletState.changeAddress || !walletState.usedAddress || @@ -553,6 +628,32 @@ const CardanoProvider = (props: Props) => { } // Find the available UTXOs in the wallet and use them as Inputs for the transaction const txUnspentOutputs = await getTxUnspentOutputs(utxos); + + if (isGuardrailScriptUsed) { + const txInputsBuilder = TxInputsBuilder.new(); + const probableCollaterals = utxos + .filter((utxo) => !utxo.multiAssetStr) + .map((utxo) => ({ + ...utxo, + amount: BigInt(utxo.amount), + })) + .sort((a, b) => (a.amount > b.amount ? -1 : 1)); + + if (probableCollaterals.length) { + const unspentOutput = + probableCollaterals[0].TransactionUnspentOutput; + const output = unspentOutput.output(); + txInputsBuilder.add_regular_input( + output.address(), + unspentOutput.input(), + output.amount(), + ); + txBuilder.set_collateral(txInputsBuilder); + } else { + throw new Error(t("errors.setCollateral")); + } + } + const changeConfig = ChangeConfig.new(shelleyChangeAddress); // Use UTxO selection strategy 3 try { @@ -575,7 +676,6 @@ const CardanoProvider = (props: Props) => { const txBody = txBuilder.build(); // Make a full transaction, passing in empty witness set - const transactionWitnessSet = TransactionWitnessSet.new(); const tx = Transaction.new( txBody, TransactionWitnessSet.from_bytes(transactionWitnessSet.to_bytes()), @@ -608,6 +708,8 @@ const CardanoProvider = (props: Props) => { resourceId, }); + setIsGuardrailScriptUsed(false); + // eslint-disable-next-line no-console console.log(signedTx.to_hex(), "signed tx cbor"); return resultHash; @@ -835,6 +937,42 @@ const CardanoProvider = (props: Props) => { return RewardAddress.from_address(Address.from_bech32(bech32Address)); }, [walletApi]); + const addVotingProposalToBuilder = useCallback( + ( + govActionBuilder: VotingProposalBuilder, + votingProposal: VotingProposal, + guardrailScript: PlutusScript, + ) => { + let redeemer: Redeemer; + if (guardrailScript) { + const redeemerTag = RedeemerTag.new_voting_proposal(); + const plutusData = PlutusData.new_map(PlutusMap.new()); + const exUnits = ExUnits.new( + BigNum.from_str("402468"), + BigNum.from_str("89488792"), + ); + redeemer = Redeemer.new( + redeemerTag, + BigNum.from_str("0"), + plutusData, + exUnits, + ); + const witness = PlutusWitness.new_with_ref_without_datum( + PlutusScriptSource.new(guardrailScript), + redeemer, + ); + setRedeemers((prevValue) => [...prevValue, redeemer]); + setIsGuardrailScriptUsed(true); + govActionBuilder.add_with_plutus_witness(votingProposal, witness); + } else { + govActionBuilder.add(votingProposal); + } + + return govActionBuilder; + }, + [], + ); + // info action const buildNewInfoGovernanceAction = useCallback( async ({ hash, url }: InfoProps) => { @@ -902,9 +1040,14 @@ const CardanoProvider = (props: Props) => { rewardAddr, BigNum.from_str(epochParams?.gov_action_deposit.toString()), ); - govActionBuilder.add(votingProposal); - return govActionBuilder; + const govActionBuilderWithVotingProposal = addVotingProposalToBuilder( + govActionBuilder, + votingProposal, + guardrailScript, + ); + + return govActionBuilderWithVotingProposal; } catch (err) { console.error(err); } @@ -971,9 +1114,13 @@ const CardanoProvider = (props: Props) => { rewardAddr, BigNum.from_str(epochParams?.gov_action_deposit.toString()), ); - govActionBuilder.add(votingProposal); + const govActionBuilderWithVotingProposal = addVotingProposalToBuilder( + govActionBuilder, + votingProposal, + guardrailScript, + ); - return govActionBuilder; + return govActionBuilderWithVotingProposal; } catch (err) { console.error(err); } From a1e05acf28956d9a15688258f2c60dc8332d3ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Sun, 10 Nov 2024 22:48:30 +0100 Subject: [PATCH 2/2] fix(#1845): set guardrail script network related --- govtool/frontend/src/consts/index.ts | 10 +- govtool/frontend/src/context/wallet.tsx | 215 +++++++++++++----------- 2 files changed, 126 insertions(+), 99 deletions(-) diff --git a/govtool/frontend/src/consts/index.ts b/govtool/frontend/src/consts/index.ts index 7d48cede4..b865f3d14 100644 --- a/govtool/frontend/src/consts/index.ts +++ b/govtool/frontend/src/consts/index.ts @@ -25,5 +25,11 @@ export const CEXPLORER_BASE_URLS = { mainnet: "https://cexplorer.io", }; -export const GUARDRAIL_SCRIPT = - "59082f59082c0101003232323232323232323232323232323232323232323232323232323232323232323232323232323232323225932325333573466e1d2000001180098121bab357426ae88d55cf001054ccd5cd19b874801000460042c6aae74004dd51aba1357446ae88d55cf1baa325333573466e1d200a35573a00226ae84d5d11aab9e0011637546ae84d5d11aba235573c6ea800642b26006003149a2c8a4c3021801c0052000c00e0070018016006901e40608058c00e00290016007003800c00b0034830268320306007001800600690406d6204e00060001801c0052004c00e007001801600690404001e0006007001800600690404007e00060001801c0052006c00e006023801c006001801a4101000980018000600700148023003801808e0070018006006904827600060001801c005200ac00e0070018016006904044bd4060c00e003000c00d2080ade204c000c0003003800a4019801c00e003002c00d2080cab5ee0180c100d1801c005200ec00e0060238000c00e00290086007003800c00b003483d00e0306007001800600690500fe00040243003800a4025803c00c01a0103003800a4029803c00e003002c00cc07520d00f8079801c006001801980ea4120078001800060070014805b00780180360070018006006603e900a4038c0003003800a4041801c00c04601a3003800a4045801c00e003002c00d20f02e80c1801c006001801a4190cb80010090c00e00290126000c00e0029013600b003803c00e003002c00cc0752032c000c00e003000c00cc075200ac000c0006007007801c006005801980ea418170058001801c006001801980ea41209d80018000c0003003800a4051802c00e007003011c00e003000c00d2080e89226c000c0006007003801808e007001800600690406c4770b7e000600030000c00e0029015600b003801c00c047003800c00300348202e2e1cb00030001801c00e006023801c006001801a410181f905540580018000c0003003800a4059801c00c047003800c00300348203000700030000c00e00290176007003800c00b003483200603060070018006006904801e00040243003800a4061801c00c0430001801c0052032c016006003801801e00600780180140100c00e002901a600b003001c00c00f003003c00c00f003002c00c007003001c00c007003803c00e003002c00c0560184014802000c00e002901b6007003800c00b003480030034801b0001801c006001801a4029800180006007001480e3003801c006005801a4001801a40498000c00e003000c00d20ca04c00080486007001480eb00380180860070018006006900f600060001801c005203cc00e006015801c006001801a4101012bcf138c09800180006007001480fb003801805600700180060069040505bc3f482e00060001801c0052040c00e0070018016006900d4060c00e003000c00d204ac000c0003003800a4085801c00c04601630000000000200f003006c00e003000c00c05a0166000200f003005c00e003000c00c057003010c0006000200f003800c00b003012c00cc05d2028c0004008801c01e007001801600602380010043000400e003000c00c04b003011c0006000800c00b00300d8049001801600601d801980924190038000801c0060010066000801c00600900f6000800c00b003480030034820225eb0001003800c003003483403f0003000400c023000400e003000c00d208094ebdc03c000c001003009c001003300f4800b0004006005801a40058001001801401c6014900518052402860169004180424008600a900a180324005003480030001806240cc6016900d18052402460129004180424004600e900018032400c6014446666aae7c004a0005003328009aab9d0019aab9e0011aba100298019aba200224c6012444a6520071300149a4432005225900689802a4d2219002912c998099bad0020068ac99807002800c4cc03001c00e300244cc03001c02a3002012c801460012218010c00888004c004880094cc8c0040048848c8cc0088c00888c00800c8c00888c00400c8d4cc01001000cd400c0044888cc00c896400a300090999804c00488ccd5cd19b87002001800400a01522333573466e2000800600100291199ab9a33712004003000801488ccd5cd19b89002001801400244666ae68cdc4001000c00a001225333573466e240080044004400a44a666ae68cdc4801000880108008004dd6801484cc010004dd6001484c8ccc02a002452005229003912999ab9a3370e0080042666ae68cdc3801800c00200430022452005229003911980899b820040013370400400648a400a45200722333573466e20cdc100200099b82002003800400880648a400a45200722333573466e24cdc100200099b82002003801400091480148a400e44666ae68cdc419b8200400133704004007002800122593300e0020018800c400922593300e00200188014400400233323357346ae8cd5d10009198051bad357420066eb4d5d08011aba2001268001bac00214800c8ccd5cd1aba3001800400a444b26600c0066ae8400626600a0046ae8800630020c0148894ccd5cd19b87480000045854ccd5cd19b88001480004cc00ccdc0a400000466e05200000113280099b8400300199b840020011980200100098021112999ab9a3370e9000000880109980180099b860020012223300622590018c002443200522323300d225900189804803488564cc0140080322600800318010004b20051900991111111001a3201322222222005448964ce402e444444440100020018c00a30000002225333573466e1c00800460002a666ae68cdc48010008c010600445200522900391199ab9a3371266e08010004cdc1001001c0020041191800800918011198010010009"; +export const COMPILED_GUARDRAIL_SCRIPTS = { + sanchonet: + "59082f59082c0101003232323232323232323232323232323232323232323232323232323232323232323232323232323232323225932325333573466e1d2000001180098121bab357426ae88d55cf001054ccd5cd19b874801000460042c6aae74004dd51aba1357446ae88d55cf1baa325333573466e1d200a35573a00226ae84d5d11aab9e0011637546ae84d5d11aba235573c6ea800642b26006003149a2c8a4c3021801c0052000c00e0070018016006901e40608058c00e00290016007003800c00b0034830268320306007001800600690406d6204e00060001801c0052004c00e007001801600690404001e0006007001800600690404007e00060001801c0052006c00e006023801c006001801a4101000980018000600700148023003801808e0070018006006904827600060001801c005200ac00e0070018016006904044bd4060c00e003000c00d2080ade204c000c0003003800a4019801c00e003002c00d2080cab5ee0180c100d1801c005200ec00e0060238000c00e00290086007003800c00b003483d00e0306007001800600690500fe00040243003800a4025803c00c01a0103003800a4029803c00e003002c00cc07520d00f8079801c006001801980ea4120078001800060070014805b00780180360070018006006603e900a4038c0003003800a4041801c00c04601a3003800a4045801c00e003002c00d20f02e80c1801c006001801a4190cb80010090c00e00290126000c00e0029013600b003803c00e003002c00cc0752032c000c00e003000c00cc075200ac000c0006007007801c006005801980ea418170058001801c006001801980ea41209d80018000c0003003800a4051802c00e007003011c00e003000c00d2080e89226c000c0006007003801808e007001800600690406c4770b7e000600030000c00e0029015600b003801c00c047003800c00300348202e2e1cb00030001801c00e006023801c006001801a410181f905540580018000c0003003800a4059801c00c047003800c00300348203000700030000c00e00290176007003800c00b003483200603060070018006006904801e00040243003800a4061801c00c0430001801c0052032c016006003801801e00600780180140100c00e002901a600b003001c00c00f003003c00c00f003002c00c007003001c00c007003803c00e003002c00c0560184014802000c00e002901b6007003800c00b003480030034801b0001801c006001801a4029800180006007001480e3003801c006005801a4001801a40498000c00e003000c00d20ca04c00080486007001480eb00380180860070018006006900f600060001801c005203cc00e006015801c006001801a4101012bcf138c09800180006007001480fb003801805600700180060069040505bc3f482e00060001801c0052040c00e0070018016006900d4060c00e003000c00d204ac000c0003003800a4085801c00c04601630000000000200f003006c00e003000c00c05a0166000200f003005c00e003000c00c057003010c0006000200f003800c00b003012c00cc05d2028c0004008801c01e007001801600602380010043000400e003000c00c04b003011c0006000800c00b00300d8049001801600601d801980924190038000801c0060010066000801c00600900f6000800c00b003480030034820225eb0001003800c003003483403f0003000400c023000400e003000c00d208094ebdc03c000c001003009c001003300f4800b0004006005801a40058001001801401c6014900518052402860169004180424008600a900a180324005003480030001806240cc6016900d18052402460129004180424004600e900018032400c6014446666aae7c004a0005003328009aab9d0019aab9e0011aba100298019aba200224c6012444a6520071300149a4432005225900689802a4d2219002912c998099bad0020068ac99807002800c4cc03001c00e300244cc03001c02a3002012c801460012218010c00888004c004880094cc8c0040048848c8cc0088c00888c00800c8c00888c00400c8d4cc01001000cd400c0044888cc00c896400a300090999804c00488ccd5cd19b87002001800400a01522333573466e2000800600100291199ab9a33712004003000801488ccd5cd19b89002001801400244666ae68cdc4001000c00a001225333573466e240080044004400a44a666ae68cdc4801000880108008004dd6801484cc010004dd6001484c8ccc02a002452005229003912999ab9a3370e0080042666ae68cdc3801800c00200430022452005229003911980899b820040013370400400648a400a45200722333573466e20cdc100200099b82002003800400880648a400a45200722333573466e24cdc100200099b82002003801400091480148a400e44666ae68cdc419b8200400133704004007002800122593300e0020018800c400922593300e00200188014400400233323357346ae8cd5d10009198051bad357420066eb4d5d08011aba2001268001bac00214800c8ccd5cd1aba3001800400a444b26600c0066ae8400626600a0046ae8800630020c0148894ccd5cd19b87480000045854ccd5cd19b88001480004cc00ccdc0a400000466e05200000113280099b8400300199b840020011980200100098021112999ab9a3370e9000000880109980180099b860020012223300622590018c002443200522323300d225900189804803488564cc0140080322600800318010004b20051900991111111001a3201322222222005448964ce402e444444440100020018c00a30000002225333573466e1c00800460002a666ae68cdc48010008c010600445200522900391199ab9a3371266e08010004cdc1001001c0020041191800800918011198010010009", + preview: + "5908545908510101003232323232323232323232323232323232323232323232323232323232323232323232323232323232259323255333573466e1d20000011180098111bab357426ae88d55cf00104554ccd5cd19b87480100044600422c6aae74004dd51aba1357446ae88d55cf1baa3255333573466e1d200a35573a002226ae84d5d11aab9e00111637546ae84d5d11aba235573c6ea800642b26006003149a2c8a4c301f801c0052000c00e0070018016006901e4070c00e003000c00d20d00fc000c0003003800a4005801c00e003002c00d20c09a0c80e1801c006001801a4101b5881380018000600700148013003801c006005801a410100078001801c006001801a4101001f8001800060070014801b0038018096007001800600690404002600060001801c0052008c00e006025801c006001801a41209d8001800060070014802b003801c006005801a410112f501c3003800c00300348202b7881300030000c00e00290066007003800c00b003482032ad7b806038403060070014803b00380180960003003800a4021801c00e003002c00d20f40380e1801c006001801a41403f800100a0c00e0029009600f0030078040c00e002900a600f003800c00b003301a483403e01a600700180060066034904801e00060001801c0052016c01e00600f801c006001801980c2402900e30000c00e002901060070030128060c00e00290116007003800c00b003483c0ba03860070018006006906432e00040283003800a40498003003800a404d802c00e00f003800c00b003301a480cb0003003800c003003301a4802b00030001801c01e0070018016006603490605c0160006007001800600660349048276000600030000c00e0029014600b003801c00c04b003800c00300348203a2489b00030001801c00e006025801c006001801a4101b11dc2df80018000c0003003800a4055802c00e007003012c00e003000c00d2080b8b872c000c0006007003801809600700180060069040607e4155016000600030000c00e00290166007003012c00e003000c00d2080c001c000c0003003800a405d801c00e003002c00d20c80180e1801c006001801a412007800100a0c00e00290186007003013c0006007001480cb005801801e006003801800e00600500403003800a4069802c00c00f003001c00c007003803c00e003002c00c05300333023480692028c0004014c00c00b003003c00c00f003003c00e00f003800c00b00301480590052008003003800a406d801c00e003002c00d2000c00d2006c00060070018006006900a600060001801c0052038c00e007001801600690006006901260003003800c003003483281300020141801c005203ac00e006027801c006001801a403d800180006007001480f3003801804e00700180060069040404af3c4e302600060001801c005203ec00e006013801c006001801a4101416f0fd20b80018000600700148103003801c006005801a403501c3003800c0030034812b00030000c00e0029021600f003800c00a01ac00e003000c00ccc08d20d00f4800b00030000c0000000000803c00c016008401e006009801c006001801807e0060298000c000401e006007801c0060018018074020c000400e00f003800c00b003010c000802180020070018006006019801805e0003000400600580180760060138000800c00b00330134805200c400e00300080330004006005801a4001801a410112f58000801c00600901260008019806a40118002007001800600690404a75ee01e00060008018046000801801e000300c4832004c025201430094800a0030028052003002c00d2002c000300648010c0092002300748028c0312000300b48018c0292012300948008c0212066801a40018000c0192008300a2233335573e00250002801994004d55ce800cd55cf0008d5d08014c00cd5d10011263009222532900389800a4d2219002912c80344c01526910c80148964cc04cdd68010034564cc03801400626601800e0071801226601800e01518010096400a3000910c008600444002600244004a664600200244246466004460044460040064600444600200646a660080080066a00600224446600644b20051800484ccc02600244666ae68cdc3801000c00200500a91199ab9a33710004003000801488ccd5cd19b89002001800400a44666ae68cdc4801000c00a00122333573466e20008006005000912a999ab9a3371200400222002220052255333573466e2400800444008440040026eb400a42660080026eb000a4264666015001229002914801c8954ccd5cd19b8700400211333573466e1c00c006001002118011229002914801c88cc044cdc100200099b82002003245200522900391199ab9a3371066e08010004cdc1001001c002004403245200522900391199ab9a3371266e08010004cdc1001001c00a00048a400a45200722333573466e20cdc100200099b820020038014000912c99807001000c40062004912c99807001000c400a2002001199919ab9a357466ae880048cc028dd69aba1003375a6ae84008d5d1000934000dd60010a40064666ae68d5d1800c0020052225933006003357420031330050023574400318010600a444aa666ae68cdc3a400000222c22aa666ae68cdc4000a4000226600666e05200000233702900000088994004cdc2001800ccdc20010008cc010008004c01088954ccd5cd19b87480000044400844cc00c004cdc300100091119803112c800c60012219002911919806912c800c4c02401a442b26600a004019130040018c008002590028c804c8888888800d1900991111111002a244b267201722222222008001000c600518000001112a999ab9a3370e004002230001155333573466e240080044600823002229002914801c88ccd5cd19b893370400800266e0800800e00100208c8c0040048c0088cc008008005", + mainnet: + "5908545908510101003232323232323232323232323232323232323232323232323232323232323232323232323232323232259323255333573466e1d20000011180098111bab357426ae88d55cf00104554ccd5cd19b87480100044600422c6aae74004dd51aba1357446ae88d55cf1baa3255333573466e1d200a35573a002226ae84d5d11aab9e00111637546ae84d5d11aba235573c6ea800642b26006003149a2c8a4c301f801c0052000c00e0070018016006901e4070c00e003000c00d20d00fc000c0003003800a4005801c00e003002c00d20c09a0c80e1801c006001801a4101b5881380018000600700148013003801c006005801a410100078001801c006001801a4101001f8001800060070014801b0038018096007001800600690404002600060001801c0052008c00e006025801c006001801a41209d8001800060070014802b003801c006005801a410112f501c3003800c00300348202b7881300030000c00e00290066007003800c00b003482032ad7b806038403060070014803b00380180960003003800a4021801c00e003002c00d20f40380e1801c006001801a41403f800100a0c00e0029009600f0030078040c00e002900a600f003800c00b003301a483403e01a600700180060066034904801e00060001801c0052016c01e00600f801c006001801980c2402900e30000c00e002901060070030128060c00e00290116007003800c00b003483c0ba03860070018006006906432e00040283003800a40498003003800a404d802c00e00f003800c00b003301a480cb0003003800c003003301a4802b00030001801c01e0070018016006603490605c0160006007001800600660349048276000600030000c00e0029014600b003801c00c04b003800c00300348203a2489b00030001801c00e006025801c006001801a4101b11dc2df80018000c0003003800a4055802c00e007003012c00e003000c00d2080b8b872c000c0006007003801809600700180060069040607e4155016000600030000c00e00290166007003012c00e003000c00d2080c001c000c0003003800a405d801c00e003002c00d20c80180e1801c006001801a412007800100a0c00e00290186007003013c0006007001480cb005801801e006003801800e00600500403003800a4069802c00c00f003001c00c007003803c00e003002c00c05300333023480692028c0004014c00c00b003003c00c00f003003c00e00f003800c00b00301480590052008003003800a406d801c00e003002c00d2000c00d2006c00060070018006006900a600060001801c0052038c00e007001801600690006006901260003003800c003003483281300020141801c005203ac00e006027801c006001801a403d800180006007001480f3003801804e00700180060069040404af3c4e302600060001801c005203ec00e006013801c006001801a4101416f0fd20b80018000600700148103003801c006005801a403501c3003800c0030034812b00030000c00e0029021600f003800c00a01ac00e003000c00ccc08d20d00f4800b00030000c0000000000803c00c016008401e006009801c006001801807e0060298000c000401e006007801c0060018018074020c000400e00f003800c00b003010c000802180020070018006006019801805e0003000400600580180760060138000800c00b00330134805200c400e00300080330004006005801a4001801a410112f58000801c00600901260008019806a40118002007001800600690404a75ee01e00060008018046000801801e000300c4832004c025201430094800a0030028052003002c00d2002c000300648010c0092002300748028c0312000300b48018c0292012300948008c0212066801a40018000c0192008300a2233335573e00250002801994004d55ce800cd55cf0008d5d08014c00cd5d10011263009222532900389800a4d2219002912c80344c01526910c80148964cc04cdd68010034564cc03801400626601800e0071801226601800e01518010096400a3000910c008600444002600244004a664600200244246466004460044460040064600444600200646a660080080066a00600224446600644b20051800484ccc02600244666ae68cdc3801000c00200500a91199ab9a33710004003000801488ccd5cd19b89002001800400a44666ae68cdc4801000c00a00122333573466e20008006005000912a999ab9a3371200400222002220052255333573466e2400800444008440040026eb400a42660080026eb000a4264666015001229002914801c8954ccd5cd19b8700400211333573466e1c00c006001002118011229002914801c88cc044cdc100200099b82002003245200522900391199ab9a3371066e08010004cdc1001001c002004403245200522900391199ab9a3371266e08010004cdc1001001c00a00048a400a45200722333573466e20cdc100200099b820020038014000912c99807001000c40062004912c99807001000c400a2002001199919ab9a357466ae880048cc028dd69aba1003375a6ae84008d5d1000934000dd60010a40064666ae68d5d1800c0020052225933006003357420031330050023574400318010600a444aa666ae68cdc3a400000222c22aa666ae68cdc4000a4000226600666e05200000233702900000088994004cdc2001800ccdc20010008cc010008004c01088954ccd5cd19b87480000044400844cc00c004cdc300100091119803112c800c60012219002911919806912c800c4c02401a442b26600a004019130040018c008002590028c804c8888888800d1900991111111002a244b267201722222222008001000c600518000001112a999ab9a3370e004002230001155333573466e240080044600823002229002914801c88ccd5cd19b893370400800266e0800800e00100208c8c0040048c0088cc008008005", +}; diff --git a/govtool/frontend/src/context/wallet.tsx b/govtool/frontend/src/context/wallet.tsx index f71fb17a4..27c6e1a66 100644 --- a/govtool/frontend/src/context/wallet.tsx +++ b/govtool/frontend/src/context/wallet.tsx @@ -3,6 +3,7 @@ import { useCallback, useContext, useMemo, + useRef, useState, } from "react"; import { @@ -70,7 +71,7 @@ import { Link } from "@mui/material"; import * as Sentry from "@sentry/react"; import { Trans } from "react-i18next"; -import { PATHS, GUARDRAIL_SCRIPT } from "@consts"; +import { PATHS, COMPILED_GUARDRAIL_SCRIPTS } from "@consts"; import { CardanoApiWallet, Protocol, VoterInfo } from "@models"; import type { StatusModalState } from "@organisms"; import { @@ -250,8 +251,15 @@ const CardanoContext = createContext( CardanoContext.displayName = "CardanoContext"; const CardanoProvider = (props: Props) => { + const { network: networkKey } = useAppContext(); + const guardrailScript = + COMPILED_GUARDRAIL_SCRIPTS[ + networkKey as keyof typeof COMPILED_GUARDRAIL_SCRIPTS + ]; + const [isEnabled, setIsEnabled] = useState(false); - const [isGuardrailScriptUsed, setIsGuardrailScriptUsed] = useState(false); + const isGuardrailScriptUsed = useRef(false); + const redeemers = useRef([]); const [isEnableLoading, setIsEnableLoading] = useState(null); const [walletApi, setWalletApi] = useState( undefined, @@ -272,14 +280,13 @@ const CardanoProvider = (props: Props) => { changeAddress: undefined, usedAddress: undefined, }); - const [redeemers, setRedeemers] = useState([]); const { t } = useTranslation(); const epochParams = getItemFromLocalStorage(PROTOCOL_PARAMS_KEY); const { isPendingTransaction, updateTransaction, pendingTransaction } = usePendingTransaction({ isEnabled, stakeKey }); - const getChangeAddress = async (enabledApi: CardanoApiWallet) => { + const getChangeAddress = useCallback(async (enabledApi: CardanoApiWallet) => { try { const raw = await enabledApi.getChangeAddress(); const changeAddress = Address.from_bytes( @@ -292,7 +299,7 @@ const CardanoProvider = (props: Props) => { } catch (err) { console.error(err); } - }; + }, []); const getUsedAddresses = async (enabledApi: CardanoApiWallet) => { try { @@ -456,7 +463,7 @@ const CardanoProvider = (props: Props) => { // eslint-disable-next-line no-throw-literal throw { status: "ERROR", error: t("errors.somethingWentWrong") }; }, - [isEnabled, stakeKeys], + [getChangeAddress, isEnabled, t], ); const disconnectWallet = useCallback(async () => { @@ -480,40 +487,37 @@ const CardanoProvider = (props: Props) => { PROTOCOL_PARAMS_KEY, ) as Protocol; - const exUnitPrices = ExUnitPrices.new( - UnitInterval.new( - BigNum.from_str(String(protocolParams.price_mem)), - BigNum.from_str(String("10000")), - ), - UnitInterval.new( - BigNum.from_str(String(protocolParams.price_step)), - BigNum.from_str(String("10000000")), - ), - ); - if (protocolParams) { - const txConfigBuilder = TransactionBuilderConfigBuilder.new() - .fee_algo( - LinearFee.new( - BigNum.from_str(String(protocolParams.min_fee_a)), - BigNum.from_str(String(protocolParams.min_fee_b)), - ), - ) - .pool_deposit(BigNum.from_str(String(protocolParams.pool_deposit))) - .key_deposit(BigNum.from_str(String(protocolParams.key_deposit))) - .coins_per_utxo_byte( - BigNum.from_str(String(protocolParams.coins_per_utxo_size)), - ) - .max_value_size(protocolParams.max_val_size) - .max_tx_size(protocolParams.max_tx_size) - .prefer_pure_change(true); - - if (isGuardrailScriptUsed) { - txConfigBuilder.ex_unit_prices(exUnitPrices); - } - - const txBuilder = TransactionBuilder.new(txConfigBuilder.build()); - + const txBuilder = TransactionBuilder.new( + TransactionBuilderConfigBuilder.new() + .fee_algo( + LinearFee.new( + BigNum.from_str(String(protocolParams.min_fee_a)), + BigNum.from_str(String(protocolParams.min_fee_b)), + ), + ) + .pool_deposit(BigNum.from_str(String(protocolParams.pool_deposit))) + .key_deposit(BigNum.from_str(String(protocolParams.key_deposit))) + .coins_per_utxo_byte( + BigNum.from_str(String(protocolParams.coins_per_utxo_size)), + ) + .max_value_size(protocolParams.max_val_size) + .max_tx_size(protocolParams.max_tx_size) + .prefer_pure_change(true) + .ex_unit_prices( + ExUnitPrices.new( + UnitInterval.new( + BigNum.from_str("577"), + BigNum.from_str("10000"), + ), + UnitInterval.new( + BigNum.from_str("721"), + BigNum.from_str("10000000"), + ), + ), + ) + .build(), + ); return txBuilder; } }, []); @@ -566,44 +570,41 @@ const CardanoProvider = (props: Props) => { txBuilder.set_voting_proposal_builder(govActionBuilder); } - if (isGuardrailScriptUsed) { + if (isGuardrailScriptUsed.current) { try { const scripts = PlutusScripts.new(); scripts.add( - PlutusScript.from_bytes_v3(Buffer.from(GUARDRAIL_SCRIPT, "hex")), + PlutusScript.from_bytes_v3(Buffer.from(guardrailScript, "hex")), ); transactionWitnessSet.set_plutus_scripts(scripts); const newRedeemers = Redeemers.new(); - redeemers.forEach((redeemer) => { + redeemers.current.forEach((redeemer) => { newRedeemers.add(redeemer); }); transactionWitnessSet.set_redeemers(newRedeemers); const costModels = Costmdls.new(); - const v1CostModels = CostModel.new(); - ( - epochParams?.cost_model?.costs?.PlutusV1 as number[] | undefined - )?.forEach((val, index) => { - v1CostModels.set(index, Int.new_i32(val)); - }); - costModels.insert(Language.new_plutus_v1(), v1CostModels); - const v2CostModels = CostModel.new(); - ( - epochParams?.cost_model?.costs?.PlutusV2 as number[] | undefined - )?.forEach((val, index) => { - v2CostModels.set(index, Int.new_i32(val)); - }); - costModels.insert(Language.new_plutus_v2(), v2CostModels); - - const v3CostModels = CostModel.new(); - ( - epochParams?.cost_model?.costs?.PlutusV3 as number[] | undefined - )?.forEach((val, index) => { - v3CostModels.set(index, Int.new_i32(val)); - }); - costModels.insert(Language.new_plutus_v3(), v3CostModels); + const addCostModels = ( + language: "v1" | "v2" | "v3", + model: "PlutusV1" | "PlutusV2" | "PlutusV3", + ) => { + const costModel = CostModel.new(); + ( + epochParams?.cost_model?.costs?.[model] as number[] | undefined + )?.forEach((val, index) => + costModel.set(index, Int.new_i32(val)), + ); + costModels.insert( + Language[`new_plutus_${language}`](), + costModel, + ); + }; + + addCostModels("v1", "PlutusV1"); + addCostModels("v2", "PlutusV2"); + addCostModels("v3", "PlutusV3"); txBuilder.calc_script_data_hash(costModels); } catch (e) { @@ -629,7 +630,7 @@ const CardanoProvider = (props: Props) => { // Find the available UTXOs in the wallet and use them as Inputs for the transaction const txUnspentOutputs = await getTxUnspentOutputs(utxos); - if (isGuardrailScriptUsed) { + if (isGuardrailScriptUsed.current) { const txInputsBuilder = TxInputsBuilder.new(); const probableCollaterals = utxos .filter((utxo) => !utxo.multiAssetStr) @@ -676,10 +677,7 @@ const CardanoProvider = (props: Props) => { const txBody = txBuilder.build(); // Make a full transaction, passing in empty witness set - const tx = Transaction.new( - txBody, - TransactionWitnessSet.from_bytes(transactionWitnessSet.to_bytes()), - ); + const tx = Transaction.new(txBody, transactionWitnessSet); // Ask wallet to to provide signature (witnesses) for the transaction let txVkeyWitnesses; @@ -687,7 +685,7 @@ const CardanoProvider = (props: Props) => { // Create witness set object using the witnesses provided by the wallet txVkeyWitnesses = TransactionWitnessSet.from_bytes( - Buffer.from(txVkeyWitnesses, "hex"), + Buffer.from(await walletApi.signTx(tx.to_hex(), true), "hex"), ); const vkeys = txVkeyWitnesses.vkeys(); @@ -708,7 +706,7 @@ const CardanoProvider = (props: Props) => { resourceId, }); - setIsGuardrailScriptUsed(false); + isGuardrailScriptUsed.current = false; // eslint-disable-next-line no-console console.log(signedTx.to_hex(), "signed tx cbor"); @@ -727,7 +725,18 @@ const CardanoProvider = (props: Props) => { throw error?.info ?? error; } }, - [isPendingTransaction, stakeKey, updateTransaction, walletApi, walletState], + [ + isPendingTransaction, + initTransactionBuilder, + walletState.changeAddress, + walletState.usedAddress, + walletApi, + t, + updateTransaction, + guardrailScript, + epochParams?.cost_model?.costs, + disconnectWallet, + ], ); const buildStakeKeyRegCert = useCallback(async (): Promise => { @@ -746,7 +755,7 @@ const CardanoProvider = (props: Props) => { console.error(e); throw e; } - }, [epochParams]); + }, [epochParams.key_deposit, stakeKey, t]); const buildVoteDelegationCert = useCallback( async (target: string): Promise => { @@ -781,7 +790,7 @@ const CardanoProvider = (props: Props) => { throw e; } }, - [stakeKey, registeredStakeKeysListState], + [stakeKey, t], ); // conway alpha @@ -818,7 +827,7 @@ const CardanoProvider = (props: Props) => { throw e; } }, - [epochParams, dRepID], + [dRepID, epochParams?.drep_deposit, t], ); const buildDRepUpdateCert = useCallback( @@ -941,10 +950,10 @@ const CardanoProvider = (props: Props) => { ( govActionBuilder: VotingProposalBuilder, votingProposal: VotingProposal, - guardrailScript: PlutusScript, + plutusScript: PlutusScript, ) => { let redeemer: Redeemer; - if (guardrailScript) { + if (isGuardrailScriptUsed.current) { const redeemerTag = RedeemerTag.new_voting_proposal(); const plutusData = PlutusData.new_map(PlutusMap.new()); const exUnits = ExUnits.new( @@ -957,12 +966,12 @@ const CardanoProvider = (props: Props) => { plutusData, exUnits, ); + const witness = PlutusWitness.new_with_ref_without_datum( - PlutusScriptSource.new(guardrailScript), + PlutusScriptSource.new(plutusScript), redeemer, ); - setRedeemers((prevValue) => [...prevValue, redeemer]); - setIsGuardrailScriptUsed(true); + redeemers.current.push(redeemer); govActionBuilder.add_with_plutus_witness(votingProposal, witness); } else { govActionBuilder.add(votingProposal); @@ -1018,13 +1027,15 @@ const CardanoProvider = (props: Props) => { const myWithdrawal = BigNum.from_str(amount); const withdrawals = TreasuryWithdrawals.new(); withdrawals.insert(treasuryTarget, myWithdrawal); - const guardrailScript = PlutusScript.from_bytes_v3( - Buffer.from(GUARDRAIL_SCRIPT, "hex"), + const guardrailPlutusScript = PlutusScript.from_bytes_v3( + Buffer.from(guardrailScript, "hex"), ); const treasuryAction = TreasuryWithdrawalsAction.new_with_policy_hash( withdrawals, - guardrailScript.hash(), + guardrailPlutusScript.hash(), ); + isGuardrailScriptUsed.current = true; + const treasuryGovAct = GovernanceAction.new_treasury_withdrawals_action(treasuryAction); // Create an anchor @@ -1041,18 +1052,23 @@ const CardanoProvider = (props: Props) => { BigNum.from_str(epochParams?.gov_action_deposit.toString()), ); - const govActionBuilderWithVotingProposal = addVotingProposalToBuilder( + addVotingProposalToBuilder( govActionBuilder, votingProposal, - guardrailScript, + guardrailPlutusScript, ); - return govActionBuilderWithVotingProposal; + return govActionBuilder; } catch (err) { console.error(err); } }, - [epochParams, getRewardAddress], + [ + addVotingProposalToBuilder, + epochParams?.gov_action_deposit, + getRewardAddress, + guardrailScript, + ], ); const buildProtocolParameterChangeGovernanceAction = useCallback( @@ -1073,8 +1089,8 @@ const CardanoProvider = (props: Props) => { setProtocolParameterUpdate(protocolParameterUpdate, key, value); } - const guardrailScript = PlutusScript.from_bytes_v3( - Buffer.from(GUARDRAIL_SCRIPT, "hex"), + const guardrailPlutusScript = PlutusScript.from_bytes_v3( + Buffer.from(guardrailScript, "hex"), ); let protocolParamChangeAction; if (prevGovernanceActionHash && prevGovernanceActionIndex) { @@ -1086,13 +1102,13 @@ const CardanoProvider = (props: Props) => { ParameterChangeAction.new_with_policy_hash_and_action_id( prevGovernanceActionId, protocolParameterUpdate, - guardrailScript.hash(), + guardrailPlutusScript.hash(), ); } else { protocolParamChangeAction = ParameterChangeAction.new_with_policy_hash( protocolParameterUpdate, - guardrailScript.hash(), + guardrailPlutusScript.hash(), ); } @@ -1114,18 +1130,23 @@ const CardanoProvider = (props: Props) => { rewardAddr, BigNum.from_str(epochParams?.gov_action_deposit.toString()), ); - const govActionBuilderWithVotingProposal = addVotingProposalToBuilder( + addVotingProposalToBuilder( govActionBuilder, votingProposal, - guardrailScript, + guardrailPlutusScript, ); - return govActionBuilderWithVotingProposal; + return govActionBuilder; } catch (err) { console.error(err); } }, - [], + [ + addVotingProposalToBuilder, + epochParams?.gov_action_deposit, + getRewardAddress, + guardrailScript, + ], ); const buildHardForkGovernanceAction = useCallback( @@ -1183,7 +1204,7 @@ const CardanoProvider = (props: Props) => { console.error(err); } }, - [], + [epochParams?.gov_action_deposit, getRewardAddress], ); const value = useMemo( @@ -1328,7 +1349,7 @@ function useCardano() { throw e; } }, - [context, openModal, context.isEnabled], + [context, closeModal, addSuccessAlert, t, openModal, networkName, navigate], ); const disconnectWallet = useCallback(async () => {