TealScript auction example, how make Jest test for bid

Hi, there!

@joe-p has a TealScript example for auctions here: auction.algo.ts

He defines bid as follows:

  bid(payment: PayTxn): void {
    /// Ensure auction hasn't ended
    assert(globals.latestTimestamp < this.auctionEnd.value);

    /// Verify payment transaction
    verifyPayTxn(payment, {
      sender: this.txn.sender,
      amount: { greaterThan: this.previousBid.value },
    });

    /// Set global state
    this.previousBid.value = payment.amount;
    this.previousBidder.value = payment.sender;

    /// Update claimable amount
    this.claimableAmount(this.txn.sender).value = payment.amount;
  }

My question is, how to make a Jest test for this bid call?

I tried his method, as follows:

/**
   * Buy 1 piece of the asset
   * @param payment Payment in /uAlgos
   */
  buyAsset(payment: PayTxn): void {
    /// Ensure asset selling period hasn't ended yet
    assert(globals.latestTimestamp < this.sellPeriodEnd.value);

    /// Verify payment transaction
    verifyPayTxn(payment, {
      sender: this.txn.sender,
      receiver: globals.creatorAddress,
      amount: { greaterThanEqualTo: this.assetPrice.value, lessThanEqualTo: this.assetPrice.value },
      rekeyTo: globals.zeroAddress,
      closeRemainderTo: globals.zeroAddress,
    });

    /// Verify asset amount
    assert(this.assetAmount.value > 0);

    /// @todo: check asset amount in  buyer account

    /// Send asset to payer
    sendAssetTransfer({
      assetReceiver: this.txn.sender,
      xferAsset: this.asset.value,
      assetAmount: 1,
    });

    // Decrease asset amount
    this.assetAmount.value = this.assetAmount.value - 1;
  }

and tried the following for the Jest test (excerpt):

  test('buyAsset', async () => {
    const { algod, testAccount } = fixture.context;
    const params = await algod.getTransactionParams().do();
    await appClient.appClient.fundAppAccount(algokit.microAlgos(400_000));

    // Opt in to asset
    const globalState = await appClient.getGlobalState();
    const asset = globalState.asset!.asNumber();
    const txn1 = algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({
      from: sender1.addr,
      to: sender1.addr,
      amount: 0,
      assetIndex: asset,
      suggestedParams: params,
    });
    const stxn1 = txn1.signTxn(sender1.sk);
    const txn2 = await algod.sendRawTransaction(stxn1).do();
    await algosdk.waitForConfirmation(algod, txn2.txId, 4);

    // Make a payment tx
    const payment = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
      from: sender1.addr,
      to: testAccount.addr,
      amount: 1_000_000,
      suggestedParams: params,
    });
    // const payment = txn3.signTxn(sender1.sk);
    // Buy asset
    await appClient.buyAsset({ payment });
  });

That is obviously WRONG, the payment isn’t signed. But if I sing it, then I can’t put it into buyAsset as a parameter, I get type error.

OK, compiled TEAL code to the rescure. From the compiled TEAL I see that it waits for a txn grup, and checks whether the last txn in the group is a payment txn:

// buyAsset(pay)void
*abi_route_buyAsset:
	// payment: pay
	txn GroupIndex
	int 1
	-
	dup
	gtxns TypeEnum
	int pay
	==
	assert

	// execute buyAsset(pay)void
	callsub buyAsset
	int 1
	return

So I see that a transaction group is needed, where the first tx is the app call, the second is the payment txn, but I still don’t know how to make it in Jest.

Please help! I need to make a demo for a simple DAO in the very near future.

2 Likes