Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
WIP
  • Loading branch information
alexandre-abrioux committed Feb 15, 2024
commit 7cc2bcb918d43e40a7f38b07775f6da2bdc32e2f
86 changes: 66 additions & 20 deletions packages/advanced-logic/src/advanced-logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,34 @@ import NativeToken from './extensions/payment-network/native-token';
import AnyToNative from './extensions/payment-network/any-to-native';
import Erc20TransferableReceivablePaymentNetwork from './extensions/payment-network/erc20/transferable-receivable';

const { ECOSYSTEM, VM_ECOSYSTEMS } = ChainTypes;

/**
* Module to manage Advanced logic extensions
* Package to route the format and parsing of extensions following their id
*/
export default class AdvancedLogic implements AdvancedLogicTypes.IAdvancedLogic {
public static supportedEcosystemsForExtension: Record<
ExtensionTypes.ID,
readonly ChainTypes.ECOSYSTEM[]
> = {
[ExtensionTypes.ID.CONTENT_DATA]: [ECOSYSTEM.EVM],
Copy link
Contributor

Choose a reason for hiding this comment

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

strange... CONTENT_DATA isn't a payment network...

[ExtensionTypes.PAYMENT_NETWORK_ID.BITCOIN_ADDRESS_BASED]: [ECOSYSTEM.BTC],
[ExtensionTypes.PAYMENT_NETWORK_ID.TESTNET_BITCOIN_ADDRESS_BASED]: [ECOSYSTEM.BTC],
[ExtensionTypes.PAYMENT_NETWORK_ID.ANY_DECLARATIVE]: [ECOSYSTEM.BTC],
[ExtensionTypes.PAYMENT_NETWORK_ID.ERC20_ADDRESS_BASED]: VM_ECOSYSTEMS,
[ExtensionTypes.PAYMENT_NETWORK_ID.ERC20_PROXY_CONTRACT]: VM_ECOSYSTEMS,
[ExtensionTypes.PAYMENT_NETWORK_ID.ERC20_FEE_PROXY_CONTRACT]: VM_ECOSYSTEMS,
[ExtensionTypes.PAYMENT_NETWORK_ID.ERC777_STREAM]: [ECOSYSTEM.EVM],
[ExtensionTypes.PAYMENT_NETWORK_ID.ETH_INPUT_DATA]: [ECOSYSTEM.EVM],
[ExtensionTypes.PAYMENT_NETWORK_ID.NATIVE_TOKEN]: [ECOSYSTEM.NEAR],
[ExtensionTypes.PAYMENT_NETWORK_ID.ANY_TO_ERC20_PROXY]: VM_ECOSYSTEMS,
[ExtensionTypes.PAYMENT_NETWORK_ID.ETH_FEE_PROXY_CONTRACT]: [ECOSYSTEM.EVM],
[ExtensionTypes.PAYMENT_NETWORK_ID.ANY_TO_ETH_PROXY]: [ECOSYSTEM.EVM],
[ExtensionTypes.PAYMENT_NETWORK_ID.ANY_TO_NATIVE_TOKEN]: [ECOSYSTEM.NEAR],
[ExtensionTypes.PAYMENT_NETWORK_ID.ERC20_TRANSFERABLE_RECEIVABLE]: [ECOSYSTEM.EVM],
};

/** Give access to the functions specific of the extensions supported */
public extensions: {
addressBasedBtc: AddressBasedBtc;
Expand Down Expand Up @@ -108,8 +131,23 @@ export default class AdvancedLogic implements AdvancedLogicTypes.IAdvancedLogic
requestState: RequestLogicTypes.IRequest,
): ExtensionTypes.IExtension {
const id: ExtensionTypes.ID = extensionAction.id;
const chain = this.getChain(extensionAction, requestState);
const extension: ExtensionTypes.IExtension | undefined = {
const ecosystems = AdvancedLogic.supportedEcosystemsForExtension[id];
if (!ecosystems) {
throw Error(`chain ecosystem not recognized for extension: ${id}`);
}
const chain = this.getChainForActionAndState(extensionAction, requestState, ecosystems);
const extensions = this.getExtensionsForChain(chain);
const extension = extensions[id];
if (!extension) {
throw Error(`extension with id: ${id} not found for network: ${chain}`);
}
return extension;
}

public getExtensionsForChain(
Copy link
Contributor

Choose a reason for hiding this comment

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

any reason this was made public?

chain?: ChainTypes.IChain,
): Record<ExtensionTypes.ID, ExtensionTypes.IExtension | undefined> {
const extensions: Record<ExtensionTypes.ID, ExtensionTypes.IExtension | undefined> = {
[ExtensionTypes.ID.CONTENT_DATA]: this.extensions.contentData,
[ExtensionTypes.PAYMENT_NETWORK_ID.BITCOIN_ADDRESS_BASED]: this.extensions.addressBasedBtc,
[ExtensionTypes.PAYMENT_NETWORK_ID.TESTNET_BITCOIN_ADDRESS_BASED]:
Expand All @@ -131,19 +169,19 @@ export default class AdvancedLogic implements AdvancedLogicTypes.IAdvancedLogic
this.getAnyToNativeTokenExtensionForNetwork(chain),
[ExtensionTypes.PAYMENT_NETWORK_ID.ERC20_TRANSFERABLE_RECEIVABLE]:
this.extensions.erc20TransferableReceivable,
}[id];

if (!extension) {
if (
id === ExtensionTypes.PAYMENT_NETWORK_ID.NATIVE_TOKEN ||
id === ExtensionTypes.PAYMENT_NETWORK_ID.ANY_TO_NATIVE_TOKEN
) {
throw Error(`extension with id: ${id} not found for network: ${chain}`);
}

throw Error(`extension not recognized, id: ${id}`);
}
return extension;
};
// filter-out unsupported extensions for this chain ecosystem
return (Object.keys(extensions) as ExtensionTypes.ID[]).reduce(
(filteredExtensions, extensionId) => {
filteredExtensions[extensionId] =
chain &&
AdvancedLogic.supportedEcosystemsForExtension[extensionId].includes(chain.ecosystem)
? extensions[extensionId]
: undefined;
return filteredExtensions;
},
{} as Record<ExtensionTypes.ID, ExtensionTypes.IExtension | undefined>,
);
}

public getNativeTokenExtensionForNetwork(
Expand All @@ -167,23 +205,30 @@ export default class AdvancedLogic implements AdvancedLogicTypes.IAdvancedLogic
}

public getFeeProxyContractErc20ForNetwork(network?: ChainTypes.IChain): FeeProxyContractErc20 {
return this.currencyManager.chainManager.ecosystems.near.isChainSupported(network)
return this.currencyManager.chainManager.ecosystems[ECOSYSTEM.NEAR].isChainSupported(network)
? new FeeProxyContractErc20(this.currencyManager, undefined, undefined, network)
: this.extensions.feeProxyContractErc20;
}

private getChain(
private getChainForActionAndState(
extensionAction: ExtensionTypes.IAction,
requestState: RequestLogicTypes.IRequest,
ecosystems: readonly ChainTypes.ECOSYSTEM[],
): ChainTypes.IChain | undefined {
// This check is only used for the "native-token" extension
// (notice the "extensionAction.parameters.paymentNetworkName" property).
// This is important because "isSameChain" throws an error
// when "extensionAction.parameters.paymentNetworkName"
// and the chain supporting "requestState.currency"
// are not part of the same ecosystem.
// This should not happen in this case.
if (
requestState.currency.network &&
requestState.currency.type &&
extensionAction.parameters.paymentNetworkName &&
!this.currencyManager.chainManager.isSameChain(
requestState.currency.network,
extensionAction.parameters.paymentNetworkName,
this.currencyManager.chainManager.getEcosystemsByCurrencyType(requestState.currency.type),
ecosystems,
)
) {
throw new Error(
Expand All @@ -198,6 +243,7 @@ export default class AdvancedLogic implements AdvancedLogicTypes.IAdvancedLogic
?.network) || requestState.currency.network;

if (!chainName) return;
return this.currencyManager.chainManager.fromName(chainName);

return this.currencyManager.chainManager.fromName(chainName, ecosystems);
}
}
8 changes: 7 additions & 1 deletion packages/advanced-logic/src/extensions/abstract-extension.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { ExtensionTypes, IdentityTypes, RequestLogicTypes } from '@requestnetwork/types';
import {
ChainTypes,
ExtensionTypes,
IdentityTypes,
RequestLogicTypes,
} from '@requestnetwork/types';
import { deepCopy } from '@requestnetwork/utils';

/**
* Abstract class to create extension
*/
export abstract class AbstractExtension<TCreationParameters> implements ExtensionTypes.IExtension {
protected actions: ExtensionTypes.SupportedActions;
static supportedEcosystems: ChainTypes.ECOSYSTEM[] = [ChainTypes.ECOSYSTEM.EVM];

protected constructor(
public readonly extensionType: ExtensionTypes.TYPE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export default abstract class AddressBasedPaymentNetwork<
return this.isValidAddressForSymbolAndNetwork(
address,
'ETH',
this.currencyManager.chainManager.fromName('mainnet', ['evm']),
this.currencyManager.chainManager.fromName('mainnet', [ChainTypes.ECOSYSTEM.EVM]),
);
default:
throw new Error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default class AnyToErc20ProxyPaymentNetwork extends Erc20FeeProxyPaymentN
if (!acceptedCurrency) {
throw new UnsupportedCurrencyError({
value: address,
network: network?.name,
network,
});
}
if (!network || !this.currencyManager.supportsConversion(acceptedCurrency, network)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ExtensionTypes, RequestLogicTypes } from '@requestnetwork/types';
import { ChainTypes, ExtensionTypes, RequestLogicTypes } from '@requestnetwork/types';
import AddressBasedPaymentNetwork from '../address-based';
import { ICurrencyManager } from '@requestnetwork/currency';

Expand All @@ -24,7 +24,7 @@ export default class BitcoinAddressBasedPaymentNetwork extends AddressBasedPayme
return this.isValidAddressForSymbolAndNetwork(
address,
'BTC',
this.currencyManager.chainManager.fromName(BITCOIN_NETWORK, ['btc']),
this.currencyManager.chainManager.fromName(BITCOIN_NETWORK, [ChainTypes.ECOSYSTEM.BTC]),
);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import BitcoinAddressBasedPaymentNetwork from './mainnet-address-based';
import { ExtensionTypes } from '@requestnetwork/types';
import { ChainTypes, ExtensionTypes } from '@requestnetwork/types';
import { ICurrencyManager } from '@requestnetwork/currency';

const BITCOIN_NETWORK = 'testnet';
Expand All @@ -20,7 +20,7 @@ export default class BitcoinTestnetAddressBasedPaymentNetwork extends BitcoinAdd
return this.isValidAddressForSymbolAndNetwork(
address,
'BTC-testnet',
this.currencyManager.chainManager.fromName(BITCOIN_NETWORK, ['btc']),
this.currencyManager.chainManager.fromName(BITCOIN_NETWORK, [ChainTypes.ECOSYSTEM.BTC]),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,24 @@ export default class Erc20FeeProxyPaymentNetwork<
chainManager: ChainManager,
network?: ChainTypes.IChain | undefined,
): string {
return chainManager.ecosystems.near.isChainSupported(network)
return chainManager.ecosystems[ChainTypes.ECOSYSTEM.NEAR].isChainSupported(network)
? NEAR_CURRENT_VERSION
: EVM_CURRENT_VERSION;
}

// Override `validate` to account for network-specific instanciation (non-EVM only)
// Override `validate` to account for network-specific instantiation (non-EVM only)
protected validate(
request: RequestLogicTypes.IRequest,
extensionAction: ExtensionTypes.IAction,
): void {
if (
this.network &&
request.currency.network &&
!this.currencyManager.chainManager.isSameChain(this.network, request.currency.network, [
'evm',
'near',
])
!this.currencyManager.chainManager.isSameChain(
this.network,
request.currency.network,
ChainTypes.VM_ECOSYSTEMS,
)
) {
throw new UnsupportedNetworkError(this.constructor.name, request.currency.network, [
this.network.name,
Expand All @@ -67,18 +68,22 @@ export default class Erc20FeeProxyPaymentNetwork<

// Override `isValidAddress` to account for network-specific instanciation (non-EVM only)
protected isValidAddress(address: string): boolean {
if (this.currencyManager.chainManager.ecosystems['near'].isChainSupported(this.network)) {
if (
this.currencyManager.chainManager.ecosystems[ChainTypes.ECOSYSTEM.NEAR].isChainSupported(
this.network,
)
) {
if (this.network?.testnet) {
return this.isValidAddressForSymbolAndNetwork(
address,
'NEAR-testnet',
this.currencyManager.chainManager.fromName('near-testnet', ['near']),
this.currencyManager.chainManager.fromName('near-testnet', [ChainTypes.ECOSYSTEM.NEAR]),
);
} else {
return this.isValidAddressForSymbolAndNetwork(
address,
'NEAR',
this.currencyManager.chainManager.fromName('near', ['near']),
this.currencyManager.chainManager.fromName('near', [ChainTypes.ECOSYSTEM.NEAR]),
);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { ICurrencyManager } from '@requestnetwork/currency';
import AnyToNearPaymentNetwork from './any-to-near';
import { ChainTypes } from '@requestnetwork/types';

export default class AnyToNearTestnetPaymentNetwork extends AnyToNearPaymentNetwork {
public constructor(currencyManager: ICurrencyManager) {
// testnet PN version is the same as mainnet, can be overridden here if needed
super(currencyManager, [currencyManager.chainManager.fromName('aurora-testnet', ['near'])]);
super(currencyManager, [
currencyManager.chainManager.fromName('aurora-testnet', [ChainTypes.ECOSYSTEM.NEAR]),
]);
}

/**
Expand All @@ -17,7 +20,7 @@ export default class AnyToNearTestnetPaymentNetwork extends AnyToNearPaymentNetw
return this.isValidAddressForSymbolAndNetwork(
address,
'NEAR-testnet',
this.currencyManager.chainManager.fromName('aurora-testnet', ['near']),
this.currencyManager.chainManager.fromName('aurora-testnet', [ChainTypes.ECOSYSTEM.NEAR]),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ export default class AnyToNearPaymentNetwork extends AnyToNativeTokenPaymentNetw
currencyManager,
ExtensionTypes.PAYMENT_NETWORK_ID.ANY_TO_NATIVE_TOKEN,
currentVersion,
supportedNetworks ?? [currencyManager.chainManager.fromName('aurora', ['near'])],
supportedNetworks ?? [
currencyManager.chainManager.fromName('aurora', [ChainTypes.ECOSYSTEM.NEAR]),
],
);
}

Expand All @@ -33,7 +35,7 @@ export default class AnyToNearPaymentNetwork extends AnyToNativeTokenPaymentNetw
return this.isValidAddressForSymbolAndNetwork(
address,
'NEAR',
this.currencyManager.chainManager.fromName('aurora', ['near']),
this.currencyManager.chainManager.fromName('aurora', [ChainTypes.ECOSYSTEM.NEAR]),
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ export default class NearNativePaymentNetwork extends NativeTokenPaymentNetwork
currencyManager,
ExtensionTypes.PAYMENT_NETWORK_ID.NATIVE_TOKEN,
currentVersion,
supportedNetworks ?? [currencyManager.chainManager.fromName('aurora', ['near'])],
supportedNetworks ?? [
currencyManager.chainManager.fromName('aurora', [ChainTypes.ECOSYSTEM.NEAR]),
],
);
}

Expand All @@ -31,7 +33,7 @@ export default class NearNativePaymentNetwork extends NativeTokenPaymentNetwork
return this.isValidAddressForSymbolAndNetwork(
address,
'NEAR',
this.currencyManager.chainManager.fromName('aurora', ['near']),
this.currencyManager.chainManager.fromName('aurora', [ChainTypes.ECOSYSTEM.NEAR]),
);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import NearNativePaymentNetwork from './near-native';
import { ICurrencyManager } from '@requestnetwork/currency';
import { ChainTypes } from '@requestnetwork/types';

/**
* Implementation of the payment network to pay in Near on testnet based on input data.
*/
export default class NearTestnetNativeNativePaymentNetwork extends NearNativePaymentNetwork {
public constructor(currencyManager: ICurrencyManager) {
// testnet PN version is the same as mainnet, can be overridden here if needed
super(currencyManager, [currencyManager.chainManager.fromName('aurora-testnet', ['near'])]);
super(currencyManager, [
currencyManager.chainManager.fromName('aurora-testnet', [ChainTypes.ECOSYSTEM.NEAR]),
]);
}

/**
Expand All @@ -20,7 +23,7 @@ export default class NearTestnetNativeNativePaymentNetwork extends NearNativePay
return this.isValidAddressForSymbolAndNetwork(
address,
'NEAR-testnet',
this.currencyManager.chainManager.fromName('aurora-testnet', ['near']),
this.currencyManager.chainManager.fromName('aurora-testnet', [ChainTypes.ECOSYSTEM.NEAR]),
);
}
}
Loading