Skip to content

Commit

Permalink
Merge pull request #33 from CudoVentures/cudos-dev
Browse files Browse the repository at this point in the history
Cudos dev - cudos master sync
  • Loading branch information
SpaghettiOverload authored Aug 18, 2023
2 parents 4dc9b58 + 60f613a commit c96bf17
Show file tree
Hide file tree
Showing 12 changed files with 466 additions and 411 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# cudos-gravity-bridge-ui
UI for the gravity bridge
UI for the Cudos Bridge
3 changes: 1 addition & 2 deletions config/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ GRAVITY_MODULE_ADDRESS=
RPC=
API=
GAS_PRICE=
GAS=
STAKING=<url_for_staking_button_in_keplr_wallet>
BLOCK_EXPLORER=(http://<explorer-web-address>/transactions)

Expand All @@ -31,4 +30,4 @@ BRIDGE_CONTRACT_ADDRESS=

#ethereum variables
ETHEREUM_GAS=
ETHEREUM_RPC=
ETHEREUM_RPC=
6 changes: 2 additions & 4 deletions config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,12 @@ const envVariables = [
'RPC',
'API',
'GAS_PRICE',
'GAS',
'ERC20_CONTRACT_ADDRESS',
'BRIDGE_CONTRACT_ADDRESS',
'ETHEREUM_GAS',
'STAKING',
'BLOCK_EXPLORER',
'NETWORK_TYPE'
'NETWORK_TYPE',
];

if (process.env.NODE_ENV === 'production') {
Expand Down Expand Up @@ -207,7 +206,6 @@ const Config = {
RPC: process.env.RPC,
API: process.env.API,
GAS_PRICE: process.env.GAS_PRICE,
GAS: process.env.GAS,
STAKING: process.env.STAKING,
BLOCK_EXPLORER: process.env.BLOCK_EXPLORER,
},
Expand All @@ -219,7 +217,7 @@ const Config = {
ETHEREUM_GAS: process.env.ETHEREUM_GAS,
ETHEREUM_RPC: process.env.ETHEREUM_RPC,
ETHERSCAN_RINKEBY: 'https://rinkeby.etherscan.io/tx',
ETHERSCAN_MAINNET: 'https://etherscan.io/tx'
ETHERSCAN_MAINNET: 'https://etherscan.io/tx',
},
};

Expand Down
539 changes: 304 additions & 235 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"source-map-support": "^0.5.19",
"web3": "^1.4.0",
"web3-utils": "^1.4.0",
"winston": "^3.3.3"
"winston": "^3.3.3",
"cudosjs": "1.0.0"
},
"devDependencies": {
"@babel/cli": "^7.12.7",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ export default class CudosBridge extends CudosBridgeH {
context.payload.ctx.type = 'html';
context.payload.ctx.body = TEMPLATE.stream({
META: {
TITLE: 'Cudos Bridge',
DESC: '',
TITLE: 'CUDOS Bridge | Migrate tokens between Blockchains',
DESC: 'A tool for migrating your tokens between the Ethereum and the CUDOS blockchain. Allows ERC-20 holders to migrate to the native CUDOS token & stake.',
KEYWORDS: SV.KEYWORDS,
ROBOTS: 'noindex, nofollow',
ROBOTS: 'all',
PAGE_URL: `${Config.URL.GENERAL}${CudosBridge.URL}`,
},
CSS: {
Expand Down
7 changes: 7 additions & 0 deletions src/frontend/pages/general/cudos-bridge.marko
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@ import pageLoading from './../common/page-loading.marko'
<script async src=`${input.Config.URL.Resources.General.VIEW}/CudosBridgePage/bundle.js`></script>
<link rel="stylesheet" href=`${input.Config.URL.Resources.General.VIEW}/CudosBridgePage/bundle.css` />
<style>$!{input.CSS.PAGE_LOADING}</style>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-NWBZN9R');</script>
<!-- End Google Tag Manager -->
</head>

<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NWBZN9R"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<div class="ReactEntryPoint"></div>
<${pageLoading} ...input/>
</body>
Expand Down
182 changes: 87 additions & 95 deletions src/frontend/resources/common/js/models/ledgers/KeplrLedger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@ import Ledger from './Ledger';
import { makeObservable, observable } from 'mobx';
import S from '../../utilities/Main';
import Config from '../../../../../../../builds/dev-generated/Config';
import CosmosNetworkH from './CosmosNetworkH';
import { MsgSendToEth, MsgRequestBatch } from '../../cosmos/codec/gravity/gravity/v1/msgs';
import { assertIsBroadcastTxSuccess, SigningStargateClient, defaultRegistryTypes, assertIsDeliverTxSuccess } from '@cosmjs/stargate';
import { EncodeObject, Registry } from '@cosmjs/proto-signing';
import { AccountData, Coin, coin, OfflineSigner, StargateClient, CudosNetworkConsts, StdFee } from 'cudosjs';
import { SigningStargateClient, assertIsDeliverTxSuccess, checkValidAddress, estimateFee } from 'cudosjs';
import { EncodeObject } from 'cudosjs';
import BigNumber from 'bignumber.js';
import { GasPrice } from '@cosmjs/launchpad';
import { Uint53 } from "@cosmjs/math";
import { coins } from "@cosmjs/amino";
import { GasPrice } from 'cudosjs';

declare global {
interface Window {
keplr: any
getOfflineSignerAuto: any
meta: any
}
}

export default class KeplrLedger implements Ledger {
@observable connected: number;
Expand All @@ -19,6 +24,8 @@ export default class KeplrLedger implements Ledger {
@observable bridgeFee: BigNumber;
@observable chainID: string;
@observable rpcEndpoint: string;
@observable txNonce: string;
queryClient: StargateClient

static NETWORK_NAME = 'Cudos';

Expand Down Expand Up @@ -47,14 +54,14 @@ export default class KeplrLedger implements Ledger {
// Staking coin information
stakeCurrency: {
// Coin denomination to be displayed to the user.
coinDenom: CosmosNetworkH.CURRENCY_DISPLAY_NAME,
coinDenom: CudosNetworkConsts.CURRENCY_DISPLAY_NAME,
// Actual denom (i.e. uatom, uscrt) used by the blockchain.
coinMinimalDenom: CosmosNetworkH.CURRENCY_DENOM,
coinMinimalDenom: CudosNetworkConsts.CURRENCY_DENOM,
// # of decimal points to convert minimal denomination to user-facing denomination.
coinDecimals: CosmosNetworkH.CURRENCY_DECIMALS,
coinDecimals: CudosNetworkConsts.CURRENCY_DECIMALS,
// (Optional) Keplr can show the fiat value of the coin if a coingecko id is provided.
// You can get id from https://api.coingecko.com/api/v3/coins/list if it is listed.
coinGeckoId: CosmosNetworkH.CURRENCY_COINGECKO_ID,
coinGeckoId: CudosNetworkConsts.CURRENCY_COINGECKO_ID,
},
// (Optional) If you have a wallet webpage used to stake the coin then provide the url to the website in `walletUrlForStaking`.
// The 'stake' button in Keplr extension will link to the webpage.
Expand All @@ -63,36 +70,36 @@ export default class KeplrLedger implements Ledger {
bip44: {
// You can only set the coin type of BIP44.
// 'Purpose' is fixed to 44.
coinType: CosmosNetworkH.LEDGER_COIN_TYPE,
coinType: CudosNetworkConsts.LEDGER_COIN_TYPE,
},
bech32Config: {
bech32PrefixAccAddr: CosmosNetworkH.BECH32_PREFIX_ACC_ADDR,
bech32PrefixAccPub: CosmosNetworkH.BECH32_PREFIX_ACC_PUB,
bech32PrefixValAddr: CosmosNetworkH.BECH32_PREFIX_VAL_ADDR,
bech32PrefixValPub: CosmosNetworkH.BECH32_PREFIX_VAL_PUB,
bech32PrefixConsAddr: CosmosNetworkH.BECH32_PREFIX_CONS_ADDR,
bech32PrefixConsPub: CosmosNetworkH.BECH32_PREFIX_CONS_PUB,
bech32PrefixAccAddr: CudosNetworkConsts.BECH32_PREFIX_ACC_ADDR,
bech32PrefixAccPub: CudosNetworkConsts.BECH32_PREFIX_ACC_PUB,
bech32PrefixValAddr: CudosNetworkConsts.BECH32_PREFIX_VAL_ADDR,
bech32PrefixValPub: CudosNetworkConsts.BECH32_PREFIX_VAL_PUB,
bech32PrefixConsAddr: CudosNetworkConsts.BECH32_PREFIX_CONS_ADDR,
bech32PrefixConsPub: CudosNetworkConsts.BECH32_PREFIX_CONS_PUB,
},
// List of all coin/tokens used in this chain.
currencies: [{
// Coin denomination to be displayed to the user.
coinDenom: CosmosNetworkH.CURRENCY_DISPLAY_NAME,
coinDenom: CudosNetworkConsts.CURRENCY_DISPLAY_NAME,
// Actual denom (i.e. uatom, uscrt) used by the blockchain.
coinMinimalDenom: CosmosNetworkH.CURRENCY_DENOM,
coinMinimalDenom: CudosNetworkConsts.CURRENCY_DENOM,
// # of decimal points to convert minimal denomination to user-facing denomination.
coinDecimals: CosmosNetworkH.CURRENCY_DECIMALS,
coinDecimals: CudosNetworkConsts.CURRENCY_DECIMALS,
// (Optional) Keplr can show the fiat value of the coin if a coingecko id is provided.
// You can get id from https://api.coingecko.com/api/v3/coins/list if it is listed.
coinGeckoId: CosmosNetworkH.CURRENCY_COINGECKO_ID,
coinGeckoId: CudosNetworkConsts.CURRENCY_COINGECKO_ID,
}],
// List of coin/tokens used as a fee token in this chain.
feeCurrencies: [{
// Coin denomination to be displayed to the user.
coinDenom: CosmosNetworkH.CURRENCY_DISPLAY_NAME,
coinDenom: CudosNetworkConsts.CURRENCY_DISPLAY_NAME,
// Actual denom (i.e. uatom, uscrt) used by the blockchain.
coinMinimalDenom: CosmosNetworkH.CURRENCY_DENOM,
coinMinimalDenom: CudosNetworkConsts.CURRENCY_DENOM,
// # of decimal points to convert minimal denomination to user-facing denomination.
coinDecimals: CosmosNetworkH.CURRENCY_DECIMALS,
coinDecimals: CudosNetworkConsts.CURRENCY_DECIMALS,
// (Optional) Keplr can show the fiat value of the coin if a coingecko id is provided.
// You can get id from https://api.coingecko.com/api/v3/coins/list if it is listed.
// coinGeckoId: Meteor.settings.public.coingeckoId,
Expand All @@ -102,7 +109,7 @@ export default class KeplrLedger implements Ledger {
// Ideally, it is recommended to be the same with BIP44 path's coin type.
// However, some early chains may choose to use the Cosmos Hub BIP44 path of '118'.
// So, this is separated to support such chains.
coinType: CosmosNetworkH.LEDGER_COIN_TYPE,
coinType: CudosNetworkConsts.LEDGER_COIN_TYPE,
// (Optional) This is used to set the fee of the transaction.
// If this field is not provided, Keplr extension will set the default gas price as (low: 0.01, average: 0.025, high: 0.04).
// Currently, Keplr doesn't support dynamic calculation of the gas prices based on on-chain data.
Expand All @@ -127,12 +134,15 @@ export default class KeplrLedger implements Ledger {
window.keplr.defaultOptions = {
sign: {
preferNoSetFee: true,
}
};
const offlineSigner = window.getOfflineSigner(Config.CUDOS_NETWORK.CHAIN_ID);
this.account = (await offlineSigner.getAccounts())[0].address;
},
};

const [_, account] = await this.GetKeplrSignerAndAccount()
this.account = account.address;

// Instantiating the queryClient just once - since it's not tied to a particular account.
// This is more performant
this.queryClient = await StargateClient.connect(Config.CUDOS_NETWORK.RPC)
this.connected = S.INT_TRUE;
} catch (error) {
if (!window.keplr) {
Expand All @@ -145,74 +155,47 @@ export default class KeplrLedger implements Ledger {
}

async disconnect(): Promise<void> {
return new Promise < void >((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
resolve();
});
}

calculateFee = (gasLimit: number, { denom, amount: gasPriceAmount }) => {
const amount = Math.ceil(gasPriceAmount.multiply(new Uint53(gasLimit)).toFloatApproximation());
return {
amount: coins(amount.toString(), denom),
gas: gasLimit.toString(),
};
};

EstimateFee = async (client: SigningStargateClient, gasPrice: GasPrice, signerAddress: string, messages: readonly EncodeObject[], memo = "") => {
const multiplier = 1.3;
const gasEstimation = await client.simulate(signerAddress, messages, memo);
return this.calculateFee(Math.round(gasEstimation * multiplier), gasPrice);
};

GetKeplrClientAndAccount = async () => {
const offlineSigner = window.getOfflineSigner(this.chainID);
const myRegistry = new Registry([
...defaultRegistryTypes,
[CosmosNetworkH.MESSAGE_TYPE_URL, MsgSendToEth],
]);
const client = await SigningStargateClient.connectWithSigner(this.rpcEndpoint, offlineSigner, {
registry: myRegistry,
});
GetKeplrSignerAndAccount = async (): Promise<[OfflineSigner, AccountData]> => {
const offlineSigner = await window.getOfflineSignerAuto(this.chainID);
const account = (await offlineSigner.getAccounts())[0];
return [client, account];
return [offlineSigner, account]
}

GetKeplrSigningClient = async (offlineSigner: OfflineSigner): Promise<SigningStargateClient> => {
const client = await SigningStargateClient.connectWithSigner(this.rpcEndpoint, offlineSigner);
return client
}

async send(amount: BigNumber, destiantionAddress: string): Promise<void> {
const stringifiedAmount = amount.multipliedBy(CosmosNetworkH.CURRENCY_1_CUDO).toString(10);
async send(amount: BigNumber, destinationAddress: string): Promise<void> {
await window.keplr.enable(this.chainID);
const [client, account] = await this.GetKeplrClientAndAccount();

const msgSend = [{
typeUrl: CosmosNetworkH.MESSAGE_TYPE_URL,
value: {
sender: account.address,
ethDest: destiantionAddress,
amount: {
amount: stringifiedAmount,
denom: CosmosNetworkH.CURRENCY_DENOM,
},
bridgeFee: {
amount: this.bridgeFee.toString(10),
denom: CosmosNetworkH.CURRENCY_DENOM,
},
},
}];
const [offlineSigner, account] = await this.GetKeplrSignerAndAccount()
const client = await this.GetKeplrSigningClient(offlineSigner);

this.walletError = null;
try {
this.walletError = null;
const msgFee = await this.EstimateFee(
client,
GasPrice.fromString(`${Config.CUDOS_NETWORK.GAS_PRICE}acudos`),
account.address,
msgSend,
'Fee Estimation Message',
);

const result = await client.signAndBroadcast(
const coinAmount: Coin = coin(
amount.multipliedBy(CudosNetworkConsts.CURRENCY_1_CUDO).toString(10),
CudosNetworkConsts.CURRENCY_DENOM,
)
const bridgeFeeAmount: Coin = coin(
this.bridgeFee.toString(10),
CudosNetworkConsts.CURRENCY_DENOM,
)
const gasPrice: GasPrice = GasPrice.fromString(`${Config.CUDOS_NETWORK.GAS_PRICE}acudos`)

const result = await client.gravitySendToEth(
account.address,
msgSend,
msgFee,
'Sent with CUDOS Gravity Bridge',
destinationAddress,
coinAmount,
bridgeFeeAmount,
gasPrice,
'Sent with CUDOS Bridge',
);

this.txHash = result.transactionHash;
Expand All @@ -222,30 +205,39 @@ export default class KeplrLedger implements Ledger {
}
}

async EstimateFee(client: SigningStargateClient, sender: string, messages: EncodeObject[], gasPrice: GasPrice,
memo?: string, gasMultiplier?: number): Promise<StdFee> {
const fee = await estimateFee(client, sender, messages, gasPrice, gasMultiplier, memo)
return fee
}

async getBalance(): Promise<BigNumber> {
this.walletError = null;
try {
const offlineSigner = window.getOfflineSigner(Config.CUDOS_NETWORK.CHAIN_ID);
const account = (await offlineSigner.getAccounts())[0];

const url = `${Config.CUDOS_NETWORK.API}/cosmos/bank/v1beta1/balances/${account.address}/by_denom?denom=${CosmosNetworkH.CURRENCY_DENOM}`;
const amount = (await (await fetch(url)).json()).balance.amount;
const [_, account] = await this.GetKeplrSignerAndAccount()
const balance: Coin = await this.queryClient.getBalance(account.address, CudosNetworkConsts.CURRENCY_DENOM)

return new BigNumber(amount).div(CosmosNetworkH.CURRENCY_1_CUDO);
return new BigNumber(balance.amount).div(CudosNetworkConsts.CURRENCY_1_CUDO);
} catch (e) {
this.walletError = 'Failed to get balance!'
}
}

setBridgeFee(bridgeFee: BigNumber) {
if (bridgeFee.lt((new BigNumber(1)).dividedBy(CosmosNetworkH.CURRENCY_1_CUDO))) {
if (bridgeFee.lt((new BigNumber(1)).dividedBy(CudosNetworkConsts.CURRENCY_1_CUDO))) {
return;
}

this.bridgeFee = bridgeFee;
}

isAddressValid(address: string): boolean {
return address.startsWith(CosmosNetworkH.BECH32_PREFIX_ACC_ADDR) && address.length === CosmosNetworkH.BECH32_ACC_ADDR_LENGTH;
try {
checkValidAddress(address)
return true
} catch {
this.walletError = 'Invalid Cosmos Address'
return false
}
}
}
Loading

0 comments on commit c96bf17

Please sign in to comment.