diff --git a/lib/hardfork.ak b/lib/hardfork.ak index 1fa624d..406beaa 100644 --- a/lib/hardfork.ak +++ b/lib/hardfork.ak @@ -856,6 +856,7 @@ pub fn hard_fork( // Handle getting input state expect [script_input1, script_input2, script_input3] = script_inputs + // I'll replace this with something better eventually let (hard_fork_state_input, miner_lock_input, nft_input) = if script_input1.output_reference == hard_fork_state_input { if script_input2.output_reference == nft_input_ref { diff --git a/miner/main.ts b/miner/main.ts index ee4efe9..e762adb 100644 --- a/miner/main.ts +++ b/miner/main.ts @@ -35,6 +35,20 @@ type Genesis = { outRef: { txHash: string; index: number }; }; +type GenesisHF = { + validatorv1: string; + validatorHashv1: string; + + validator: string; + validatorHash: string; + validatorAddress: string; + + validatorv2: string; + validatorHashv2: string; + validatorAddressv2: string; + outRef: { txHash: string; index: number }; +}; + const delay = (ms: number | undefined) => new Promise((res) => setTimeout(res, ms)); @@ -380,6 +394,7 @@ const genesisRegister = new Command() .option("-p, --preview", "Use testnet") .action(async ({ preview, ogmiosUrl, kupoUrl }) => { const unAppliedValidator = readValidator(); + const genesisFile = Deno.readTextFileSync( `genesis/${preview ? "preview" : "mainnet"}.json`, ); @@ -439,6 +454,7 @@ const genesisRegister = new Command() } }); +// Used to mint the initial tokens and state for the hard fork const genesisHardFork = new Command() .description("Create state 0 for hard fork") .env("KUPO_URL=", "Kupo URL", { required: true }) @@ -453,7 +469,6 @@ const genesisHardFork = new Command() const { validatorHash: validatorHashv1, - validatorAddress: validatorAddressv1, validator: validatorv1, }: Genesis = JSON .parse( @@ -546,9 +561,7 @@ const genesisHardFork = new Command() .payToContract(validatorAddress, Data.to(new Constr(2, [0n])), { [validatorHash + fromText("lock_state")]: 1n, }) - .complete({ - coinSelection: false, - }); + .complete(); const signed = await registerTx.sign().complete(); @@ -588,29 +601,177 @@ const userLockHardFork = new Command() .env("OGMIOS_URL=", "Ogmios URL", { required: true }) .option("-p, --preview", "Use testnet") .action(async ({ preview, ogmiosUrl, kupoUrl }) => { - // const unAppliedValidator = readValidator(); - // const unAppliedValidatorv2 = readValidatorv2(); - // const genesisFile = Deno.readTextFileSync( - // `genesis/${preview ? "preview" : "mainnet"}.json`, - // ); + const genesisHFFile = Deno.readTextFileSync( + `genesis-hf/${preview ? "preview" : "mainnet"}.json`, + ); - // const { - // validatorHash: validatorHashv1, - // validator: validatorv1, - // }: Genesis = JSON - // .parse( - // genesisFile, - // ); + const { validatorHashv1, validatorHash, validatorAddress, validator }: + GenesisHF = JSON + .parse( + genesisHFFile, + ); - // const provider = new Kupmios(kupoUrl, ogmiosUrl); - // const lucid = await Lucid.new(provider, preview ? "Preview" : "Mainnet"); - // lucid.selectWalletFromSeed(Deno.readTextFileSync("seed.txt")); + const provider = new Kupmios(kupoUrl, ogmiosUrl); + const lucid = await Lucid.new(provider, preview ? "Preview" : "Mainnet"); + lucid.selectWalletFromSeed(Deno.readTextFileSync("seed.txt")); - // const utxos = await lucid.wallet.getUtxos(); + const utxos = await lucid.wallet.getUtxos(); + const script_utxos = await lucid.utxosAt(validatorAddress); - // if (utxos.length === 0) { - // throw new Error("No UTXOs Found"); - // } + if (utxos.length === 0) { + throw new Error("No UTXOs Found"); + } + + const userStateUtxo = script_utxos.find((u) => { + Object.keys(u.assets).find((a) => { + return a == validatorHash + "lock_state"; + }); + })!; + + const hardForkUtxo = script_utxos.find((u) => { + Object.keys(u.assets).find((a) => { + return a == validatorHash + "hfs"; + }); + })!; + + const hasLockNFT = utxos.find((u) => { + Object.keys(u.assets).find((a) => { + return a.slice(0, 56) == validatorHash; + }); + }); + + const validatorScript: Script = { + type: "PlutusV2", + script: validator, + }; + + const validatorRewardAddress = lucid.utils.validatorToRewardAddress( + validatorScript, + ); + + if (!hasLockNFT) { + const utxo = utxos[0]; + + const token_amount = utxos.reduce((acc, u) => { + const token_amount = u.assets[validatorHashv1 + fromText("tuna")]; + return acc + token_amount; + }, 0n); + + const nft_name = lucid.utils.datumToHash(Data.to( + new Constr(0, [ + new Constr(0, [utxo.txHash]), + utxo.outputIndex, + ]), + )); + const datum = userStateUtxo.datum!; + + const userState = (Data.from(datum) as Constr) + .fields[0] as bigint; + + const lockTx = await lucid + .newTx() + .withdraw( + validatorRewardAddress, + 0n, + Data.to( + new Constr(1, [ + new Constr(0, [ + new Constr(0, [hardForkUtxo.txHash]), + hardForkUtxo.outputIndex, + ]), + 0n, + 1n, + new Constr(2, []), + ]), + ), + ) + .mintAssets({ + [validatorHash + nft_name]: 1n, + }, Data.to(0n)) + .readFrom([hardForkUtxo]) + .collectFrom([utxo]) + .collectFrom( + [userStateUtxo], + Data.to( + new Constr(1, [ + 0n, + ]), + ), + ).payToContract( + validatorAddress, + Data.to(new Constr(2, [userState + token_amount])), + { + [validatorHash + "lock_state"]: 1n, + }, + ).payToContract( + validatorAddress, + Data.to(new Constr(3, [nft_name])), + // amount of tuna to lock + { + [validatorHashv1 + fromText("tuna")]: token_amount, + }, + ) + .complete(); + } else { + const utxo = hasLockNFT!; + + const token_amount = utxos.reduce((acc, u) => { + const token_amount = u.assets[validatorHashv1 + fromText("tuna")]; + return acc + token_amount; + }, 0n); + + const nft_name = Object.keys(utxo.assets); + const datum = userStateUtxo.datum!; + + const userState = (Data.from(datum) as Constr) + .fields[0] as bigint; + + // Not done yet + const lockTx = await lucid + .newTx() + .withdraw( + validatorRewardAddress, + 0n, + Data.to( + new Constr(1, [ + new Constr(0, [ + new Constr(0, [hardForkUtxo.txHash]), + hardForkUtxo.outputIndex, + ]), + 0n, + 1n, + new Constr(3, []), + ]), + ), + ) + .mintAssets({ + [validatorHash + nft_name]: 1n, + }, Data.to(0n)) + .readFrom([hardForkUtxo]) + .collectFrom([utxo]) + .collectFrom( + [userStateUtxo], + Data.to( + new Constr(1, [ + 0n, + ]), + ), + ).payToContract( + validatorAddress, + Data.to(new Constr(2, [userState + token_amount])), + { + [validatorHash + "lock_state"]: 1n, + }, + ).payToContract( + validatorAddress, + Data.to(new Constr(3, [nft_name])), + // amount of tuna to lock + { + [validatorHashv1 + fromText("tuna")]: token_amount, + }, + ) + .complete(); + } // const initOutputRef = new Constr(0, [ // new Constr(0, [utxos[0].txHash]),