Skip to content

Conversation

@alexandre-abrioux
Copy link
Contributor

@alexandre-abrioux alexandre-abrioux commented Oct 11, 2022

supersedes #945 and #943

Context

The advanced-logic layer is a stateless singleton that contains an instance of all payment networks (PN). When created (see its class), it has no knowledge of what chain(s) it will be used on. It only needs an instance of the currency manager. It has no other dependency.

Issue / Solution

It is a pain to manually update PN whenever we want them to support a new chain, especially when it could be done automatically via our smart contract artifacts. Without adding new dependencies on the advanced-logic object, this can be done from the payment-detection layer. PN should have zero knowledge of what chain(s) they support. Routing from the chain/version to the payment network should be done during the instantiation of the payment detector.

From this point:

  • isValidAddress in PNs now only accepts an address (no more network parameter), this means:
    • PN supporting EVM chains then support EVM addresses (that was already the case)
    • PN can now only support one type of address, so all Near-related PN had to be split in two: one for Near mainnet and one for Near testnet, the same way we already had one for BTC and one for BTC-testnet
  • PN don't accept a supportedNetworks parameter anymore. Classes that extend native-token and any-to-native still have a supportedNetworks array as they need some kind of deeper level of routing. However, those are supper specific and not supposed to change that often once they are set.
  • everything Near related has been moved to its own directory in advanced-logic, like we did in payment-detection
  • the advanced-logic package typing has been updated (removed any whenever possible)

Ideally, those changes should not impact the behavior of the library when used for payment detection.

Comment on lines -12 to +13
public constructor(
public extensionId: ExtensionTypes.ID = ExtensionTypes.ID.CONTENT_DATA,
public currentVersion: string = CURRENT_VERSION,
) {
super(ExtensionTypes.TYPE.CONTENT_DATA, extensionId, currentVersion);
public constructor() {
super(ExtensionTypes.TYPE.CONTENT_DATA, ExtensionTypes.ID.CONTENT_DATA, CURRENT_VERSION);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Type of change made for classes that never get extended


export default abstract class AnyToNativeTokenPaymentNetwork extends FeeReferenceBasedPaymentNetwork {
public constructor(
protected constructor(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

abstract class constructors should be protected

@alexandre-abrioux alexandre-abrioux force-pushed the pn-check-contract-deployed branch from 818873a to 9e7a533 Compare October 11, 2022 20:41
@alexandre-abrioux alexandre-abrioux changed the base branch from master to fix-ts-json October 11, 2022 20:42
Base automatically changed from fix-ts-json to master October 13, 2022 08:44
@coveralls
Copy link

coveralls commented Oct 13, 2022

Coverage Status

Coverage decreased (-0.1%) to 88.999% when pulling e57154b on pn-check-contract-deployed into 7055d4c on master.

/**
* Handle payment detection for native token payment with conversion
*/
export abstract class AnyToNativeDetector extends AnyToAnyDetector<
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New abstract class for all (future) any-to-native. Did the same for native-token

import Erc20InfoRetriever from './address-based-info-retriever';

import { PaymentDetectorBase } from '../payment-detector-base';
const supportedNetworks = ['mainnet', 'rinkeby', 'goerli', 'private'];
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please challenge this. Here we're in the payment-detection package, so the context is not exactly the same. I don't think it makes sense to have a fixed array of supportedNetworks here either, but I may be wrong.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I agree. If there was such a limitation, it would be in the info-retriever.

Maybe throwing if no (default) provider exists for the network, within getTransferEvents(), would maintain clarity for what works and what does not? And the next step depends on what this provider returns if we query a wider range of blocks than it allows, specifically, if it allows {fromBlock: 0, toBlock: 'latest'}.

As we expect the result to be incomplete in most cases, while getTransferEvents() should be TheGraph-based, shouldn't we add a console.warn for address-based info retrieval?

Copy link
Contributor Author

@alexandre-abrioux alexandre-abrioux Oct 19, 2022

Choose a reason for hiding this comment

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

Good idea! Let me try to do something about that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After further digging, I found out that getDefaultProvider already throws whenever a provider cannot be instantiated for the network, so that was already taken care of! This throws:

return providers.getDefaultProvider(network, providersApiKeys);

As you advised I added a warning every time we use getTransferEvents from an ERC20InfoRetriever, done here: 8675519 👍

}) {
super(
PaymentTypes.PAYMENT_NETWORK_ID.ANY_TO_NATIVE,
advancedLogic.extensions.anyToNativeToken[0],
Copy link
Contributor Author

Choose a reason for hiding this comment

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

No need to specify an index like this anymore. The routing is now done automatically in the constructor of the new parent class AnyToNativeDetector, using the new getAnyToNativeTokenExtensionForNetwork method of the AdvancedLogic class

Copy link
Contributor

Choose a reason for hiding this comment

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

good news

protected readonly extension: TExtension,
protected constructor(
public readonly paymentNetworkId: PaymentTypes.PAYMENT_NETWORK_ID,
public readonly extension: TExtension,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

public because now needed in the factory

Comment on lines 138 to 144
if (detector.extension && 'getDeploymentInformation' in detectorClass) {
// this throws when the contract isn't deployed and was mandatory for payment detection
(detectorClass as ContractBasedDetector).getDeploymentInformation(
network,
detector.extension.currentVersion,
);
}
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 the main change, please review this 😇 We let the detector choose wether we should throw or not for an unsupported network. Do you think that is OK?

Comment on lines -125 to +117
expect(paymentNetworkFactory.getPaymentNetworkFromRequest(request)).toBeInstanceOf(
NearConversionNativeTokenPaymentDetector,
);
expect(
paymentNetworkFactory.getPaymentNetworkFromRequest({
...request,
currency: { ...request.currency, network: 'aurora-testnet' },
}),
).toBeInstanceOf(NearConversionNativeTokenPaymentDetector);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The network was missing, and since we're not mocking advancedLogic in this test file anymore, the test wasn't working

Comment on lines -90 to 80
const paymentDetector = new NearNativeTokenPaymentDetector({
advancedLogic: mockAdvancedLogic,
network: 'aurora',
advancedLogic: advancedLogic,
currencyManager: CurrencyManager.getDefault(),
});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

same as above

Comment on lines +17 to +18
// FIXME: should be Extension.PnReferenceBased.IReferenceBased<Extension.PnStreamReferenceBased.ICreationParameters>
erc777Stream: any;
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 was messing with some files if I remember well, an issue between the interface and the implementation. Will try to fix it in a consecutive PR

getAnyToNativeTokenExtensionForNetwork: (
network: string,
) => Extension.IExtension<Extension.PnAnyToEth.ICreationParameters> | undefined;
extensions: IAdvancedLogicExtensions;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Properly typed the extensions property. This way we can quickly know if our PN interfaces (types) match our PN implementations (classes).

parameters: IAddRefundInstructionParameters,
) => Extension.IAction;
createCreationAction: (parameters?: TCreationParameters) => Extension.IAction;
createCreationAction: (parameters: TCreationParameters) => Extension.IAction;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The interface was not compatible with the actual class implementation. I fixed it that way, let me know if you would have done otherwise.

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.

amazing! great work. Happy to see those supportedNetworks go away 👍

}) {
super(
PaymentTypes.PAYMENT_NETWORK_ID.ANY_TO_NATIVE,
advancedLogic.extensions.anyToNativeToken[0],
Copy link
Contributor

Choose a reason for hiding this comment

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

good news

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.

Really clean, well done.


private isValidMainnetAddress(address: string): boolean {
protected isValidAddress(address: string): boolean {
return this.isValidAddressForSymbolAndNetwork(address, 'NEAR', 'aurora');
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 understand why we get rid of the testnet addresses validation. FYI they have different validation rules compared to mainnet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Near testnet now has its separate class:

return this.isValidAddressForSymbolAndNetwork(address, 'NEAR-testnet', 'aurora-testnet');

import Erc20InfoRetriever from './address-based-info-retriever';

import { PaymentDetectorBase } from '../payment-detector-base';
const supportedNetworks = ['mainnet', 'rinkeby', 'goerli', 'private'];
Copy link
Member

Choose a reason for hiding this comment

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

Yes, I agree. If there was such a limitation, it would be in the info-retriever.

Maybe throwing if no (default) provider exists for the network, within getTransferEvents(), would maintain clarity for what works and what does not? And the next step depends on what this provider returns if we query a wider range of blocks than it allows, specifically, if it allows {fromBlock: 0, toBlock: 'latest'}.

As we expect the result to be incomplete in most cases, while getTransferEvents() should be TheGraph-based, shouldn't we add a console.warn for address-based info retrieval?

Comment on lines +68 to +69
nativeToken: [new NearNative(), new NearTestnetNative()],
anyToNativeToken: [new AnyToNear(currencyManager), new AnyToNearTestnet(currencyManager)],
Copy link
Member

Choose a reason for hiding this comment

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

If we go down that line, can we add anyToEthProxy and feeProxyContractEth to these 2 generic PNs? And deprecate the "separate" use of these extensions? It does not add anything while we just have Near.

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 agree! We should deprecate any-to-eth-proxy and instead use any-to-native-token. Not sure however that eth-fee-proxy-contract and native-token are compatible as the latest doesn't support fees as far as I know. I'll keep this PR a refactor without changing payment networks, but let's keep this in mind for the next steps.

alexandre-abrioux added a commit that referenced this pull request Oct 20, 2022
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.

5 participants