diff --git a/CHANGELOG.md b/CHANGELOG.md index 06cb651..e66a4b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ +June 14, 2023 + +v1.0: a toolbox for test-driven development + June 1, 2023 https://adambard.com/blog/on-library-versioning/ -v1.0: helios vesting testing template +v0.0: helios vesting testing template diff --git a/src/matching-keyhash.js b/src/matching-keyhash.js deleted file mode 100644 index ce9117b..0000000 --- a/src/matching-keyhash.js +++ /dev/null @@ -1,11 +0,0 @@ -spending matching_pubKeyHash - - struct Datum { - owner: PubKeyHash - } - - struct Redeemer { - owner: PubKeyHash - } - - func main(datum : Datum, redeemer: Redeemer) -> Bool {datum.owner == redeemer.owner} diff --git a/src/vesting-lock.ts b/src/vesting-lock.ts index cc295cd..7780fea 100644 --- a/src/vesting-lock.ts +++ b/src/vesting-lock.ts @@ -49,9 +49,6 @@ export const lockAda = async ( const inputUtxos = await alice.utxos; - const tx = new Tx(); - - tx.addInputs([inputUtxos[0]]); const mintScript =`minting nft @@ -83,8 +80,6 @@ export const lockAda = async ( const mintProgram = Program.new(mintScript).compile(optimize); - tx.attachScript(mintProgram); - // Construct the NFT that we will want to send as an output const nftTokenName = ByteArrayData.fromString("Vesting Key").toHex(); const tokens: [number[], bigint][] = [[hexToBytes(nftTokenName), BigInt(1)]]; @@ -93,17 +88,19 @@ export const lockAda = async ( // a plutus script transaction even if we don't actually use it. const mintRedeemer = new ConstrData(0, []); - // Indicate the minting we want to include as part of this transaction - tx.mintTokens( - mintProgram.mintingPolicyHash, - tokens, - mintRedeemer - ) - const lockedVal = new Value(adaAmountVal.lovelace, new Assets([[mintProgram.mintingPolicyHash, tokens]])); - - // Add the destination address and the amount of Ada to lock including a datum - tx.addOutput(new TxOutput(validatorAddress, lockedVal, inlineDatum)); + + const tx = new Tx() + .addInputs([inputUtxos[0]]) + .attachScript(mintProgram) + // Indicate the minting we want to include as part of this transaction + .mintTokens( + mintProgram.mintingPolicyHash, + tokens, + mintRedeemer + ) + // Add the destination address and the amount of Ada to lock including a datum + .addOutput(new TxOutput(validatorAddress, lockedVal, inlineDatum)); await tx.finalize(networkParams, alice.address); diff --git a/src/vesting.js b/src/vesting.hl similarity index 100% rename from src/vesting.js rename to src/vesting.hl diff --git a/tests/template.test.ts b/tests/template.test.ts index 8912ee6..958fba3 100644 --- a/tests/template.test.ts +++ b/tests/template.test.ts @@ -25,7 +25,7 @@ describe("a template", async () => { let optimize = false; // compile script - const script = await fs.readFile('./src/vesting.js', 'utf8'); + const script = await fs.readFile('./src/vesting.hl', 'utf8'); const compiledProgram = Program.new(script).compile(optimize); const validatorHash = compiledProgram.validatorHash; const validatorAddress = Address.fromValidatorHash(validatorHash); diff --git a/tests/unit/program.test.ts b/tests/unit/program.test.ts index 7bac44f..a5bc62c 100644 --- a/tests/unit/program.test.ts +++ b/tests/unit/program.test.ts @@ -11,7 +11,7 @@ describe("a uplc instance is created from source code", async () => { beforeEach(async (context) => { let optimize = false; - const script = await fs.readFile('./src/vesting.js', 'utf8'); + const script = await fs.readFile('./src/vesting.hl', 'utf8'); const program = Program.new(script); const compiledProgram = program.compile(optimize); const validatorHash = compiledProgram.validatorHash; diff --git a/tests/vesting-cancel.test.ts b/tests/vesting-cancel.test.ts index 3217729..39be606 100644 --- a/tests/vesting-cancel.test.ts +++ b/tests/vesting-cancel.test.ts @@ -26,7 +26,7 @@ describe("a vesting contract: Cancel transaction", async () => { let optimize = false; // compile script - const script = await fs.readFile('./src/vesting.js', 'utf8'); + const script = await fs.readFile('./src/vesting.hl', 'utf8'); const program = Program.new(script); const compiledProgram = program.compile(optimize); const validatorHash = compiledProgram.validatorHash; @@ -51,8 +51,7 @@ describe("a vesting contract: Cancel transaction", async () => { context.network = network; }) - it ("docs the tx ingridients", async ({network, alice, validatorHash}) => { - // network.getUtxos(alice.address) + it ("documents the initial network state", async ({network, alice, validatorHash}) => { // EmulatorWallet const aliceUtxos = await alice.utxos; // https://www.hyperion-bt.org/helios-book/api/reference/address.html?highlight=Address#address @@ -64,7 +63,32 @@ describe("a vesting contract: Cancel transaction", async () => { }) - it ("locks funds and tries to unlock as the owner", async ({network, alice, bob, program}) => { + it ("tests cancelVesting.ts", async ({network, alice, bob, program}) => { + const optimize = false; // need to add it to the context + const compiledScript = program.compile(optimize); + const validatorHash = compiledScript.validatorHash; + const validatorAddress = Address.fromValidatorHash(validatorHash); + + expect((await alice.utxos)[0].value.dump().lovelace).toBe('20000000'); + expect((await alice.utxos)[1].value.dump().lovelace).toBe('50000000'); + + const adaQty = 10; + const duration = 1000000; + await lockAda(network!, alice!, bob!, program, adaQty, duration); + expect((await alice.utxos)[0].value.dump().lovelace).toBe('50000000'); + expect((await alice.utxos)[1].value.dump().lovelace).toBe('9755287'); + + await cancelVesting(network!, alice!, program ); + + const oracle = await alice.utxos; + + // think about which is which. + expect(oracle[2].value.dump().lovelace).toBe('9546007'); + expect(oracle[1].value.dump().lovelace).toBe('10000000');// + expect(oracle[0].value.dump().lovelace).toBe('50000000');// collateral? + }) + + it ("documents cancelVesting", async ({network, alice, bob, program}) => { // Obtain UPLC: // need to add it to the context // Compile the Helios script @@ -131,30 +155,6 @@ describe("a vesting contract: Cancel transaction", async () => { const oracle = await alice.utxos; - // think about which is which. - expect(oracle[2].value.dump().lovelace).toBe('9546007'); - expect(oracle[1].value.dump().lovelace).toBe('10000000');// - expect(oracle[0].value.dump().lovelace).toBe('50000000');// collateral? - }) - it ("tests cancelVesting.ts", async ({network, alice, bob, program}) => { - const optimize = false; // need to add it to the context - const compiledScript = program.compile(optimize); - const validatorHash = compiledScript.validatorHash; - const validatorAddress = Address.fromValidatorHash(validatorHash); - - expect((await alice.utxos)[0].value.dump().lovelace).toBe('20000000'); - expect((await alice.utxos)[1].value.dump().lovelace).toBe('50000000'); - - const adaQty = 10; - const duration = 1000000; - await lockAda(network!, alice!, bob!, program, adaQty, duration); - expect((await alice.utxos)[0].value.dump().lovelace).toBe('50000000'); - expect((await alice.utxos)[1].value.dump().lovelace).toBe('9755287'); - - await cancelVesting(network!, alice!, program ); - - const oracle = await alice.utxos; - // think about which is which. expect(oracle[2].value.dump().lovelace).toBe('9546007'); expect(oracle[1].value.dump().lovelace).toBe('10000000');// diff --git a/tests/vesting-lock.test.ts b/tests/vesting-lock.test.ts index 2003143..ca55833 100644 --- a/tests/vesting-lock.test.ts +++ b/tests/vesting-lock.test.ts @@ -26,7 +26,7 @@ describe("a vesting contract lockAda transaction", async () => { let optimize = false; // compile script - const script = await fs.readFile('./src/vesting.js', 'utf8'); + const script = await fs.readFile('./src/vesting.hl', 'utf8'); const program = Program.new(script); const compiledProgram = program.compile(optimize); const validatorHash = compiledProgram.validatorHash; @@ -51,25 +51,39 @@ describe("a vesting contract lockAda transaction", async () => { context.network = network; }) - it ("checks that a correct script is loaded", async ({programName}) => { - // https://www.hyperion-bt.org/helios-book/api/reference/program.html - expect(programName).toBe('vesting') - }) - it ("tests NetworkEmulator state", async ({network, alice}) => { + it ("tests initial NetworkEmulator state", async ({network, alice}) => { // https://www.hyperion-bt.org/helios-book/api/reference/address.html?highlight=Address#address const aliceUtxos = await network.getUtxos(alice.address); - - expect(alice.address.toHex().length).toBe(58) + expect(alice.address.toHex().length).toBe(58) //property? expect(aliceUtxos[1].value.dump().lovelace).toBe('5000000') + expect(aliceUtxos[0].value.dump().lovelace).toBe('20000000') }) - it ("tests lockAda tx", async ({network, alice, bob, validatorAddress}) => { + it ("tests lockAda tx", async ({network, alice, bob,validatorHash, program}) => { + const adaQty = 10 ; + const duration = 10000000; + await lockAda(network!, alice!, bob!, program, adaQty, duration) + + // one utxo is unchanged, second has (10 ADA + txFee) less + expect((await alice.utxos)[0].value.dump().lovelace).toBe('5000000'); + expect((await network.getUtxos(await alice.address))[0].value.dump().lovelace).toBe('5000000'); + expect((await alice.utxos)[1].value.dump().lovelace).toBe('9755287'); + + const validatorAddress = Address.fromValidatorHash(validatorHash); + // there exists a utxo that has a specified token locked at a validatorAddress. + expect(Object.keys((await network.getUtxos(validatorAddress))[0].value.dump().assets)[0]).toBe('702cd6229f16532ca9735f65037092d099b0ff78a741c82db0847bbf'); + }) + it ("reproduces lockAda tx", async ({network, alice, bob, validatorAddress}) => { // https://github.com/lley154/helios-examples/blob/704cf0a92cfe252b63ffb9fd36c92ffafc1d91f6/vesting/pages/index.tsx#LL157C1-L280C4 const benAddr = bob.address; const adaQty = 10 ; const duration = 10000000; - const emulatorDate = 1677108984000; + const networkParamsFile = await fs.readFile('./src/preprod.json', 'utf8'); + const networkParams = new NetworkParams(JSON.parse(networkParamsFile.toString())); + + const emulatorDate = Number(networkParams.slotToTime(BigInt(0))); const deadline = new Date(emulatorDate + duration); + const benPkh = bob.pubKeyHash; const ownerPkh = alice.pubKeyHash; @@ -83,9 +97,6 @@ describe("a vesting contract lockAda transaction", async () => { const inputUtxos = await alice.utxos; - const tx = new Tx(); - - tx.addInputs(inputUtxos); const mintScript =`minting nft @@ -118,8 +129,6 @@ describe("a vesting contract lockAda transaction", async () => { const optimize = false; //maybe add to test context? const mintProgram = Program.new(mintScript).compile(optimize); - tx.attachScript(mintProgram); - // Construct the NFT that we will want to send as an output const nftTokenName = ByteArrayData.fromString("Vesting Key").toHex(); const tokens: [number[], bigint][] = [[hexToBytes(nftTokenName), BigInt(1)]]; @@ -128,44 +137,37 @@ describe("a vesting contract lockAda transaction", async () => { // a plutus script transaction even if we don't actually use it. const mintRedeemer = new ConstrData(0, []); - // Indicate the minting we want to include as part of this transaction - tx.mintTokens( - mintProgram.mintingPolicyHash, - tokens, - mintRedeemer - ) - const lockedVal = new Value(adaAmountVal.lovelace, new Assets([[mintProgram.mintingPolicyHash, tokens]])); - - // Add the destination address and the amount of Ada to lock including a datum - tx.addOutput(new TxOutput(validatorAddress, lockedVal, inlineDatum)); - // beforeAll? - const networkParamsFile = await fs.readFile('./src/preprod.json', 'utf8'); - const networkParams = new NetworkParams(JSON.parse(networkParamsFile.toString())); + const tx = new Tx() + .attachScript(mintProgram) + .addInputs(inputUtxos) + // Indicate the minting we want to include as part of this transaction + .mintTokens( + mintProgram.mintingPolicyHash, + tokens, + mintRedeemer + ) + + // Add the destination address and the amount of Ada to lock including a datum + .addOutput(new TxOutput(validatorAddress, lockedVal, inlineDatum)); + await tx.finalize(networkParams, alice.address); const txId = await network.submitTx(tx); network.tick(BigInt(10)); - //alice utxos changed + // this should be consistent with previous test. + // alice has only one utxo: expect((await alice.utxos)[0].value.dump().lovelace).toBe('14749259'); - expect(mintProgram.mintingPolicyHash.hex).toBe('702cd6229f16532ca9735f65037092d099b0ff78a741c82db0847bbf'); - + // and the fee is different, compare L67 + expect(14749259).not.to.equal(9755287+5000000); + expect((await alice.utxos)[1]).toBeUndefined(); // validator address holds Vesting Key + expect(mintProgram.mintingPolicyHash.hex).toBe('702cd6229f16532ca9735f65037092d099b0ff78a741c82db0847bbf'); expect(Object.keys((await network.getUtxos(validatorAddress))[0].value.dump().assets)[0]).toEqual(mintProgram.mintingPolicyHash.hex); }) - it ("tests lockAda tx import", async ({network, alice, bob,validatorHash, program}) => { - const adaQty = 10 ; - const duration = 10000000; - await lockAda(network!, alice!, bob!, program, adaQty, duration) - - const validatorAddress = Address.fromValidatorHash(validatorHash); - expect((await alice.utxos)[0].value.dump().lovelace).toBe('5000000'); - expect((await alice.utxos)[1].value.dump().lovelace).toBe('9755287'); - expect(Object.keys((await network.getUtxos(validatorAddress))[0].value.dump().assets)[0]).toBe('702cd6229f16532ca9735f65037092d099b0ff78a741c82db0847bbf'); - }) })