Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add printed events to the context for assertions #59

Open
moodmosaic opened this issue Dec 11, 2024 · 2 comments
Open

Add printed events to the context for assertions #59

moodmosaic opened this issue Dec 11, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@moodmosaic
Copy link
Member

When calling callPublicFn, we should add any events to the Rendezvous context.

I haven't fully thought about this yet, but I'm opening this to support what @friedger worked on in stacks-network/sbtc#1091.

This also opens the door for adding support for templates (or dealers in the Rendezvous DSL), which I'll track as a separate issue. Using dealers, it would be possible to run rv against a Clarinet project and have it check all its SIP-10 contracts, for example.

@moodmosaic moodmosaic added the enhancement New feature or request label Dec 17, 2024
@moodmosaic
Copy link
Member Author

One way of running this can be via #99.

@moodmosaic
Copy link
Member Author

moodmosaic commented Jan 31, 2025

This also opens the door for adding support for templates (or dealers in the Rendezvous DSL), which I'll track as a separate issue. Using dealers, it would be possible to run rv against a Clarinet project and have it check all its SIP-10 contracts, for example.

It turns out, this should be tackled here, as a pre-requisite. The way I imagine this is that the user runs rv via:

npx rv sbtc/contracts sbtc-token invariant --dial sip-10

dialing in custom behaviors (e.g. assertions as in @friedger's case to check for the printed events) dynamically.


Here's a blueprint. Have a delegate type, e.g.:

type Dialer = (context: any) => Promise<void> | void;

and implement a registry for such delegates, e.g.:

class DialerRegistry {
  private preDialers: Dialer[] = [];
  private postDialers: Dialer[] = [];

  registerPreDialer(dialer: Dialer) {
    this.preDialers.push(dialer);
  }

  registerPostDialer(dialer: Dialer) {
    this.postDialers.push(dialer);
  }

  async executePreDialers(context: any) {
    if (this.preDialers.length === 0) {
      console.log("No pre-dialers registered.");
      return;
    }

    for (const dial of this.preDialers) {
      await dial(context);
    }
  }

  async executePostDialers(context: any) {
    if (this.postDialers.length === 0) {
      console.log("No post-dialers registered.");
      return;
    }

    for (const dial of this.postDialers) {
      await dial(context);
    }
  }
}

export const dialerRegistry = new DialerRegistry();

Then a hypothetical way of registering could be importing the file sip-10.js (in this example) and searching for exported functions starting with pre and post, e.g.:

async function registerDialers() {
  const dialFlagIndex = args.indexOf("--dial");

  if (dialFlagIndex === -1 || dialFlagIndex + 1 >= args.length) {
    return;
  }

  const dialPath = path.resolve(args[dialFlagIndex + 1]);

  if (!fs.existsSync(dialPath)) {
    console.error(`Error: Dialer file not found: ${dialPath}`);
    process.exit(1);
  }

  try {
    console.log(`Dialing in custom behaviors from: ${dialPath}`);
    const userModule = await import(dialPath);

    Object.entries(userModule).forEach(([key, fn]) => {
      if (typeof fn === "function") {
        if (key.startsWith("pre")) {
          dialerRegistry.registerPreDialer(fn as Dialer);
          console.log(`Registered pre-dialer: ${key}`);
        } else if (key.startsWith("post")) {
          dialerRegistry.registerPostDialer(fn as Dialer);
          console.log(`Registered post-dialer: ${key}`);
        }
      }
    });

  } catch (error) {
    console.error(`Failed to load dialers:`, error);
    process.exit(1);
  }
}

Then call into the registry before/after a call is sent to the target contract.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant