diff --git a/modules/bitgo/test/v2/unit/keychains.ts b/modules/bitgo/test/v2/unit/keychains.ts index 2e9b7c922d..745d21c8b2 100644 --- a/modules/bitgo/test/v2/unit/keychains.ts +++ b/modules/bitgo/test/v2/unit/keychains.ts @@ -93,6 +93,7 @@ describe('V2 Keychains', function () { n.asset !== UnderlyingAsset.SEIEVM && n.asset !== UnderlyingAsset.KAIA && n.asset !== UnderlyingAsset.IRYS && + n.asset !== UnderlyingAsset.FLRP && coinFamilyValues.includes(n.name) ); diff --git a/modules/sdk-core/src/bitgo/environments.ts b/modules/sdk-core/src/bitgo/environments.ts index 636f265530..0165941126 100644 --- a/modules/sdk-core/src/bitgo/environments.ts +++ b/modules/sdk-core/src/bitgo/environments.ts @@ -71,6 +71,8 @@ interface EnvironmentTemplate { xdcExplorerApiToken?: string; flrExplorerBaseUrl?: string; flrExplorerApiToken?: string; + flrpExplorerBaseUrl?: string; + // flrpExplorerApiToken?: string; sgbExplorerBaseUrl?: string; sgbExplorerApiToken?: string; icpNodeUrl: string; @@ -235,6 +237,7 @@ const mainnetBase: EnvironmentTemplate = { monExplorerBaseUrl: 'https://mainnet-beta.monvision.io', stxNodeUrl: 'https://api.hiro.so', vetNodeUrl: 'https://rpc-mainnet.vechain.energy', + flrpExplorerBaseUrl: 'https://coston2-rpc.flare.network', }; const testnetBase: EnvironmentTemplate = { @@ -305,6 +308,7 @@ const testnetBase: EnvironmentTemplate = { worldExplorerBaseUrl: 'https://sepolia.worldscan.org/', somniaExplorerBaseUrl: 'https://shannon-explorer.somnia.network/', soneiumExplorerBaseUrl: 'https://soneium-minato.blockscout.com', + flrpExplorerBaseUrl: 'https://coston2-explorer.flare.network', // To be checked again evm: { phrs: { baseUrl: 'https://testnet.dplabs-internal.com', diff --git a/modules/statics/src/base.ts b/modules/statics/src/base.ts index 3a4d78d7a1..c5f7069055 100644 --- a/modules/statics/src/base.ts +++ b/modules/statics/src/base.ts @@ -55,6 +55,7 @@ export enum CoinFamily { FETCHAI = 'fetchai', FIAT = 'fiat', FLR = 'flr', + FLRP = 'flrp', // Flare P Chain HASH = 'hash', // Provenance HBAR = 'hbar', ICP = 'icp', @@ -469,6 +470,7 @@ export enum UnderlyingAsset { EURR = 'eurr', FETCHAI = 'fetchai', FLR = 'flr', + FLRP = 'flrp', // Flare P Chain GTC = 'gtc', HASH = 'hash', // Provenance HBAR = 'hbar', // Hedera main coin diff --git a/modules/statics/src/coins.ts b/modules/statics/src/coins.ts index a20a5d28bd..55f7c419e4 100644 --- a/modules/statics/src/coins.ts +++ b/modules/statics/src/coins.ts @@ -53,6 +53,7 @@ import { import { ofcToken } from './ofc'; import { ada } from './ada'; import { avaxp } from './avaxp'; +import { flrp } from './flrp'; import { BaseCoin, BaseUnit, CoinFeature, KeyCurve, UnderlyingAsset } from './base'; import { AmsTokenConfig, TrimmedAmsTokenConfig } from './tokenConfig'; import { erc20Coins } from './coins/erc20Coins'; @@ -153,6 +154,14 @@ export const coins = CoinMap.fromCoins([ Networks.test.avalancheP, UnderlyingAsset.AVAXP ), + flrp('f90c4f28-447d-4b34-a75a-a94bbce97c14', 'flrp', 'Flare P Chain', Networks.main.flrp, UnderlyingAsset.FLRP), + flrp( + '80f08de8-a61f-4e25-bb06-866752b63382', + 'tflrp', + 'Flare P Chain Testnet', + Networks.test.flrp, + UnderlyingAsset.FLRP + ), ada( 'fd4d125e-f14f-414b-bd17-6cb1393265f0', 'ada', diff --git a/modules/statics/src/flrp.ts b/modules/statics/src/flrp.ts new file mode 100644 index 0000000000..9708e6fed8 --- /dev/null +++ b/modules/statics/src/flrp.ts @@ -0,0 +1,92 @@ +import { BaseCoin, BaseUnit, CoinFeature, CoinKind, KeyCurve, UnderlyingAsset } from './base'; +import { AvalancheNetwork } from './networks'; + +export interface FLRPConstructorOptions { + id: string; + fullName: string; + name: string; + network: AvalancheNetwork; // To be checked again + features: CoinFeature[]; + asset: UnderlyingAsset; + prefix?: string; + suffix?: string; + primaryKeyCurve: KeyCurve; +} + +export class FLRPCoin extends BaseCoin { + public static readonly DEFAULT_FEATURES = [ + CoinFeature.UNSPENT_MODEL, + CoinFeature.CUSTODY_BITGO_TRUST, + CoinFeature.CUSTODY_BITGO_MENA_FZE, + CoinFeature.CUSTODY_BITGO_CUSTODY_MENA_FZE, + CoinFeature.CUSTODY_BITGO_GERMANY, + CoinFeature.CUSTODY_BITGO_FRANKFURT, + CoinFeature.MULTISIG_COLD, + CoinFeature.MULTISIG, + ]; + + /** + * Additional fields for utxo coins + */ + public readonly network: AvalancheNetwork; + + constructor(options: FLRPConstructorOptions) { + super({ + ...options, + kind: CoinKind.CRYPTO, + isToken: false, + decimalPlaces: 9, + baseUnit: BaseUnit.ETH, + }); + + this.network = options.network; + } + + protected disallowedFeatures(): Set { + return new Set([CoinFeature.ACCOUNT_MODEL]); + } + + protected requiredFeatures(): Set { + return new Set([CoinFeature.UNSPENT_MODEL]); + } +} + +/** + * Factory function for utxo coin instances. + * + * @param id uuid v4 + * @param name unique identifier of the coin + * @param fullName Complete human-readable name of the coin + * @param network Network object for this coin + * @param asset Asset which this coin represents. This is the same for both mainnet and testnet variants of a coin. + * @param features? Features of this coin. Defaults to the DEFAULT_FEATURES defined in `UtxoCoin` + * @param prefix? Optional coin prefix. Defaults to empty string + * @param suffix? Optional coin suffix. Defaults to coin name. + * @param primaryKeyCurve The elliptic curve for this chain/token + */ +export function flrp( + id: string, + name: string, + fullName: string, + network: AvalancheNetwork, //To be checked again + asset: UnderlyingAsset, + features: CoinFeature[] = FLRPCoin.DEFAULT_FEATURES, + prefix = '', + suffix: string = name.toUpperCase(), + /** All UTXOs BitGo supports are SECP256K1 **/ + primaryKeyCurve: KeyCurve = KeyCurve.Secp256k1 +) { + return Object.freeze( + new FLRPCoin({ + id, + name, + fullName, + network, + prefix, + suffix, + features, + asset, + primaryKeyCurve, + }) + ); +} diff --git a/modules/statics/src/networks.ts b/modules/statics/src/networks.ts index 1603e2ef76..bf7897ff2e 100644 --- a/modules/statics/src/networks.ts +++ b/modules/statics/src/networks.ts @@ -311,6 +311,61 @@ class AvalanchePTestnet extends Testnet implements AvalancheNetwork { minDelegationFee = '2'; } +//TO BE CHECKED AGAIN +class FlrP extends Mainnet implements AvalancheNetwork { + name = 'FlareP'; + family = CoinFamily.FLRP; + explorerUrl = 'https://flare.space/dapp/p-chain-explorer'; + accountExplorerUrl = 'https://subnets.avax.network/p-chain/address/'; // To be checked again + blockchainID = '11111111111111111111111111111111LpoYY'; // To be checked again + cChainBlockchainID = '2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5'; // To be checked again + avaxAssetID = 'FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z'; // To be checked again + networkID = 1; + hrp = 'flare'; + alias = 'P'; + vm = 'platformvm'; + txFee = '1000000'; + maxImportFee = '10000000'; + createSubnetTx = '1000000000'; + createChainTx = '1000000000'; + creationTxFee = '10000000'; + minConsumption = '0.1'; + maxConsumption = '0.12'; + maxSupply = '720000000000000000'; + minStake = '2000000000000'; + minStakeDuration = '1209600'; + maxStakeDuration = '31536000'; + minDelegationStake = '25000000000'; + minDelegationFee = '2'; +} + +//TO BE CHECKED AGAIN +class FlrPTestnet extends Testnet implements AvalancheNetwork { + name = 'FlarePTestnet'; + family = CoinFamily.FLRP; + explorerUrl = 'https://subnets-test.avax.network/p-chain/tx/'; + accountExplorerUrl = 'https://subnets-test.avax.network/p-chain/address/'; + blockchainID = '11111111111111111111111111111111LpoYY'; + cChainBlockchainID = 'yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp'; + avaxAssetID = 'U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK'; + networkID = 5; + alias = 'P'; + hrp = 'flare'; + vm = 'platformvm'; + txFee = '1000000'; + maxImportFee = '10000000'; + createSubnetTx = '1000000000'; + createChainTx = '1000000000'; + creationTxFee = '10000000'; + minConsumption = '0.1'; + maxConsumption = '0.12'; + maxSupply = '720000000000000000'; + minStake = '1000000000'; + minStakeDuration = '86400'; + maxStakeDuration = '31536000'; + minDelegationStake = '1000000000'; + minDelegationFee = '2'; +} class BinanceSmartChain extends Mainnet implements EthereumNetwork { name = 'BinanceSmartChain'; family = CoinFamily.BSC; @@ -1704,6 +1759,7 @@ export const Networks = { fiat: Object.freeze(new Fiat()), fetchai: Object.freeze(new FetchAi()), flr: Object.freeze(new Flare()), + flrp: Object.freeze(new FlrP()), hash: Object.freeze(new Hash()), hedera: Object.freeze(new Hedera()), icp: Object.freeze(new Icp()), @@ -1788,6 +1844,7 @@ export const Networks = { fiat: Object.freeze(new FiatTestnet()), fetchai: Object.freeze(new FetchAiTestnet()), flr: Object.freeze(new FlareTestnet()), + flrp: Object.freeze(new FlrPTestnet()), mon: Object.freeze(new MonadTestnet()), pyrmont: Object.freeze(new Pyrmont()), ethereumClassicTestnet: Object.freeze(new EthereumClassicTestnet()), diff --git a/modules/statics/test/unit/coins.ts b/modules/statics/test/unit/coins.ts index ec669d522d..59ea29c6f7 100644 --- a/modules/statics/test/unit/coins.ts +++ b/modules/statics/test/unit/coins.ts @@ -59,6 +59,18 @@ const custodyFeatures: Record = { avaxp: { features: [CoinFeature.CUSTODY_BITGO_GERMANY, CoinFeature.CUSTODY_BITGO_FRANKFURT], }, + flrp: { + features: [ + CoinFeature.CUSTODY_BITGO_GERMANY, + CoinFeature.CUSTODY_BITGO_NEW_YORK, + CoinFeature.CUSTODY_BITGO_FRANKFURT, + CoinFeature.CUSTODY_BITGO_EUROPE_APS, + CoinFeature.CUSTODY_BITGO_SISTER_TRUST_ONE, + CoinFeature.CUSTODY_BITGO_KOREA, + CoinFeature.CUSTODY_BITGO_SINGAPORE, + CoinFeature.CUSTODY_BITGO_SWITZERLAND, + ], + }, btc: { features: [ CoinFeature.CUSTODY_BITGO_GERMANY, @@ -432,6 +444,18 @@ const custodyFeatures: Record = { tavaxp: { features: [CoinFeature.CUSTODY_BITGO_GERMANY, CoinFeature.CUSTODY_BITGO_FRANKFURT], }, + tflr: { + features: [ + CoinFeature.CUSTODY_BITGO_GERMANY, + CoinFeature.CUSTODY_BITGO_NEW_YORK, + CoinFeature.CUSTODY_BITGO_FRANKFURT, + CoinFeature.CUSTODY_BITGO_EUROPE_APS, + CoinFeature.CUSTODY_BITGO_SISTER_TRUST_ONE, + CoinFeature.CUSTODY_BITGO_KOREA, + CoinFeature.CUSTODY_BITGO_SINGAPORE, + CoinFeature.CUSTODY_BITGO_SWITZERLAND, + ], + }, tbtc: { features: [ CoinFeature.CUSTODY_BITGO_GERMANY,