Skip to content

Conversation

@ncomerci
Copy link
Member

@ncomerci ncomerci commented Feb 6, 2025

The purpose of this PR is to implement support and correct handling of parameters for queries. To ensure that the library side functions are correctly typed, both the parameters and their response value, a serialization and deserialization was implemented internally with a JSON library for assemblyscript in order to make the communication with the relayer as simple as possible.

These changes led to change the way inputs.json is generated by reading the .wat file instead of the .ts file.

Still missing:

  • Adding parameter support to the interfaces that are generated based on ABIs (will be done in a future PR in order not to extend this one)

@ncomerci ncomerci added the WIP Work in Progress label Feb 6, 2025
@ncomerci ncomerci self-assigned this Feb 6, 2025
@ncomerci ncomerci changed the base branch from main to lib/intent-related-calls February 12, 2025 19:26
@ncomerci ncomerci requested a review from PedroAraoz February 12, 2025 20:29
@ncomerci ncomerci removed the WIP Work in Progress label Feb 12, 2025
Copy link
Member

@facuspagnuolo facuspagnuolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general I don't get the purpose of this PR tbh

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of this class?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this is code that I forgot to remove because I was testing. The idea was to separate price-related queries from environment-related queries by classifying them by scope.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get why we have this mapping here between the class and the namespace, what's the reason behind it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pr goes together with this PR and is to serialize and deserialize the function parameters. The mapping is for the task to be written using the lib tools and then serialized so that the relayer can read it.

Copy link
Member Author

@ncomerci ncomerci Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are thinking with Pedro about a way to make this process more efficient and not having to do it parameter by parameter as it is now.

(Edit) Update: We found a way to use JSON serialization/deserialization for params that improves dev experience

})
})

return sortedResult
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have we dropped the AST logic to produce the inputs file in favor of manual parsing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the task.ts file to generate the inputs.json I found that is necessary to specify in the compile command what it has to look for to generate the inputs. For example: let's suppose that there are 2 contracts defined in the manifest that are used in the task, then the compile, besides looking for the environment functions that were used, it has to identify each contract and for each one, its functions.

On the other hand, if we use the .wat file instead of the task.ts, it is very clear which are the external functions necessary to generate the inputs.json (all of them are identified with an “import” at the beginning of the line). That is why no matter how many external functions are used in the task, the compile does not need to have context and can generate the inputs.json very easily.

Base automatically changed from lib/intent-related-calls to main February 18, 2025 20:51
@ncomerci ncomerci force-pushed the relayer/parameterized-queries-digest branch from ed509ca to 4f7a89a Compare February 18, 2025 21:05
@PedroAraoz
Copy link
Member

There is a bug with the new generation. I would add some more tests to catch cases like these
If I have the following task

export default function main(): void {
  const usdcAddress = Address.fromString("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
  const USDC = ERC20.load(usdcAddress, 1)
  const name = USDC.name()
  const number = USDC.balanceOf(usdcAddress)
  Environment.call(usdcAddress, 1, usdcAddress, usdcAddress, number, Bytes.fromHexString(name))
}

The inputs.json that generates is the following

{
"ERC20": {
  "ERC20": [
    "load"
  ]
},
"index": {
  "environment": [
    "call"
  ]
}
}

@ncomerci
Copy link
Member Author

ncomerci commented Feb 19, 2025

There is a bug with the new generation. I would add some more tests to catch cases like these If I have the following task

export default function main(): void {
  const usdcAddress = Address.fromString("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
  const USDC = ERC20.load(usdcAddress, 1)
  const name = USDC.name()
  const number = USDC.balanceOf(usdcAddress)
  Environment.call(usdcAddress, 1, usdcAddress, usdcAddress, number, Bytes.fromHexString(name))
}

The inputs.json that generates is the following

{
"ERC20": {
  "ERC20": [
    "load"
  ]
},
"index": {
  "environment": [
    "call"
  ]
}
}

Hey @PedroAraoz Thank you! I fixed the inputs.json generation to fix this. However, the way the interface is generated will change in the next PR as it doesn't have the correct parameter handling implemented for now.

Edit: Check #20

@ncomerci ncomerci changed the title relayer: Parameterized queries digest Relayer: Add query parameter support Feb 19, 2025
Comment on lines 21 to 22
Environment.call(settler, chainId, target, feeToken, fee1, data)
Environment.call(settler, chainId, target, feeToken, fee2, data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double checking on this, I don't like the idea of calling classes, it's conceptually wrong, this should be an instance of the environment or sth similar to that, that's why this was a namespace initially. Why we are changing this? Is there any other alternative?

Copy link
Member Author

@ncomerci ncomerci Feb 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Facu! Thanks for the comment. I did a double check on this and, as long as we don't have to handle an internal enviroment state (which is not currently the case), something like this can be done which aligns with what you propose:

image

Only the functions that are exported are accessible to the user, the others are for internal use.

There were no strong reasons to use a class other than to maintain consistency with the contracts interface which at the moment, having an internal state (address and chain ID), I could not find any other way to implement it other than a class.

Let me know if you agree with this to include it in the PR!

@facuspagnuolo facuspagnuolo merged commit 8b43c4d into main Feb 25, 2025
9 checks passed
@facuspagnuolo facuspagnuolo deleted the relayer/parameterized-queries-digest branch February 25, 2025 13:33
Comment on lines +9 to +13
type FunctionsMap = {
[namespace: string]: {
[subNamespace: string]: string[]
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, this does not follow our convention to declare types


const result: FunctionsMap = {}

const importRegex = /\(import\s+"([^"]+)"\s+"([^"]+)"\s+\(func\s+\$[^\s)]+/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, this does not follow our convention to declare constants

sortedInputs[ns][subNs] = inputs[ns][subNs].sort()
})
})
return sortedInputs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, I would love to double-check this is actually better than using the AST

feeAmount: BigInt,
data: Bytes | null = null
): void {
_call(JSON.stringify<CallParams>(new CallParams(settler, chainId, target, feeToken, feeAmount, data)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, let's analyze the alternative of serializing a list of primitive types instead a single string param (JSON). Not sure if this will be simpler, but it might help to avoid declaring classes for every param structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants