Skip to content

Commit

Permalink
feat: enable developers to configure network whitelisting (#170)
Browse files Browse the repository at this point in the history
Closes #148 #146

---------

Signed-off-by: Marin Petrunic <[email protected]>
Co-authored-by: Marin Petrunic <[email protected]>
  • Loading branch information
Lykhoyda and mpetrunic committed May 7, 2024
1 parent b154555 commit 5db505f
Show file tree
Hide file tree
Showing 7 changed files with 378 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import '../../../context/wallet';
import { choose } from 'lit/directives/choose.js';
import { when } from 'lit/directives/when.js';
import type { Eip1193Provider } from 'packages/widget/src/interfaces';
import type { PropertyValues } from '@lit/reactive-element';
import {
FungibleTokenTransferController,
FungibleTransferState
Expand All @@ -28,11 +29,18 @@ import { styles } from './styles';
export class FungibleTokenTransfer extends BaseComponent {
static styles = styles;

@property({ type: Array }) whitelistedSourceResources?: Array<string>;

@property({ type: String })
environment?: Environment = Environment.MAINNET;

@property({ type: Object })
whitelistedSourceNetworks?: string[];

@property({ type: Object })
whitelistedDestinationNetworks?: string[];

@property({ type: Object })
whitelistedSourceResources?: string[];

@property({ type: Object })
onSourceNetworkSelected?: (domain: Domain) => void;

Expand All @@ -41,7 +49,26 @@ export class FungibleTokenTransfer extends BaseComponent {

connectedCallback(): void {
super.connectedCallback();
void this.transferController.init(this.environment!);
void this.transferController.init(this.environment!, {
whitelistedSourceNetworks: this.whitelistedSourceNetworks,
whitelistedDestinationNetworks: this.whitelistedDestinationNetworks,
whitelistedSourceResources: this.whitelistedSourceResources
});
}

updated(changedProperties: PropertyValues<this>): void {
super.updated(changedProperties);
if (
changedProperties.has('whitelistedSourceNetworks') ||
changedProperties.has('whitelistedDestinationNetworks') ||
changedProperties.has('whitelistedSourceResources')
) {
void this.transferController.init(this.environment!, {
whitelistedSourceNetworks: this.whitelistedSourceNetworks,
whitelistedDestinationNetworks: this.whitelistedDestinationNetworks,
whitelistedSourceResources: this.whitelistedSourceResources
});
}
}

private onClick = (): void => {
Expand Down
4 changes: 2 additions & 2 deletions packages/widget/src/context/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { customElement, property } from 'lit/decorators.js';
import { createContext, ContextProvider } from '@lit/context';
import { ContextProvider, createContext } from '@lit/context';
import type { WalletConnectOptions } from '@web3-onboard/walletconnect/dist/types';
import type { HTMLTemplateResult, PropertyValues } from 'lit';
import { html } from 'lit';
import type { AppMetadata, WalletInit } from '@web3-onboard/common';
import { BaseComponent } from '../components/common/base-component';
import type { Theme } from '../interfaces';
import { BaseComponent } from '../components/common/base-component';

export interface ConfigContext {
theme?: Theme;
Expand Down
4 changes: 2 additions & 2 deletions packages/widget/src/context/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ export class WalletContextProvider extends BaseComponent {
@property({ attribute: false })
substrateProviders?: Array<ApiPromise> = [];

@property({ type: String }) environment?: Environment;
@property({ type: String })
environment?: Environment;

async connectedCallback(): Promise<void> {
super.connectedCallback();
Expand Down Expand Up @@ -174,7 +175,6 @@ export class WalletContextProvider extends BaseComponent {
// if not already specified by the user
const parachainIds = Object.keys(SUBSTRATE_RPCS[environment]);
for (const parachainId of parachainIds) {
console.log(`creating default provider for ${parachainId}`);
const _parachainId = parseInt(parachainId);

if (!substrateProviders.has(_parachainId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import type {
import {
Config,
Environment,
Network,
getRoutes
getRoutes,
Network
} from '@buildwithsygma/sygma-sdk-core';
import { ContextConsumer } from '@lit/context';
import { BigNumber, ethers } from 'ethers';
Expand All @@ -22,12 +22,12 @@ import type {
ParachainID,
SubstrateFee
} from '@buildwithsygma/sygma-sdk-core/substrate';
import type { WalletContext } from '../../context';
import { walletContext } from '../../context';
import { MAINNET_EXPLORER_URL, TESTNET_EXPLORER_URL } from '../../constants';
import { validateAddress } from '../../utils';
import { SdkInitializedEvent } from '../../interfaces';
import { substrateProviderContext } from '../../context/wallet';
import type { WalletContext } from '../../context';
import { buildEvmFungibleTransactions, executeNextEvmTransaction } from './evm';
import {
buildSubstrateFungibleTransactions,
Expand Down Expand Up @@ -92,6 +92,10 @@ export class FungibleTokenTransferController implements ReactiveController {
//source network chain id -> Route[]
protected routesCache: Map<number, Route[]> = new Map();

protected whitelistedSourceNetworks?: string[] = [];
protected whitelistedDestinationNetworks?: string[] = [];
protected whitelistedSourceResources?: string[] = [];

host: ReactiveElement;
walletContext: ContextConsumer<typeof walletContext, ReactiveElement>;
substrateProviderContext: ContextConsumer<
Expand Down Expand Up @@ -127,7 +131,7 @@ export class FungibleTokenTransferController implements ReactiveController {
/**
* Provides substrate provider
* based on parachain id
* @param {ParachainId} parachainId
* @param {parachainId} parachainId
* @returns {ApiPromise | undefined}
*/
getSubstrateProvider(parachainId: ParachainID): ApiPromise | undefined {
Expand All @@ -146,6 +150,7 @@ export class FungibleTokenTransferController implements ReactiveController {
constructor(host: ReactiveElement) {
(this.host = host).addController(this);
this.config = new Config();

this.walletContext = new ContextConsumer(host, {
context: walletContext,
subscribe: true,
Expand Down Expand Up @@ -200,15 +205,59 @@ export class FungibleTokenTransferController implements ReactiveController {
}
}

async init(env: Environment): Promise<void> {
/**
* Filter source and destination networks specified by User
* @param whitelistedNetworks
* @param network
*/
filterWhitelistedNetworks = (
whitelistedNetworks: string[] | undefined,
network: Domain
): boolean => {
// skip filtering if whitelisted networks are empty
if (!whitelistedNetworks?.length) return true;

return whitelistedNetworks.some(
(networkName) => networkName.toLowerCase() === network.name.toLowerCase()
);
};

async init(
env: Environment,
options?: {
whitelistedSourceNetworks?: string[];
whitelistedDestinationNetworks?: string[];
whitelistedSourceResources?: string[];
}
): Promise<void> {
this.host.requestUpdate();
this.env = env;

this.whitelistedSourceNetworks = options?.whitelistedSourceNetworks;
this.whitelistedDestinationNetworks =
options?.whitelistedDestinationNetworks;
this.whitelistedSourceResources = options?.whitelistedSourceResources;

await this.retryInitSdk();
this.supportedSourceNetworks = this.config.getDomains();
this.supportedDestinationNetworks = this.config.getDomains();
this.supportedSourceNetworks = this.config
.getDomains()
.filter((network) =>
this.filterWhitelistedNetworks(
options?.whitelistedSourceNetworks,
network
)
);
this.supportedDestinationNetworks = this.config
.getDomains()
.filter((network) =>
this.filterWhitelistedNetworks(
options?.whitelistedDestinationNetworks,
network
)
);
this.host.requestUpdate();
}

resetFee(): void {
this.fee = null;
}
Expand Down Expand Up @@ -415,6 +464,12 @@ export class FungibleTokenTransferController implements ReactiveController {
if (!this.destinationNetwork) {
this.supportedDestinationNetworks = routes
.filter((route) => route.toDomain.chainId !== sourceNetwork.chainId)
.filter((route) =>
this.filterWhitelistedNetworks(
this.whitelistedDestinationNetworks,
route.toDomain
)
)
.map((route) => route.toDomain);
} // source change but not destination, check if route is supported
else if (this.supportedDestinationNetworks.length && routes.length) {
Expand Down Expand Up @@ -442,8 +497,13 @@ export class FungibleTokenTransferController implements ReactiveController {
(route.toDomain.chainId === this.destinationNetwork?.chainId &&
!this.supportedResources.includes(route.resource))
)
.map((route) => route.resource);
.filter((route) => {
// skip filter if resources are not specified
if (!this.whitelistedSourceResources?.length) return true;

return this.whitelistedSourceResources.includes(route.resource.symbol!);
})
.map((route) => route.resource);
void this.buildTransactions();
this.host.requestUpdate();
};
Expand Down
8 changes: 2 additions & 6 deletions packages/widget/src/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import type {
Environment,
EvmResource,
SubstrateResource
} from '@buildwithsygma/sygma-sdk-core';
import type { Environment } from '@buildwithsygma/sygma-sdk-core';
import type { ApiPromise } from '@polkadot/api';
import type { Signer } from '@polkadot/api/types';
import type { WalletConnectOptions } from '@web3-onboard/walletconnect/dist/types';
Expand All @@ -27,11 +23,11 @@ export interface ISygmaProtocolWidget {
environment?: Environment;
whitelistedSourceNetworks?: string[];
whitelistedDestinationNetworks?: string[];
whitelistedSourceResources?: string[];
evmProvider?: Eip1193Provider;
substrateProviders?: Array<ApiPromise>;
substrateSigner?: Signer;
show?: boolean;
whitelistedSourceResources?: Array<EvmResource | SubstrateResource>;
expandable?: boolean;
darkTheme?: boolean;
customLogo?: SVGElement;
Expand Down
18 changes: 8 additions & 10 deletions packages/widget/src/widget.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import type {
Domain,
EvmResource,
SubstrateResource
} from '@buildwithsygma/sygma-sdk-core';
import type { Domain } from '@buildwithsygma/sygma-sdk-core';
import { Environment } from '@buildwithsygma/sygma-sdk-core';
import type { ApiPromise } from '@polkadot/api';
import type { Signer } from '@polkadot/api/types';
Expand All @@ -28,6 +24,7 @@ import type {
Theme
} from './interfaces';
import { styles } from './styles';
import { BaseComponent } from './components/common';

@customElement('sygmaprotocol-widget')
class SygmaProtocolWidget
Expand All @@ -44,6 +41,8 @@ class SygmaProtocolWidget

@property({ type: Array }) whitelistedDestinationNetworks?: string[];

@property({ type: Array }) whitelistedSourceResources?: string[];

@property({ type: Object }) evmProvider?: Eip1193Provider;

@property({ type: Array }) substrateProviders?: Array<ApiPromise>;
Expand All @@ -52,10 +51,6 @@ class SygmaProtocolWidget

@property({ type: Boolean }) show?: boolean;

@property({ type: Array }) whitelistedSourceResources?: Array<
EvmResource | SubstrateResource
>;

@property({ type: Boolean }) expandable?: boolean;

@property({ type: Boolean }) darkTheme?: boolean;
Expand Down Expand Up @@ -126,8 +121,11 @@ class SygmaProtocolWidget
.environment=${this.environment as Environment}
.onSourceNetworkSelected=${(domain: Domain) =>
(this.sourceNetwork = domain)}
.whitelistedSourceResources=${this.whitelistedSourceNetworks}
environment=${Environment.TESTNET}
.whitelistedSourceNetworks=${this.whitelistedSourceNetworks}
.whitelistedDestinationNetworks=${this
.whitelistedDestinationNetworks}
.whitelistedSourceResources=${this.whitelistedSourceResources}
>
</sygma-fungible-transfer>
</section>
Expand Down
Loading

0 comments on commit 5db505f

Please sign in to comment.