Skip to content

Commit

Permalink
Merge pull request #1013 from moonbeam-foundation/themacexpert/ups
Browse files Browse the repository at this point in the history
New XC Asset Registration Process
  • Loading branch information
eshaben authored Feb 12, 2025
2 parents 70aa14c + 1a29184 commit bd60f55
Show file tree
Hide file tree
Showing 9 changed files with 357 additions and 148 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import axios from 'axios';

// CoinGecko IDs for the networks
const NETWORK_IDS = {
GLMR: 'moonbeam',
MOVR: 'moonriver',
};

async function calculateRelativePrice(
assetPrice: number,
assetDecimals: number,
network: 'GLMR' | 'MOVR'
): Promise<bigint> {
try {
// Fetch the native token price from CoinGecko
const response = await axios.get(
`https://api.coingecko.com/api/v3/simple/price?ids=${NETWORK_IDS[network]}&vs_currencies=usd`
);

const nativeTokenPrice = response.data[NETWORK_IDS[network]].usd;

// Calculate relative price with 18 decimal places
// Formula: (assetPrice / nativeTokenPrice) * 10^18
// This gives us how many units of the asset we need to equal 1 unit of native token
const relativePrice = BigInt(
0.175 *
Math.pow(10, 18 - assetDecimals) *
(assetPrice / nativeTokenPrice) *
Math.pow(10, 18)
);

// Return as string to preserve precision
return relativePrice;
} catch (error) {
if (error instanceof Error) {
throw new Error(`Failed to calculate relative price: ${error.message}`);
}
throw error;
}
}

function validateInput(
price: string,
decimals: string,
network: string
): { assetPrice: number; assetDecimals: number; network: 'GLMR' | 'MOVR' } {
// Validate price
const assetPrice = parseFloat(price);
if (isNaN(assetPrice) || assetPrice <= 0) {
throw new Error('Price must be a positive number');
}

// Validate decimals
const assetDecimals = parseFloat(decimals);
if (isNaN(assetDecimals) || assetDecimals <= 0) {
throw new Error('Decimals must be a positive number');
}

// Validate network
const upperNetwork = network.toUpperCase() as 'GLMR' | 'MOVR';
if (!['GLMR', 'MOVR'].includes(upperNetwork)) {
throw new Error('Network must be either GLMR or MOVR');
}

return { assetPrice, assetDecimals, network: upperNetwork };
}

function printUsage() {
console.log('\nUsage:');
console.log(
'npx ts-node calculate-relative-price.ts <price> <decimals> <network>'
);
console.log('\nExample:');
console.log('npx ts-node calculate-relative-price.ts 0.25 12 GLMR');
console.log('\nParameters:');
console.log('price - The price of your asset in USD');
console.log('decimals - The decimals of your asset');
console.log('network - Either GLMR or MOVR');
}

async function main() {
try {
// Get command line arguments
const [, , price, decimals, network] = process.argv;

// Check if help flag is passed
if (price === '--help' || price === '-h') {
printUsage();
return;
}

// Check if required arguments are provided
if (!price || !decimals || !network) {
console.error('Error: Missing required arguments');
printUsage();
process.exit(1);
}

// Validate inputs
const {
assetPrice,
assetDecimals,
network: validNetwork,
} = validateInput(price, decimals, network);

console.log(
`\nCalculating relative price for asset worth $${assetPrice} against ${validNetwork}...`
);
const relativePrice = await calculateRelativePrice(
assetPrice,
assetDecimals,
validNetwork
);
const nativeTokenPrice = (
await axios.get(
`https://api.coingecko.com/api/v3/simple/price?ids=${NETWORK_IDS[validNetwork]}&vs_currencies=usd`
)
).data[NETWORK_IDS[validNetwork]].usd;

const decimalRatio = nativeTokenPrice / assetPrice;

console.log(`\nResults:`);
console.log(`Asset Price: $${assetPrice}`);
console.log(`Network: ${validNetwork}`);
console.log(`Native Token Price (from CoinGecko): $${nativeTokenPrice}`);
console.log(`\nRelative Price Analysis:`);
console.log(
`1 ${validNetwork} is equal to approximately ${decimalRatio.toFixed(
3
)} of your specified token.`
);
console.log(
`With 18 decimals, 1 ${validNetwork} or in WEI, 1000000000000000000 is equal to a relative price of ${relativePrice} units of your token`
);
console.log(`\nRelative Price: ${relativePrice}`);
console.log(
`\nThe relative price you should specify in asset registration steps is ${relativePrice}\n`
);
} catch (error) {
console.error('\nError:', error instanceof Error ? error.message : error);
process.exit(1);
}
}

main();
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div id="termynal" data-termynal>
<span data-ty="input"><span class="file-path"></span>yarn calculate-relative-price 0.04901 12 GLMR</span>
<span data-ty></span>
<span data-ty>Calculating relative price for asset worth $0.04901 against GLMR...</span>
<span data-ty></span>
<span data-ty>Results:</span>
<span data-ty>Asset Price: $0.04901</span>
<span data-ty>Network: GLMR</span>
<span data-ty>Native Token Price (from CoinGecko): $0.126009</span>
<span data-ty></span>
<span data-ty>Relative Price Analysis:</span>
<span data-ty>1 GLMR is equal to approximately 2.571 of your specified token.</span>
<span data-ty>With 18 decimals, 1 GLMR (in WEI: 1000000000000000000) is equal to 68064582688538114392064 units of your token.</span>
<span data-ty></span>
<span data-ty>Relative Price: 68064582688538114392064</span>
<span data-ty></span>
<span data-ty>The relative price you should specify in asset registration steps is 68064582688538114392064</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div id="termynal" data-termynal>
<span data-ty><span class="file-path"></span>yarn register-asset --w wss://wss.api.moonbeam.network \</span>
<span data-ty>--asset '{ "parents": 1, "interior": {"X1": [{ "Parachain": 3370}]}}' \</span>
<span data-ty>--symbol "xcLAOS" \</span>
<span data-ty>--decimals 18 \</span>
<span data-ty>--name "LAOS" \</span>
<span data-ty>--relative-price 68064582688538114392064</span>
<span data-ty>yarn run v1.22.22</span>
<span data-ty>warning ../../../package.json: No license field</span>
<span data-ty>$ ts-node 'scripts/xcm-asset-registrator.ts' --w wss://wss.api.moonbeam.network --asset '{ "parents": 1, "interior": {"X1": [{ "Parachain": 3370}]}}' --symbol xcLAOS --decimals 18 --name LAOS --relative-price 68064582688538114392064</span>
<span data-ty>XCM Version is V4</span>
<span data-ty>Encoded Call Data for registerAsset is 0x72008835e1b9f588de47ec5e4a828e4e70dd010100a934121878634c414f53104c414f53</span>
<span data-ty>Encoded Call Data for Set Relative Price is 0x7300010100a9340000805c9cf5d5c9690e000000000000</span>
<span data-ty>Encoded Call Data for batched is 0x1e000872008835e1b9f588de47ec5e4a828e4e70dd010100a934121878634c414f53104c414f537300010100a9340000805c9cf5d5c9690e000000000000</span>
<span data-ty>✨ Done in 5.20s.</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ApiPromise, WsProvider } from '@polkadot/api';
import { encodeAddress } from '@polkadot/util-crypto';
import { u8aToHex } from '@polkadot/util';

async function getEncodedCallData() {
// Connect to Moonbase Alpha
const provider = new WsProvider('wss://moonbase-alpha.public.blastapi.io');
const api = await ApiPromise.create({ provider });

// Corrected XCM V4 Multilocation structure
const xcmLocation = {
parents: 1,
interior: {
X1: [{ Parachain: 888 }],
},
};

// Relative price as u128
const relativePrice = 'INSERT_RELATIVE_PRICE'; // Insert value generated
// from the relative price script e.g. 1299476000000000000

try {
// Create the call
const call = api.tx.xcmWeightTrader.addAsset(xcmLocation, relativePrice);

// Get the encoded call data
const encodedData = call.method.toHex();
console.log('Encoded Call Data:', encodedData);

await api.disconnect();
return encodedData;
} catch (error) {
console.error('Error details:', error);
console.error(
'Attempted XCM Location:',
JSON.stringify(xcmLocation, null, 2)
);
await api.disconnect();
throw error;
}
}

// Execute the function
getEncodedCallData()
.catch(console.error)
.finally(() => process.exit());
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div id="termynal" data-termynal>
<span data-ty><span class="file-path"></span>yarn hrmp-manipulator --target-para-id 3370 \</span>
<span data-ty>--parachain-ws-provider wss://moonbeam.public.blastapi.io \</span>
<span data-ty>--relay-ws-provider wss://polkadot-rpc.publicnode.com \</span>
<span data-ty>--hrmp-action accept</span>
<span data-ty>yarn run v1.22.22</span>
<span data-ty>warning ../../../package.json: No license field</span>
<span data-ty>$ ts-node 'scripts/hrmp-channel-manipulator.ts' --target-para-id 3370 --parachain-ws-provider wss://moonbeam.public.blastapi.io --relay-ws-provider wss://polkadot-rpc.publicnode.com --hrmp-action accept</span>
<span data-ty></span>
<span data-ty>Genesis hash is: 0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3</span>
<span data-ty>Polkadot</span>
<span data-ty>FeeAmount is: 10000000000</span>
<span data-ty>XCM Version is V4</span>
<span data-ty>Encoded Call Data for Tx is 0x6b09012a0d0000010401000100e40b5402000000000000000000000002286bee020004000100</span>
<span data-ty>✨ Done in 4.39s.</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div id="termynal" data-termynal>
<span data-ty><span class="file-path"></span>yarn hrmp-manipulator --target-para-id 3370 \</span>
<span data-ty>--parachain-ws-provider wss://moonbeam.public.blastapi.io \</span>
<span data-ty>--relay-ws-provider wss://polkadot-rpc.publicnode.com \</span>
<span data-ty>--max-capacity 1000 --max-message-size 102400 \</span>
<span data-ty>--hrmp-action open</span>
<span data-ty>yarn run v1.22.22</span>
<span data-ty>warning ../../../package.json: No license field</span>
<span data-ty>$ ts-node 'scripts/hrmp-channel-manipulator.ts' --target-para-id 3370 --parachain-ws-provider wss://moonbeam.public.blastapi.io --relay-ws-provider wss://polkadot-rpc.publicnode.com --max-capacity 1000 --max-message-size 102400 --hrmp-action open</span>
<span data-ty></span>
<span data-ty>Genesis hash is: 0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3</span>
<span data-ty>Polkadot</span>
<span data-ty>FeeAmount is: 10000000000</span>
<span data-ty>XCM Version is V4</span>
<span data-ty>Encoded Call Data for Tx is 0x6b09002a0d0000e803000000900100010401000100e40b5402000000000000000000000002286bee020004000100</span>
<span data-ty>✨ Done in 4.25s.</span>
</div>
Loading

0 comments on commit bd60f55

Please sign in to comment.