Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PEN and XLM tokens to Astar portal #1348

Merged
merged 20 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
23 changes: 23 additions & 0 deletions src/assets/img/token/PEN.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions src/assets/img/token/XLM.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/modules/xcm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,15 @@ export let xcmChainObj: XcmChainObj = {
subscan: 'https://hydration.subscan.io',
isAstarNativeToken: true,
},
[Chain.PENDULUM]: {
name: Chain.PENDULUM,
relayChain: Chain.POLKADOT,
img: require('/src/assets/img/token/PEN.svg'),
parachainId: parachainIds.PENDULUM,
endpoints: ['wss://rpc-pendulum.prd.pendulumchain.tech:443'],
subscan: 'https://pendulum.subscan.io/',
isAstarNativeToken: false,
},
};

export const xcmChains = objToArray(xcmChainObj);
Expand Down
20 changes: 20 additions & 0 deletions src/modules/xcm/tokens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,26 @@ export const xcmToken = {
originChain: Chain.HYDRATION,
minBridgeAmount: '5',
},
{
symbol: 'xcPEN',
isNativeToken: true,
assetId: '18446744073709551634',
originAssetId: 'PEN',
logo: require('/src/assets/img/token/PEN.svg'),
isXcmCompatible: true,
originChain: Chain.PENDULUM,
minBridgeAmount: '2',
},
{
symbol: 'XLM.s',
isNativeToken: false,
assetId: '18446744073709551635',
originAssetId: 'XLM.s',
logo: require('/src/assets/img/token/XLM.svg'),
isXcmCompatible: true,
originChain: Chain.PENDULUM,
minBridgeAmount: '1',
},
],
[endpointKey.SHIDEN]: [
{
Expand Down
2 changes: 2 additions & 0 deletions src/v2/config/xcm/XcmRepositoryConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
EquilibriumXcmRepository,
UniqueXcmRepository,
HydrationXcmRepository,
PendulumXcmRepository,
} from 'src/v2/repositories/implementations';
import { Chain } from 'src/v2/models/XcmModels';
import { TypeMapping } from 'src/v2/config/types';
Expand All @@ -36,6 +37,7 @@ export const XcmRepositoryConfiguration: TypeMapping = {
[Chain.EQUILIBRIUM]: EquilibriumXcmRepository,
[Chain.UNIQUE]: UniqueXcmRepository,
[Chain.HYDRATION]: HydrationXcmRepository,
[Chain.PENDULUM]: PendulumXcmRepository,
};

export type AstarToken = 'ASTR' | 'SDN';
Expand Down
2 changes: 2 additions & 0 deletions src/v2/models/XcmModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export enum Chain {
EQUILIBRIUM = 'Equilibrium',
UNIQUE = 'Unique',
HYDRATION = 'Hydration',
PENDULUM = 'Pendulum',
}

export enum parachainIds {
Expand All @@ -43,6 +44,7 @@ export enum parachainIds {
EQUILIBRIUM = 2011,
UNIQUE = 2037,
HYDRATION = 2034,
PENDULUM = 2094,
}

export interface XcmChain {
Expand Down
1 change: 1 addition & 0 deletions src/v2/repositories/implementations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export * from './xcm/BifrostXcmRepository';
export * from './xcm/EquilibriumXcmRepository';
export * from './xcm/UniqueXcmRepository';
export * from './xcm/HydrationXcmRepository';
export * from './xcm/PendulumXcmRepository';
export * from './NftRepository';
export * from './AccountUnificationRepository';
export * from './InflationRepository';
Expand Down
106 changes: 106 additions & 0 deletions src/v2/repositories/implementations/xcm/PendulumXcmRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { BN } from '@polkadot/util';
import { XcmTokenInformation } from 'src/modules/xcm';
import { container } from 'src/v2/common';
import { ExtrinsicPayload, IApi, IApiFactory } from 'src/v2/integration';
import { Asset } from 'src/v2/models';
import { Symbols } from 'src/v2/symbols';
import { XcmRepository } from '../XcmRepository';
import { XcmChain } from 'src/v2/models/XcmModels';
import { TokensAccounts } from 'src/v2/repositories/implementations/xcm/AcalaXcmRepository';
import { decodeAddress } from '@polkadot/util-crypto';

// Mapping object for token IDs
const TOKEN_IDS: Record<string, any> = {
PEN: 'Native',
'XLM.s': { Stellar: 'StellarNative' },
};

export class PendulumXcmRepository extends XcmRepository {
constructor() {
const defaultApi = container.get<IApi>(Symbols.DefaultApi);
const apiFactory = container.get<IApiFactory>(Symbols.ApiFactory);
const registeredTokens = container.get<XcmTokenInformation[]>(Symbols.RegisteredTokens);
super(defaultApi, apiFactory, registeredTokens);
}

public async getTransferCall(
from: XcmChain,
to: XcmChain,
recipientAddress: string,
token: Asset,
amount: BN,
endpoint: string
): Promise<ExtrinsicPayload> {
if (!to.parachainId) {
throw `Parachain id for ${to.name} is not defined`;
}

const tokenData = TOKEN_IDS[token.originAssetId];
if (!tokenData) {
throw `Token name for ${token.originAssetId} is not defined`;
}

const version = 'V3';

const AccountId32 = {
id: decodeAddress(recipientAddress),
};

const destination = {
[version]: {
parents: '1',
interior: {
X2: [
{
Parachain: to.parachainId,
},
{
AccountId32,
},
],
},
},
};

const destWeight = { Unlimited: null };

return await this.buildTxCall(
from,
endpoint,
'xTokens',
'transfer',
tokenData,
amount,
destination,
destWeight
);
}

public async getTokenBalance(
address: string,
chain: XcmChain,
token: Asset,
isNativeToken: boolean,
endpoint: string
): Promise<string> {
const api = await this.apiFactory.get(endpoint);

try {
if (isNativeToken) {
const nativeBalance = await this.getNativeBalance(address, chain, endpoint);
return nativeBalance.toString();
}

const currencyId = TOKEN_IDS[token.originAssetId];
if (!currencyId) {
console.error(`Token name for ${token.originAssetId} is not defined`);
return '0';
}
const bal = await api.query.tokens.accounts<TokensAccounts>(address, currencyId);
return bal.free.toString();
} catch (e) {
console.error(e);
return '0';
}
}
}
Loading