Is there a way to delegate contract to call its own function by condition trigger?

I have a following use case:

  1. The user Jack mint a ERC721 token
  2. The user Jack approve ERC721 token to be used by marketplace contract
  3. The user Jake and user Alice independently & asynchronous call approveExchange() function of marketplace contract
  4. Marketplace contract performs exchange of token.

The issue I faced with during test case is:
Step 4 should be called after step 3 performed by each party. I could add check condition at step 3 and call step 4 in positive case, however the msg.sender in this case would be Jack or Alice, but token might be transferred only by owner or address which has been approved (in real scenario there are multiple token are exchanged at once).

To overcome this I could implement pooling the chain for exchange which are approved by both users, but is there a better way to do this? Is there a way to delegate contract to call its own function by condition?

Thanks!

:1234: Code to reproduce

        it("On approveSwap() call in positive scenario SwapChain transfers tokens and makes them consumed", async function() {
            // TODO complete me 
            const { contract, contractValue } = await loadFixture(deploy);
            await prepareApproveSwapConditions();
            const accounts = await ethers.getSigners();
            const owner = accounts[0];
            const anotherUser = accounts[1];
            const notRegisteredUser = accounts[2];
            const match = {
                _userFirst: owner.address,
                _valueOfFirstUser: 0,
                _userSecond: anotherUser.address,
                _valueOfSecondUser: 1,
                _approvedByFirstUser: false,
                _approvedBySecondUser: false
            }
            await contract.connect(owner).approveMatch(match);
            await contract.connect(owner).approveMatch(match);
            // TODO complete me
            // TODO how to delegate contract address to call approveSwap() ?
  }
}

:computer: Environment

VS Code, hardhat

I couldn't understand the question. Feel free to elaborate and try to explain it in other terms.

I have figured out each function call is called from the contract would have this contract address despite on one or another user. In other terms even originally msg.sender is Alice or Jack in the next call msg.sender would be the Contract.

It solves the first part of issue.

The second part of issue might be solved by triggering event when both parties confirms exchange. The client or server by schedule query this events and executes exchange. At this moment it looks as the best option to solve this.