Skip to content

Conversation

@alexandre-abrioux
Copy link
Contributor

@alexandre-abrioux alexandre-abrioux commented Feb 3, 2023

Description of the changes

This PR adds chain configuration files. Those configs allow us to easily convert Request Network's internal chain names (mainnet, aurora, etc...) to standard chain IDs.

This PR also strengthens the types of chain names across our packages. Chain names used to be simple strings. They are now strong types, and it is easier to know which part of the protocol is compatible with EVM chains, and, which part is compatible with a broader definition of chains.

How to review

I'd suggest checking first those new files before anything else:

  • packages/types/src/currency-types.ts
  • packages/currency/src/chains/evm/index.ts
  • packages/currency/src/chains/btc/index.ts
  • packages/currency/src/chains/index.ts

The rest is mostly changes of types.

Possible Improvements (next steps)

We could strongly type storage chains = have a different type for storage chains instead of using CurrencyType.EvmChainName.

* @param networkId Id of the network
* @return name of the network
*/
export default {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed the default export here (cc @MantisClone) and exported these utilities in the index file of the package. It allows other packages to filter storage chains amongst all supported EVM chains.

Comment on lines +27 to +30
const network = getEthereumStorageNetworkNameFromId(config.getStorageNetworkId());
if (!network) {
throw new Error(`Storage network not supported: ${config.getStorageNetworkId()}`);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is how the newly exported ethereum-storage utility becomes convenient.


/** Parameters for the creation action */
export interface ICreationParameters extends PnAnyToAnyConversion.ICreationParameters {
network?: EvmChainName;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

precise network type for pn-any-to-erc20

Copy link
Member

Choose a reason for hiding this comment

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

I'd like to know if @leoslr thinks this is compatible with the approach of calling all fungible tokens ERC20, even on non-EVMs.

Copy link
Contributor

Choose a reason for hiding this comment

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

It won't be compatible no.
Currently the tests are pasing as aurora and aurora-testnet are declared as EvmChainName.

I think we should keep the ChainName from the underlying interface. Calling all fungible token ERC20 is a langage abuse, but in the context of creating requests and detecting the payment, the logic remains the same.

@coveralls
Copy link

coveralls commented Feb 3, 2023

Coverage Status

Coverage: 87.834% (-0.4%) from 88.246% when pulling 0b99099 on networks into 0c651b9 on master.

@alexandre-abrioux alexandre-abrioux marked this pull request as ready for review February 3, 2023 19:08
Copy link
Contributor

@benjlevesque benjlevesque left a comment

Choose a reason for hiding this comment

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

great job on the chain configuration 👏

I'm not totally convinced by the EvmChainName though... Imo, we could consider chains as a purely configurable: in the future, chain configuration could even include smart contract addresses, and could be injected to the client. That would make typing the chain name irrelevant, and even wrong.

I think you cover the problem very well with the assertChainSupported util, and it's probably enough.

@alexandre-abrioux
Copy link
Contributor Author

alexandre-abrioux commented Feb 6, 2023

(saw on a call with @benjlevesque)

Use case 1

EvmChainName / BtcChainName are nice to have with our current "static" configuration as they prevent typos in chain names in:

This use case will be voided once we implement a proper way of dynamically configuring chains. Like @benjlevesque said:

in the future, chain configuration could even include smart contract addresses and could be injected to the client

At this point, we should implement all safeguards at run time (when the library is first loaded, for instance), which would replace those compile-time safeguards.

Use case 2

EvmChainName / BtcChainName can shield features that should only be used on EVM or BTC chains against using them on other chains. Example: ERC20 payment extensions should only be used on EVM chains.

This is also a nice to have, but having a union type is not future-proof (it's not compatible with a dynamic configuration). What we could do is implement proper classes to represent chains in our codebase, instead of representing them as strings. That way:

  • type EvmChainName would become interface EvmChain
  • type BtcChainName would become interface BtcChain

The feature-shielding could be preserved. The assertion of compatibility would be made when first creating the chain class, something like:

class EvmChain implements  {
  contructor (public name) {
    // here we would check that the chain is supported from the dynamic chain configuration
    assertChainSupported(name);
  }
}

Conclusion

Overall, those types were hard to add but will be very easy to replace by interfaces or by simple string aliases once we move forward with dynamic configurations. We could merge this as a first step and iterate on it.

Please let me know if you have other concerns or suggestions!

Misc

A suggestion was to use the newly added satisfies keyword instead of manually creating a union type (see. #1057).

Unfortunately, this is not easily doable: chain configurations are declared in @requestnetwork/currency, but @requestnetwork/types also need those types. Doing it would create a circular dependency between @requestnetwork/types and @requestnetwork/currency.

Copy link
Member

@yomarion yomarion left a comment

Choose a reason for hiding this comment

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

(reviewed advanced-logic, currency, types, toolbox and smart-contracts for now)

import { NamedNativeCurrency } from './types';

export const nativeCurrencies: Record<NativeCurrencyType, (NativeCurrency & { name: string })[]> = {
type NativeEthCurrency = NamedNativeCurrency & { network: CurrencyTypes.EvmChainName };
Copy link
Member

Choose a reason for hiding this comment

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

1/ Generic question: why having a different type per blockchain type?

2/
Watch out:

    {
      symbol: 'NEAR',
      decimals: 24,
      name: 'Near',
      network: 'aurora',
    },

Was defined within RequestLogicTypes.CURRENCY.ETH, as it seemed complex to define one Currency type per chain. These new types can enforce the confusion, maybe it's easier to make the difference at this stage with NativeNearCurrency (but cf. 1/).

Option 1/n: NativeAMCurrency, AM standing for AccountModel, opposed to UTXO (https://www.horizen.io/blockchain-academy/technology/expert/utxo-vs-account-model/#:~:text=The%20UTXO%20model%20is%20a,constructions%2C%20as%20well%20a%20sharding.)
Option 2/n: NativeVMCurrency: Common type for VM chains native tokens
...

3/ Consider usign Evm instead of Eth

Copy link
Contributor Author

@alexandre-abrioux alexandre-abrioux Feb 7, 2023

Choose a reason for hiding this comment

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

I fixed it in d6ae451 with the following bit of code:

type NativeEthCurrency = NamedNativeCurrency & {
  network: CurrencyTypes.EvmChainName | CurrencyTypes.NearChainName;
};

why having a different type per blockchain type

The goal was to have a different type per "currency type".

IMO, if we can specify the type, let's do it; it brings clarity to the model. The change already revealed small flaws in the current design (which are OK flaws):

  • flaw 1: because chain names are not unique across different "chain types", a collision is possible for "currency types" that span across multiple "chain types", like RequestLogicTypes.CURRENCY.ETH that spans across EVM-type and NEAR-type chains
  • flaw 2: the "currency type" RequestLogicTypes.CURRENCY.ETH's name is a bit confusing

I think that's great: it made it more obvious. I didn't want to change any logic in this PR, so I haven't refactored anything related to currencies. Let's keep it in mind tho! I didn't know about "UTXO vs. Account Model", thanks!

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.

7 participants