├── .clippy.toml ├── .dockerignore ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── ci-stone-android.yml │ ├── ci-stone-ios.yml │ ├── ci-stone-tag.yml │ ├── ci.yml │ ├── diesel.yml │ ├── docker.yml │ ├── lint.yml │ ├── release-stone-android.yml │ └── release-stone-ios.yml ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── .windsurf └── rules │ ├── code-style-guide.md │ └── gemstone-crate.md ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── README.md ├── Settings.yaml ├── apps ├── api │ ├── Cargo.toml │ └── src │ │ ├── assets │ │ ├── cilent.rs │ │ └── mod.rs │ │ ├── config │ │ ├── client.rs │ │ └── mod.rs │ │ ├── devices │ │ ├── client.rs │ │ └── mod.rs │ │ ├── fiat │ │ └── mod.rs │ │ ├── main.rs │ │ ├── markets │ │ └── mod.rs │ │ ├── metrics │ │ ├── client.rs │ │ └── mod.rs │ │ ├── model.rs │ │ ├── name.rs │ │ ├── nft │ │ ├── client.rs │ │ └── mod.rs │ │ ├── parser │ │ ├── client.rs │ │ └── mod.rs │ │ ├── price_alerts │ │ └── mod.rs │ │ ├── prices │ │ └── mod.rs │ │ ├── scan │ │ ├── client.rs │ │ ├── mod.rs │ │ └── providers.rs │ │ ├── status.rs │ │ ├── subscriptions │ │ ├── client.rs │ │ └── mod.rs │ │ ├── swap │ │ ├── client.rs │ │ └── mod.rs │ │ ├── transactions │ │ ├── client.rs │ │ └── mod.rs │ │ └── websocket_prices │ │ ├── client.rs │ │ ├── mod.rs │ │ └── stream.rs ├── daemon │ ├── Cargo.toml │ └── src │ │ ├── alerter │ │ ├── mod.rs │ │ └── price_alerts_sender.rs │ │ ├── assets │ │ ├── asset_updater.rs │ │ └── mod.rs │ │ ├── device │ │ ├── device_updater.rs │ │ └── mod.rs │ │ ├── fiat │ │ ├── fiat_assets_updater.rs │ │ └── mod.rs │ │ ├── main.rs │ │ ├── model.rs │ │ ├── nft │ │ ├── collections_image_uploader.rs │ │ ├── collections_updater.rs │ │ ├── image_uploader.rs │ │ ├── mod.rs │ │ ├── nft_collection_asset_consumer.rs │ │ └── nft_collection_consumer.rs │ │ ├── notifications │ │ ├── mod.rs │ │ └── notifications_consumer.rs │ │ ├── pricer │ │ ├── charts_updater.rs │ │ ├── markets_updater.rs │ │ ├── mod.rs │ │ ├── price_asset_updater.rs │ │ └── price_updater.rs │ │ ├── search │ │ ├── assets_index_updater.rs │ │ └── mod.rs │ │ ├── transaction │ │ ├── mod.rs │ │ └── transaction_updater.rs │ │ └── version │ │ ├── mod.rs │ │ ├── model.rs │ │ └── version_updater.rs ├── parser │ ├── Cargo.toml │ └── src │ │ ├── consumers │ │ ├── assets_addresses_consumer.rs │ │ ├── fetch_assets_addresses_consumer.rs │ │ ├── fetch_assets_consumer.rs │ │ ├── fetch_blocks_consumer.rs │ │ ├── mod.rs │ │ ├── transactions_consumer.rs │ │ └── transactions_consumer_config.rs │ │ ├── main.rs │ │ ├── parser.rs │ │ ├── parser_options.rs │ │ ├── parser_proxy.rs │ │ └── pusher │ │ ├── mod.rs │ │ └── pusher.rs └── setup │ ├── Cargo.toml │ └── src │ └── main.rs ├── bin ├── generate │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── img-downloader │ ├── Cargo.toml │ └── src │ │ ├── cli_args.rs │ │ └── main.rs ├── swapper-dump │ ├── Cargo.toml │ └── src │ │ └── main.rs └── uniffi-bindgen │ ├── Cargo.toml │ └── src │ └── main.rs ├── crates ├── alien_provider │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── api_connector │ ├── Cargo.toml │ └── src │ │ ├── app_store_client │ │ ├── client.rs │ │ ├── mod.rs │ │ └── models.rs │ │ ├── lib.rs │ │ └── pusher │ │ ├── client.rs │ │ ├── mod.rs │ │ └── model.rs ├── blockchain │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── algorand │ │ └── algorand_model.rs │ │ ├── aptos │ │ └── models │ │ │ └── aptos_model.rs │ │ ├── bitcoin │ │ └── models │ │ │ ├── bitcoin_account.rs │ │ │ ├── bitcoin_block.rs │ │ │ ├── bitcoin_fee.rs │ │ │ ├── bitcoin_node_info.rs │ │ │ ├── bitcoin_transaction.rs │ │ │ └── bitcoin_utxo.rs │ │ ├── cardano │ │ └── cardano_model.rs │ │ ├── cosmos │ │ └── models │ │ │ ├── cosmos_account.rs │ │ │ ├── cosmos_balance.rs │ │ │ ├── cosmos_node_info.rs │ │ │ ├── cosmos_staking.rs │ │ │ ├── cosmos_syncing.rs │ │ │ └── cosmos_transaction.rs │ │ ├── ethereum │ │ └── models │ │ │ └── ethereum_transaction.rs │ │ ├── graphql │ │ └── graphql_model.rs │ │ ├── lib.rs │ │ ├── near │ │ └── models │ │ │ └── account.rs │ │ ├── polkadot │ │ └── polkadot_model.rs │ │ ├── solana │ │ └── models │ │ │ ├── solana_balance.rs │ │ │ ├── solana_blockhash.rs │ │ │ ├── solana_prioritization_fee.rs │ │ │ ├── solana_stake.rs │ │ │ ├── solana_token_account.rs │ │ │ ├── solana_transaction.rs │ │ │ └── solana_value.rs │ │ ├── stellar │ │ └── stellar_model.rs │ │ ├── sui │ │ └── models │ │ │ ├── sui_coin_balance.rs │ │ │ └── sui_pay.rs │ │ ├── ton │ │ └── models │ │ │ ├── ton_broadcast_transaction.rs │ │ │ ├── ton_chaininfo.rs │ │ │ ├── ton_fee.rs │ │ │ ├── ton_transaction.rs │ │ │ └── ton_wallet_info.rs │ │ ├── tron │ │ └── models │ │ │ ├── tron_account.rs │ │ │ ├── tron_block.rs │ │ │ ├── tron_chain_parameters.rs │ │ │ ├── tron_smart_contract.rs │ │ │ └── tron_transaction.rs │ │ └── xrp │ │ └── models │ │ └── xrp_account.rs ├── cacher │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── chain_primitives │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── coingecko │ ├── Cargo.toml │ └── src │ │ ├── client.rs │ │ ├── lib.rs │ │ ├── mapper.rs │ │ └── model.rs ├── fiat │ ├── Cargo.toml │ └── src │ │ ├── client.rs │ │ ├── error.rs │ │ ├── ip_check_client.rs │ │ ├── lib.rs │ │ ├── model.rs │ │ ├── provider.rs │ │ └── providers │ │ ├── banxa │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── provider.rs │ │ ├── mercuryo │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── provider.rs │ │ ├── mod.rs │ │ ├── moonpay │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── provider.rs │ │ ├── ramp │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── provider.rs │ │ └── transak │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── provider.rs ├── gem_algorand │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ └── model.rs ├── gem_aptos │ ├── Cargo.toml │ └── src │ │ ├── constants.rs │ │ ├── lib.rs │ │ ├── model.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── mapper.rs │ │ └── mod.rs ├── gem_bitcoin │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ └── model.rs ├── gem_bsc │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── stake_hub.rs ├── gem_cardano │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ └── model.rs ├── gem_chain_rpc │ ├── Cargo.toml │ ├── src │ │ ├── algorand.rs │ │ ├── aptos.rs │ │ ├── bitcoin.rs │ │ ├── cardano.rs │ │ ├── cosmos.rs │ │ ├── ethereum.rs │ │ ├── lib.rs │ │ ├── near.rs │ │ ├── polkadot.rs │ │ ├── solana.rs │ │ ├── stellar.rs │ │ ├── sui.rs │ │ ├── ton.rs │ │ ├── tron.rs │ │ └── xrp.rs │ └── tests │ │ └── integration_test.rs ├── gem_cosmos │ ├── Cargo.toml │ └── src │ │ ├── converter.rs │ │ ├── lib.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ └── model.rs ├── gem_evm │ ├── Cargo.toml │ └── src │ │ ├── across │ │ ├── contracts │ │ │ ├── config_store.rs │ │ │ ├── hub_pool.rs │ │ │ ├── mod.rs │ │ │ ├── multicall_handler.rs │ │ │ └── spoke_pool.rs │ │ ├── deployment.rs │ │ ├── fees │ │ │ ├── lp.rs │ │ │ ├── mod.rs │ │ │ └── relayer.rs │ │ └── mod.rs │ │ ├── address.rs │ │ ├── chainlink │ │ ├── contract.rs │ │ └── mod.rs │ │ ├── eip712.rs │ │ ├── erc20.rs │ │ ├── erc2612.rs │ │ ├── ether_conv.rs │ │ ├── jsonrpc.rs │ │ ├── lib.rs │ │ ├── lido.rs │ │ ├── multicall3.rs │ │ ├── permit2.rs │ │ ├── rpc │ │ ├── alchemy │ │ │ ├── client.rs │ │ │ ├── mod.rs │ │ │ └── model.rs │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ ├── swap_mapper.rs │ │ └── test │ │ │ ├── v3_eth_token_tx.json │ │ │ ├── v3_eth_token_tx_receipt.json │ │ │ ├── v3_pol_usdt_tx.json │ │ │ ├── v3_pol_usdt_tx_receipt.json │ │ │ ├── v3_token_eth_tx.json │ │ │ ├── v3_token_eth_tx_receipt.json │ │ │ ├── v3_usdc_paxg_receipt.json │ │ │ ├── v3_usdc_paxg_tx.json │ │ │ ├── v4_eth_dai_tx.json │ │ │ ├── v4_eth_dai_tx_receipt.json │ │ │ ├── v4_usdc_eth_tx.json │ │ │ └── v4_usdc_eth_tx_receipt.json │ │ ├── test │ │ ├── 1inch_permit.json │ │ └── uniswap_permit2.json │ │ ├── thorchain │ │ ├── contracts.rs │ │ └── mod.rs │ │ ├── typeshare.rs │ │ ├── uniswap │ │ ├── actions.rs │ │ ├── command.rs │ │ ├── contracts │ │ │ ├── mod.rs │ │ │ ├── v3.rs │ │ │ └── v4.rs │ │ ├── deployment │ │ │ ├── mod.rs │ │ │ ├── v3.rs │ │ │ └── v4.rs │ │ ├── mod.rs │ │ └── path.rs │ │ └── weth.rs ├── gem_hash │ ├── Cargo.toml │ └── src │ │ ├── keccak.rs │ │ └── lib.rs ├── gem_near │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ └── model.rs ├── gem_polkadot │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ └── model.rs ├── gem_solana │ ├── Cargo.toml │ ├── src │ │ ├── hash.rs │ │ ├── jsonrpc.rs │ │ ├── lib.rs │ │ ├── metaplex │ │ │ ├── collection.rs │ │ │ ├── data.rs │ │ │ ├── metadata.rs │ │ │ ├── mod.rs │ │ │ └── uses.rs │ │ ├── model.rs │ │ ├── pubkey.rs │ │ ├── rpc │ │ │ ├── client.rs │ │ │ ├── mapper.rs │ │ │ └── mod.rs │ │ └── typeshare │ │ │ ├── mod.rs │ │ │ ├── solana_balance.rs │ │ │ ├── solana_blockhash.rs │ │ │ ├── solana_prioritization_fee.rs │ │ │ ├── solana_stake.rs │ │ │ ├── solana_token_account.rs │ │ │ ├── solana_transaction.rs │ │ │ └── solana_value.rs │ └── testdata │ │ ├── pyusd_mint.json │ │ ├── swap_sol_to_token.json │ │ ├── swap_token_to_sol.json │ │ ├── swap_token_to_token.json │ │ └── usdc_mint.json ├── gem_stellar │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ └── model.rs ├── gem_sui │ ├── Cargo.toml │ ├── src │ │ ├── jsonrpc.rs │ │ ├── lib.rs │ │ ├── model.rs │ │ ├── object_id.rs │ │ ├── rpc │ │ │ ├── client.rs │ │ │ ├── constants.rs │ │ │ ├── mapper.rs │ │ │ ├── mod.rs │ │ │ └── model.rs │ │ ├── stake.rs │ │ ├── transfer.rs │ │ └── tx.rs │ └── testdata │ │ ├── swap_sui_to_token.json │ │ └── swap_token_to_token.json ├── gem_ton │ ├── Cargo.toml │ └── src │ │ ├── address.rs │ │ ├── address │ │ └── error.rs │ │ ├── cell.rs │ │ ├── cell │ │ ├── bag_of_cells.rs │ │ ├── bit_string.rs │ │ ├── builder.rs │ │ ├── dict_loader.rs │ │ ├── error.rs │ │ ├── parser.rs │ │ ├── raw.rs │ │ ├── slice.rs │ │ └── util.rs │ │ ├── lib.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── model_rpc.rs ├── gem_tron │ ├── Cargo.toml │ └── src │ │ ├── address.rs │ │ ├── lib.rs │ │ └── rpc │ │ ├── client.rs │ │ ├── constants.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ └── model.rs ├── gem_xrp │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ ├── rpc │ │ ├── client.rs │ │ ├── constants.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ └── model.rs │ │ └── typeshare.rs ├── job_runner │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── localizer │ ├── Cargo.toml │ ├── i18n.toml │ ├── i18n │ │ ├── ar │ │ │ └── localizer.ftl │ │ ├── de │ │ │ └── localizer.ftl │ │ ├── en │ │ │ └── localizer.ftl │ │ ├── es │ │ │ └── localizer.ftl │ │ ├── fa │ │ │ └── localizer.ftl │ │ ├── fr │ │ │ └── localizer.ftl │ │ ├── he │ │ │ └── localizer.ftl │ │ ├── hi │ │ │ └── localizer.ftl │ │ ├── id │ │ │ └── localizer.ftl │ │ ├── it │ │ │ └── localizer.ftl │ │ ├── ja │ │ │ └── localizer.ftl │ │ ├── ko │ │ │ └── localizer.ftl │ │ ├── pl │ │ │ └── localizer.ftl │ │ ├── pt-BR │ │ │ └── localizer.ftl │ │ ├── ru │ │ │ └── localizer.ftl │ │ ├── th │ │ │ └── localizer.ftl │ │ ├── tr │ │ │ └── localizer.ftl │ │ ├── uk │ │ │ └── localizer.ftl │ │ ├── vi │ │ │ └── localizer.ftl │ │ ├── zh-Hans │ │ │ └── localizer.ftl │ │ └── zh-Hant │ │ │ └── localizer.ftl │ ├── src │ │ └── lib.rs │ └── tests │ │ └── localizer.rs ├── name_resolver │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── aptos.rs │ │ ├── base │ │ │ ├── contract.rs │ │ │ ├── mod.rs │ │ │ └── provider.rs │ │ ├── client.rs │ │ ├── codec │ │ │ └── mod.rs │ │ ├── did.rs │ │ ├── ens │ │ │ ├── client.rs │ │ │ ├── contract.rs │ │ │ ├── mod.rs │ │ │ ├── normalizer.rs │ │ │ └── provider.rs │ │ ├── eths.rs │ │ ├── hyperliquid │ │ │ ├── contracts.rs │ │ │ ├── mod.rs │ │ │ ├── provider.rs │ │ │ └── record.rs │ │ ├── icns.rs │ │ ├── injective.rs │ │ ├── lens.rs │ │ ├── lib.rs │ │ ├── sns.rs │ │ ├── spaceid.rs │ │ ├── suins.rs │ │ ├── ton.rs │ │ ├── ton_codec.rs │ │ └── ud.rs │ └── tests │ │ └── integration_test.rs ├── nft │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ ├── magiceden │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── provider.rs │ │ ├── nftscan │ │ ├── client.rs │ │ ├── evm │ │ │ ├── mapper.rs │ │ │ ├── mod.rs │ │ │ └── model.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ ├── provider.rs │ │ ├── solana │ │ │ └── mod.rs │ │ └── ton │ │ │ └── mod.rs │ │ └── opensea │ │ ├── client.rs │ │ ├── mapper.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── provider.rs ├── number_formatter │ ├── Cargo.toml │ └── src │ │ ├── big_number_formatter.rs │ │ ├── lib.rs │ │ └── number_formatter.rs ├── pricer │ ├── Cargo.toml │ └── src │ │ ├── chart_client.rs │ │ ├── lib.rs │ │ ├── markets_client.rs │ │ ├── price_alert_client.rs │ │ └── price_client.rs ├── pricer_dex │ ├── Cargo.toml │ ├── src │ │ ├── lib.rs │ │ └── pyth │ │ │ ├── client.rs │ │ │ ├── decoder.rs │ │ │ ├── mapper.rs │ │ │ ├── mod.rs │ │ │ ├── model.rs │ │ │ └── provider.rs │ └── tests │ │ └── integration_test.rs ├── primitives │ ├── Cargo.toml │ └── src │ │ ├── account.rs │ │ ├── address_formatter.rs │ │ ├── asset.rs │ │ ├── asset_address.rs │ │ ├── asset_balance.rs │ │ ├── asset_constants.rs │ │ ├── asset_data.rs │ │ ├── asset_details.rs │ │ ├── asset_id.rs │ │ ├── asset_metadata.rs │ │ ├── asset_order.rs │ │ ├── asset_price.rs │ │ ├── asset_price_info.rs │ │ ├── asset_score.rs │ │ ├── asset_type.rs │ │ ├── balance.rs │ │ ├── balance_type.rs │ │ ├── banner.rs │ │ ├── block_explorer.rs │ │ ├── chain.rs │ │ ├── chain_address.rs │ │ ├── chain_bitcoin.rs │ │ ├── chain_cosmos.rs │ │ ├── chain_evm.rs │ │ ├── chain_stake.rs │ │ ├── chain_type.rs │ │ ├── config.rs │ │ ├── currency.rs │ │ ├── delegation.rs │ │ ├── device.rs │ │ ├── diff.rs │ │ ├── encoding_type.rs │ │ ├── explorers │ │ ├── algorand.rs │ │ ├── aptos.rs │ │ ├── blockchair.rs │ │ ├── blockscout.rs │ │ ├── blocksec.rs │ │ ├── cardano.rs │ │ ├── chainflip.rs │ │ ├── etherscan.rs │ │ ├── hyperliquid.rs │ │ ├── mantle.rs │ │ ├── mayanscan.rs │ │ ├── mempool.rs │ │ ├── mintscan.rs │ │ ├── mod.rs │ │ ├── near.rs │ │ ├── okx.rs │ │ ├── relay.rs │ │ ├── routescan.rs │ │ ├── scope.rs │ │ ├── socketscan.rs │ │ ├── solana.rs │ │ ├── subscan.rs │ │ ├── sui.rs │ │ ├── thorchain.rs │ │ ├── tonscan.rs │ │ ├── tonviewer.rs │ │ ├── tronscan.rs │ │ ├── xrpscan.rs │ │ └── zksync.rs │ │ ├── fee.rs │ │ ├── fiat_assets.rs │ │ ├── fiat_provider.rs │ │ ├── fiat_quote.rs │ │ ├── fiat_quote_request.rs │ │ ├── fiat_rate.rs │ │ ├── fiat_transaction.rs │ │ ├── image_formatter.rs │ │ ├── json_rpc.rs │ │ ├── lib.rs │ │ ├── link_type.rs │ │ ├── markets.rs │ │ ├── name.rs │ │ ├── nft.rs │ │ ├── node.rs │ │ ├── node_config.rs │ │ ├── payment_decoder │ │ ├── decoder.rs │ │ ├── erc681.rs │ │ ├── mod.rs │ │ ├── solana_pay.rs │ │ └── ton_pay.rs │ │ ├── platform.rs │ │ ├── price.rs │ │ ├── price_alert.rs │ │ ├── push_notification.rs │ │ ├── response.rs │ │ ├── scan.rs │ │ ├── solana_pay.rs │ │ ├── solana_token_program.rs │ │ ├── subscription.rs │ │ ├── swap │ │ ├── mod.rs │ │ ├── mode.rs │ │ ├── quote.rs │ │ └── slippage.rs │ │ ├── swap_provider.rs │ │ ├── tag.rs │ │ ├── transaction.rs │ │ ├── transaction_direction.rs │ │ ├── transaction_extended.rs │ │ ├── transaction_id.rs │ │ ├── transaction_metadata_types.rs │ │ ├── transaction_state.rs │ │ ├── transaction_type.rs │ │ ├── transaction_utxo.rs │ │ ├── utxo.rs │ │ ├── validator.rs │ │ ├── wallet.rs │ │ ├── wallet_connect.rs │ │ ├── wallet_connector.rs │ │ └── websocket.rs ├── search_index │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── model.rs ├── security_goplus │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ ├── models.rs │ │ └── provider.rs ├── security_hashdit │ ├── Cargo.toml │ └── src │ │ ├── api.rs │ │ ├── lib.rs │ │ ├── models.rs │ │ └── provider.rs ├── security_provider │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── serde_serializers │ ├── Cargo.toml │ └── src │ │ ├── bigint.rs │ │ ├── biguint.rs │ │ ├── f64.rs │ │ ├── lib.rs │ │ └── u64.rs ├── settings │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── settings_chain │ ├── Cargo.toml │ └── src │ │ ├── chain_providers.rs │ │ ├── lib.rs │ │ └── provider_config.rs ├── storage │ ├── Cargo.toml │ └── src │ │ ├── clickhouse │ │ ├── clickhouse_database.rs │ │ ├── clickhouse_migration.sql │ │ └── mod.rs │ │ ├── database │ │ ├── assets.rs │ │ ├── assets_addresses.rs │ │ ├── assets_links.rs │ │ ├── assets_types.rs │ │ ├── devices.rs │ │ ├── fiat.rs │ │ ├── link_types.rs │ │ ├── mod.rs │ │ ├── nft.rs │ │ ├── nodes.rs │ │ ├── parser_state.rs │ │ ├── price_alerts.rs │ │ ├── prices.rs │ │ ├── releases.rs │ │ ├── scan_addresses.rs │ │ ├── subscriptions.rs │ │ └── tag.rs │ │ ├── lib.rs │ │ ├── migrations │ │ ├── 00000000000000_diesel_initial_setup │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-07-18-212125_chains │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-07-21-201556_assets_types │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-07-22-205905_assets │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-07-23-195320_nodes │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-07-23-215138_fiat_providers │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-07-24-215139_fiat_assets │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-07-28-193518_prices │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-07-28-193519_prices_assets │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-07-29-040300_fiat_rates │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-09-03-192926_devices │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-09-03-220931_parser │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-09-04-220616_subscriptions │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-09-05-011115_transactions │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-10-18-184745_scan_address │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2023-11-03-004112_transactions_addresses │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2024-03-29-030159_fiat_transactions │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2024-05-08-002620_subscriptions_addresses_exclude │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2024-09-12-202145_price_alerts │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2024-09-24-204906_releases │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2025-01-13-170539_link_types │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2025-01-14-162733_nft_collections │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2025-01-14-191614_nft_assets │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2025-01-22-173935_assets_links │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── 2025-03-12-161335_assets_tags │ │ │ ├── down.sql │ │ │ └── up.sql │ │ └── 2025-06-05-015957_assets_addresses │ │ │ ├── down.sql │ │ │ └── up.sql │ │ ├── mod.rs │ │ ├── models │ │ ├── asset.rs │ │ ├── asset_address.rs │ │ ├── asset_type.rs │ │ ├── chain.rs │ │ ├── chart.rs │ │ ├── device.rs │ │ ├── fiat.rs │ │ ├── link.rs │ │ ├── mod.rs │ │ ├── nft_asset.rs │ │ ├── nft_collection.rs │ │ ├── nft_link.rs │ │ ├── node.rs │ │ ├── parser_state.rs │ │ ├── price.rs │ │ ├── price_alert.rs │ │ ├── release.rs │ │ ├── scan.rs │ │ ├── subscription.rs │ │ ├── tag.rs │ │ ├── transaction.rs │ │ └── transaction_addresses.rs │ │ └── schema.rs └── streamer │ ├── Cargo.toml │ └── src │ ├── consumer.rs │ ├── exchange.rs │ ├── lib.rs │ ├── payload.rs │ ├── queue.rs │ ├── steam_producer_queue.rs │ ├── stream_producer.rs │ └── stream_reader.rs ├── diesel.toml ├── docker-compose.yml ├── gemstone ├── .cargo │ └── config.toml ├── .gitignore ├── Cargo.toml ├── README.md ├── android │ ├── .gitignore │ ├── build.gradle.kts │ ├── gemstone │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── gemwallet │ │ │ │ └── gemstone │ │ │ │ └── GemstoneTest.kt │ │ │ └── main │ │ │ └── AndroidManifest.xml │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle.kts ├── build.rs ├── justfile ├── src │ ├── Info.plist │ ├── Package.swift │ ├── asset │ │ └── mod.rs │ ├── block_explorer │ │ └── mod.rs │ ├── bsc │ │ └── mod.rs │ ├── chain │ │ └── mod.rs │ ├── config │ │ ├── bitcoin_chain.rs │ │ ├── docs.rs │ │ ├── evm_chain.rs │ │ ├── mod.rs │ │ ├── node.rs │ │ ├── public.rs │ │ ├── social.rs │ │ ├── stake.rs │ │ ├── swap_config.rs │ │ ├── validators.rs │ │ └── wallet_connect.rs │ ├── cosmos │ │ └── mod.rs │ ├── lib.rs │ ├── message │ │ ├── decoder.rs │ │ ├── eip712.rs │ │ ├── mod.rs │ │ ├── sign_type.rs │ │ └── test │ │ │ └── eip712_seaport.json │ ├── network │ │ ├── jsonrpc.rs │ │ ├── mock.rs │ │ ├── mod.rs │ │ ├── provider.rs │ │ └── target.rs │ ├── payment │ │ ├── mod.rs │ │ └── solana_pay.rs │ ├── solana │ │ └── mod.rs │ ├── sui │ │ ├── gas_budget.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── rpc │ │ │ ├── client.rs │ │ │ ├── jsonrpc.rs │ │ │ ├── mod.rs │ │ │ └── models.rs │ ├── swapper │ │ ├── across │ │ │ ├── api.rs │ │ │ ├── config_store.rs │ │ │ ├── hubpool.rs │ │ │ ├── mod.rs │ │ │ └── provider.rs │ │ ├── approval │ │ │ ├── evm.rs │ │ │ ├── mod.rs │ │ │ └── tron.rs │ │ ├── asset.rs │ │ ├── cetus │ │ │ ├── api │ │ │ │ ├── client.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── models.rs │ │ │ │ └── test │ │ │ │ │ └── stats_pool.json │ │ │ ├── mod.rs │ │ │ ├── models.rs │ │ │ ├── provider.rs │ │ │ ├── test │ │ │ │ ├── route_data.json │ │ │ │ ├── sui_all_coins.json │ │ │ │ ├── sui_dev_inspect.json │ │ │ │ ├── sui_suip_pool.json │ │ │ │ └── sui_usdc_pool.json │ │ │ └── tx_builder.rs │ │ ├── chainflip │ │ │ ├── broker │ │ │ │ ├── client.rs │ │ │ │ ├── mod.rs │ │ │ │ └── model.rs │ │ │ ├── capitalize.rs │ │ │ ├── client │ │ │ │ ├── mod.rs │ │ │ │ ├── model.rs │ │ │ │ ├── swap.rs │ │ │ │ └── test │ │ │ │ │ └── btc_eth_quote.json │ │ │ ├── mod.rs │ │ │ ├── model.rs │ │ │ ├── price.rs │ │ │ ├── provider.rs │ │ │ ├── seed.rs │ │ │ ├── test │ │ │ │ ├── chainflip_boost_quotes.json │ │ │ │ └── chainflip_quotes.json │ │ │ └── tx_builder.rs │ │ ├── chainlink.rs │ │ ├── custom_types.rs │ │ ├── error.rs │ │ ├── eth_address.rs │ │ ├── eth_rpc.rs │ │ ├── jupiter │ │ │ ├── client.rs │ │ │ ├── mod.rs │ │ │ ├── model.rs │ │ │ ├── provider.rs │ │ │ └── token_account.rs │ │ ├── mod.rs │ │ ├── models.rs │ │ ├── orca │ │ │ ├── fee_tiers.rs │ │ │ ├── jsonrpc.rs │ │ │ ├── mod.rs │ │ │ ├── models.rs │ │ │ ├── provider.rs │ │ │ ├── test │ │ │ │ ├── tick_array_request.json │ │ │ │ └── tick_array_response.json │ │ │ └── whirlpool.rs │ │ ├── pancakeswap_aptos │ │ │ ├── client.rs │ │ │ ├── mod.rs │ │ │ └── model.rs │ │ ├── permit2_data.rs │ │ ├── proxy │ │ │ ├── client.rs │ │ │ ├── mayan │ │ │ │ ├── explorer.rs │ │ │ │ ├── mod.rs │ │ │ │ └── model.rs │ │ │ ├── mod.rs │ │ │ ├── provider.rs │ │ │ ├── provider_factory.rs │ │ │ ├── symbiosis │ │ │ │ ├── mod.rs │ │ │ │ └── model.rs │ │ │ └── test │ │ │ │ ├── eth_to_sui_swift.json │ │ │ │ ├── mctp_pending.json │ │ │ │ └── swift_refunded.json │ │ ├── remote_models.rs │ │ ├── slippage.rs │ │ ├── thorchain │ │ │ ├── asset.rs │ │ │ ├── chain.rs │ │ │ ├── client.rs │ │ │ ├── mod.rs │ │ │ ├── model.rs │ │ │ └── provider.rs │ │ └── uniswap │ │ │ ├── deadline.rs │ │ │ ├── fee_token.rs │ │ │ ├── mod.rs │ │ │ ├── quote_result.rs │ │ │ ├── swap_route.rs │ │ │ ├── universal_router │ │ │ ├── mod.rs │ │ │ ├── oku.rs │ │ │ ├── pancakeswap.rs │ │ │ ├── reservoir.rs │ │ │ ├── uniswap_v3.rs │ │ │ └── wagmi.rs │ │ │ ├── v3 │ │ │ ├── commands.rs │ │ │ ├── mod.rs │ │ │ ├── path.rs │ │ │ ├── provider.rs │ │ │ └── quoter_v2.rs │ │ │ └── v4 │ │ │ ├── commands.rs │ │ │ ├── mod.rs │ │ │ ├── path.rs │ │ │ ├── provider.rs │ │ │ └── quoter.rs │ ├── ton │ │ ├── address.rs │ │ ├── jetton.rs │ │ └── mod.rs │ ├── tron │ │ ├── client.rs │ │ ├── mod.rs │ │ └── model.rs │ └── wallet_connect │ │ └── mod.rs ├── tests │ ├── android │ │ └── GemTest │ │ │ ├── .gitignore │ │ │ ├── app │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src │ │ │ │ └── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── gemtest │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ ├── NativeProvider.kt │ │ │ │ │ └── ui │ │ │ │ │ └── theme │ │ │ │ │ ├── Color.kt │ │ │ │ │ ├── Theme.kt │ │ │ │ │ └── Type.kt │ │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── strings.xml │ │ │ │ └── themes.xml │ │ │ │ └── xml │ │ │ │ ├── backup_rules.xml │ │ │ │ └── data_extraction_rules.xml │ │ │ ├── build.gradle │ │ │ ├── gradle.properties │ │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ └── settings.gradle │ ├── integration_test.rs │ └── ios │ │ └── GemTest │ │ ├── GemTest.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── swiftpm │ │ │ │ └── Package.resolved │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── GemTest.xcscheme │ │ └── xcuserdata │ │ │ └── magician.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ │ ├── GemTest │ │ ├── Assets.xcassets │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── ContentView.swift │ │ ├── Extension │ │ │ ├── Data+Hex.swift │ │ │ ├── Gemstone+Extension.swift │ │ │ ├── Swapper+Ext.swift │ │ │ └── URLRequest+Extension.swift │ │ ├── GemTestApp.swift │ │ ├── Networking │ │ │ ├── Cache.swift │ │ │ └── Provider.swift │ │ ├── Preview Content │ │ │ └── Preview Assets.xcassets │ │ │ │ └── Contents.json │ │ ├── SwapRequests.swift │ │ └── ViewModel.swift │ │ └── GemTestTests │ │ └── GemTestTests.swift └── uniffi.toml ├── justfile ├── rustfmt.toml ├── scripts ├── free_disk_space.sh └── localize.sh └── typeshare.toml /.clippy.toml: -------------------------------------------------------------------------------- 1 | too-many-arguments-threshold = 18 # lower this until we fix current code, ideally 8~10 2 | type-complexity-threshold = 384 3 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | target -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/.gitattributes -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "cargo" 4 | directory: "/" 5 | open-pull-requests-limit: 2 6 | schedule: 7 | interval: "daily" 8 | ignore: 9 | - dependency-name: "*" 10 | update-types: 11 | ["version-update:semver-patch", "version-update:semver-minor"] 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI - Unit Tests 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["main"] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | SCCACHE_GHA_ENABLED: "true" 12 | RUSTC_WRAPPER: "sccache" 13 | 14 | jobs: 15 | unit_test: 16 | runs-on: ubuntu-latest 17 | defaults: 18 | run: 19 | working-directory: ./ 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | - name: Restore cargo cache 25 | uses: Swatinem/rust-cache@v2 26 | 27 | - name: Run sccache-cache 28 | uses: mozilla-actions/sccache-action@v0.0.8 29 | 30 | - name: Install just 31 | run: sudo apt install just 32 | 33 | - name: Run tests 34 | run: just --unstable test-all 35 | 36 | - name: Build integration tests 37 | run: | 38 | just --unstable gemstone build-integration-tests 39 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: CI - Docker Build 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["main"] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | docker_build: 14 | runs-on: ubuntu-latest 15 | defaults: 16 | run: 17 | working-directory: ./ 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | - name: Clean space 23 | run: ./free_disk_space.sh 24 | working-directory: scripts 25 | 26 | - name: Docker Build 27 | run: | 28 | docker build --tag core . 29 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: CI - Lint 2 | on: 3 | pull_request: 4 | branches: ["main"] 5 | 6 | env: 7 | CARGO_TERM_COLOR: always 8 | 9 | jobs: 10 | clippy_check: 11 | runs-on: ubuntu-latest 12 | defaults: 13 | run: 14 | working-directory: ./ 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: actions/cache@v3 19 | with: 20 | path: | 21 | ~/.cargo/registry 22 | ~/.cargo/git 23 | target 24 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 25 | 26 | - name: Install just 27 | run: sudo apt install just 28 | 29 | - name: Run Lint 30 | run: just --unstable lint 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .DS_Store 3 | .env 4 | .idea/ 5 | .vscode/ 6 | .vscode/settings.json 7 | gemstone/src/.build -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.check.command": "clippy", 3 | "[rust]": { 4 | "editor.defaultFormatter": "rust-lang.rust-analyzer", 5 | "editor.formatOnSave": true 6 | }, 7 | "[toml]": { 8 | "editor.formatOnSave": true 9 | }, 10 | "[yaml]": { 11 | "editor.formatOnSave": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.windsurf/rules/code-style-guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | trigger: always_on 3 | --- 4 | 5 | ## Code Style Guidelines 6 | 7 | - Use Rust 2021 edition conventions 8 | - Lint with Clippy (follow .clippy.toml) 9 | - Error handling: Use Result types with the ? operator 10 | - Naming: snake_case for functions/variables, CamelCase for types, "util" or "utils" are not allowed 11 | - Testing: Use #[test] or #[tokio::test] for async tests 12 | - Documentation: /// for function docs, //! for module docs 13 | - Code Comments: Only adding absolute necessary comments to complex algorithm, no need for most self explanatory code 14 | - Imports: Group by std, external crates, then internal modules 15 | - Types: Always specify explicit types for public API functions 16 | - Prefer async/await over raw futures where appropriate 17 | - Don't change test data in unit tests to make it pass (or add hardcode values to code either) 18 | -------------------------------------------------------------------------------- /apps/api/src/config/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub use client::ConfigClient; 3 | extern crate rocket; 4 | 5 | use primitives::config::ConfigResponse; 6 | use rocket::serde::json::Json; 7 | use rocket::tokio::sync::Mutex; 8 | use rocket::State; 9 | 10 | #[get("/config")] 11 | pub async fn get_config(config_client: &State>) -> Json { 12 | let config: ConfigResponse = config_client.lock().await.get_config().unwrap(); 13 | Json(config) 14 | } 15 | -------------------------------------------------------------------------------- /apps/api/src/markets/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate rocket; 2 | 3 | use pricer::MarketsClient; 4 | use primitives::{Markets, ResponseResult}; 5 | use rocket::response::status::NotFound; 6 | use rocket::serde::json::Json; 7 | use rocket::tokio::sync::Mutex; 8 | use rocket::State; 9 | 10 | #[get("/markets")] 11 | pub async fn get_markets(client: &State>) -> Result>, NotFound> { 12 | match client.lock().await.get_markets().await { 13 | Ok(data) => Ok(Json(ResponseResult::new(data))), 14 | Err(err) => Err(NotFound(err.to_string())), 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /apps/api/src/metrics/mod.rs: -------------------------------------------------------------------------------- 1 | mod client; 2 | pub use client::MetricsClient; 3 | 4 | extern crate rocket; 5 | 6 | use rocket::tokio::sync::Mutex; 7 | use rocket::State; 8 | 9 | #[get("/")] 10 | pub async fn get_metrics(client: &State>) -> String { 11 | client.lock().await.get() 12 | } 13 | -------------------------------------------------------------------------------- /apps/api/src/model.rs: -------------------------------------------------------------------------------- 1 | use strum::EnumIter; 2 | use strum_macros::{AsRefStr, EnumString}; 3 | 4 | #[derive(Debug, Clone, AsRefStr, EnumString, EnumIter, PartialEq)] 5 | #[strum(serialize_all = "snake_case")] 6 | pub enum APIService { 7 | Api, 8 | WebsocketPrices, 9 | } 10 | -------------------------------------------------------------------------------- /apps/api/src/name.rs: -------------------------------------------------------------------------------- 1 | extern crate rocket; 2 | use std::str::FromStr; 3 | 4 | use name_resolver::client::Client as NameClient; 5 | use primitives::chain::Chain; 6 | use primitives::name::NameRecord; 7 | use rocket::{response::status::NotFound, serde::json::Json, tokio::sync::Mutex, State}; 8 | 9 | #[get("/name/resolve/?")] 10 | pub async fn get_name_resolve(name: &str, chain: &str, name_client: &State>) -> Result, NotFound> { 11 | let chain = Chain::from_str(chain).unwrap(); 12 | let result = name_client.lock().await.resolve(name, chain).await; 13 | match result { 14 | Ok(name) => Ok(Json(name)), 15 | Err(err) => Err(NotFound(err.to_string())), 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /apps/api/src/scan/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate rocket; 2 | use primitives::{ResponseResult, ScanTransaction, ScanTransactionPayload}; 3 | use rocket::{serde::json::Json, tokio::sync::Mutex, State}; 4 | 5 | pub mod client; 6 | pub mod providers; 7 | 8 | pub use client::ScanClient; 9 | pub use providers::ScanProviderFactory; 10 | 11 | #[post("/scan/transaction", data = "")] 12 | pub async fn scan_transaction(request: Json, client: &State>) -> Json> { 13 | let result: ScanTransaction = client.lock().await.get_scan_transaction(request.0).await.unwrap(); 14 | Json(ResponseResult::new(result)) 15 | } 16 | -------------------------------------------------------------------------------- /apps/api/src/scan/providers.rs: -------------------------------------------------------------------------------- 1 | use security_goplus::GoPlusProvider; 2 | use security_hashdit::HashDitProvider; 3 | use security_provider::ScanProvider; 4 | use settings::Settings; 5 | 6 | pub struct ScanProviderFactory {} 7 | 8 | impl ScanProviderFactory { 9 | pub fn create_providers(settings: &Settings) -> Vec> { 10 | let client = reqwest::Client::builder() 11 | .timeout(std::time::Duration::from_millis(settings.scan.timeout_ms)) 12 | .build() 13 | .unwrap(); 14 | 15 | vec![ 16 | Box::new(GoPlusProvider::new(client.clone(), &settings.scan.goplus.url, &settings.scan.goplus.key.public)), 17 | Box::new(HashDitProvider::new( 18 | client.clone(), 19 | &settings.scan.hashdit.key.public, 20 | &settings.scan.hashdit.key.secret, 21 | )), 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/api/src/status.rs: -------------------------------------------------------------------------------- 1 | extern crate rocket; 2 | use rocket::serde::json::Json; 3 | use rocket::serde::Serialize; 4 | use std::time::{SystemTime, UNIX_EPOCH}; 5 | 6 | #[get("/")] 7 | pub fn get_status(ip: std::net::IpAddr) -> Json { 8 | Json(Status { 9 | time: get_epoch_ms(), 10 | ipv4: ip.to_string(), 11 | }) 12 | } 13 | 14 | fn get_epoch_ms() -> u128 { 15 | SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() 16 | } 17 | 18 | #[derive(Serialize)] 19 | pub struct Status { 20 | time: u128, 21 | ipv4: String, 22 | } 23 | -------------------------------------------------------------------------------- /apps/api/src/swap/client.rs: -------------------------------------------------------------------------------- 1 | extern crate rocket; 2 | 3 | use std::error::Error; 4 | 5 | use primitives::FiatAssets; 6 | use storage::DatabaseClient; 7 | 8 | pub struct SwapClient { 9 | database: DatabaseClient, 10 | } 11 | 12 | impl SwapClient { 13 | pub async fn new(database_url: &str) -> Self { 14 | let database = DatabaseClient::new(database_url); 15 | Self { database } 16 | } 17 | 18 | pub async fn get_swap_assets(&mut self) -> Result> { 19 | let assets = self.database.get_swap_assets()?; 20 | let version = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_secs() / 3600; 21 | 22 | Ok(FiatAssets { 23 | version: version as u32, 24 | asset_ids: assets, 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /apps/api/src/swap/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | 3 | extern crate rocket; 4 | use primitives::fiat_assets::FiatAssets; 5 | use rocket::serde::json::Json; 6 | use rocket::tokio::sync::Mutex; 7 | use rocket::State; 8 | 9 | pub use client::SwapClient; 10 | 11 | #[get("/swap/assets")] 12 | pub async fn get_swap_assets(client: &State>) -> Json { 13 | let quote = client.lock().await.get_swap_assets().await.unwrap(); 14 | Json(quote) 15 | } 16 | -------------------------------------------------------------------------------- /apps/api/src/websocket_prices/mod.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use rocket::tokio::sync::Mutex; 4 | use rocket::State; 5 | use rocket_ws::{Channel, WebSocket}; 6 | 7 | mod client; 8 | mod stream; 9 | 10 | pub use client::{PriceObserverClient, PriceObserverConfig}; 11 | use pricer::PriceClient; 12 | use stream::Stream; 13 | 14 | #[rocket::get("/prices")] 15 | pub async fn ws_prices(ws: WebSocket, price_client: &State>>, config: &State>>) -> Channel<'static> { 16 | let price_client = price_client.inner().clone(); 17 | let redis_url = config.lock().await.redis_url.clone(); 18 | 19 | ws.channel(move |stream| { 20 | Box::pin(async move { 21 | let mut observer = PriceObserverClient::new(price_client.clone()); 22 | Stream::new_stream(&redis_url, &mut observer, stream).await; 23 | Ok::<(), rocket_ws::result::Error>(()) 24 | }) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /apps/daemon/src/device/device_updater.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use storage::database::DatabaseClient; 3 | 4 | pub struct DeviceUpdater { 5 | database: DatabaseClient, 6 | } 7 | 8 | impl DeviceUpdater { 9 | pub fn new(database_url: &str) -> Self { 10 | let database = DatabaseClient::new(database_url); 11 | Self { database } 12 | } 13 | 14 | pub async fn update(&mut self) -> Result> { 15 | Ok(self.database.delete_devices_subscriptions_after_days(120)?) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /apps/daemon/src/device/mod.rs: -------------------------------------------------------------------------------- 1 | mod device_updater; 2 | use device_updater::DeviceUpdater; 3 | use job_runner::run_job; 4 | use settings::Settings; 5 | use std::future::Future; 6 | use std::pin::Pin; 7 | use std::sync::Arc; 8 | use std::time::Duration; 9 | 10 | pub async fn jobs(settings: Settings) -> Vec + Send>>> { 11 | let device_updater = run_job("device updater", Duration::from_secs(86400), { 12 | let settings = Arc::new(settings.clone()); 13 | move || { 14 | let mut device_updater = DeviceUpdater::new(&settings.postgres.url); 15 | async move { device_updater.update().await } 16 | } 17 | }); 18 | 19 | vec![Box::pin(device_updater)] 20 | } 21 | -------------------------------------------------------------------------------- /apps/daemon/src/model.rs: -------------------------------------------------------------------------------- 1 | use strum::{EnumIter, IntoEnumIterator}; 2 | use strum_macros::{AsRefStr, EnumString}; 3 | 4 | #[derive(Debug, Clone, AsRefStr, EnumString, EnumIter, PartialEq)] 5 | #[strum(serialize_all = "lowercase")] 6 | pub enum DaemonService { 7 | Alerter, 8 | Pricer, 9 | Fiat, 10 | Assets, 11 | Version, 12 | Transaction, 13 | Device, 14 | Search, 15 | Nft, 16 | Notifications, 17 | } 18 | 19 | impl DaemonService { 20 | pub fn all() -> Vec { 21 | Self::iter().collect() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /apps/daemon/src/nft/nft_collection_asset_consumer.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | use async_trait::async_trait; 4 | use streamer::{consumer::MessageConsumer, FetchNFTCollectionAssetPayload}; 5 | 6 | pub struct UpdateNftCollectionAssetsConsumer {} 7 | 8 | impl UpdateNftCollectionAssetsConsumer { 9 | pub fn new() -> Self { 10 | Self {} 11 | } 12 | } 13 | 14 | #[async_trait] 15 | impl MessageConsumer for UpdateNftCollectionAssetsConsumer { 16 | async fn process(&mut self, _payload: FetchNFTCollectionAssetPayload) -> Result> { 17 | Ok(0) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/daemon/src/nft/nft_collection_consumer.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | use async_trait::async_trait; 4 | use streamer::{consumer::MessageConsumer, FetchNFTCollectionPayload}; 5 | 6 | pub struct UpdateNftCollectionConsumer {} 7 | 8 | impl UpdateNftCollectionConsumer { 9 | pub fn new() -> Self { 10 | Self {} 11 | } 12 | } 13 | 14 | #[async_trait] 15 | impl MessageConsumer for UpdateNftCollectionConsumer { 16 | async fn process(&mut self, _payload: FetchNFTCollectionPayload) -> Result> { 17 | Ok(0) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/daemon/src/notifications/notifications_consumer.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | use api_connector::PusherClient; 4 | use async_trait::async_trait; 5 | use streamer::{consumer::MessageConsumer, NotificationsPayload}; 6 | 7 | pub struct NotificationsConsumer { 8 | pub pusher: PusherClient, 9 | } 10 | 11 | impl NotificationsConsumer { 12 | pub fn new(pusher: PusherClient) -> Self { 13 | Self { pusher } 14 | } 15 | } 16 | 17 | #[async_trait] 18 | impl MessageConsumer for NotificationsConsumer { 19 | async fn process(&mut self, payload: NotificationsPayload) -> Result> { 20 | let count = payload.notifications.len(); 21 | if count == 0 { 22 | return Ok(0); 23 | } 24 | Ok(self.pusher.push_notifications(payload.notifications).await?.counts as usize) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /apps/daemon/src/transaction/mod.rs: -------------------------------------------------------------------------------- 1 | mod transaction_updater; 2 | 3 | use job_runner::run_job; 4 | use settings::Settings; 5 | use std::future::Future; 6 | use std::pin::Pin; 7 | use std::sync::Arc; 8 | use std::time::Duration; 9 | use transaction_updater::TransactionUpdater; 10 | 11 | pub async fn jobs(settings: Settings) -> Vec + Send>>> { 12 | let transaction_updater = run_job("transaction update", Duration::from_secs(86400), { 13 | let settings = Arc::new(settings.clone()); 14 | move || { 15 | let mut transaction_updater = TransactionUpdater::new(&settings.postgres.url); 16 | async move { transaction_updater.update().await } 17 | } 18 | }); 19 | 20 | vec![Box::pin(transaction_updater)] 21 | } 22 | -------------------------------------------------------------------------------- /apps/parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "parser" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | serde_json = { workspace = true } 9 | tokio = { workspace = true } 10 | futures = { workspace = true } 11 | chrono = { workspace = true } 12 | async-trait = { workspace = true } 13 | rand = { workspace = true } 14 | 15 | primitives = { path = "../../crates/primitives" } 16 | storage = { path = "../../crates/storage" } 17 | settings = { path = "../../crates/settings" } 18 | settings_chain = { path = "../../crates/settings_chain" } 19 | gem_chain_rpc = { path = "../../crates/gem_chain_rpc" } 20 | api_connector = { path = "../../crates/api_connector" } 21 | localizer = { path = "../../crates/localizer" } 22 | number_formatter = { path = "../../crates/number_formatter" } 23 | streamer = { path = "../../crates/streamer" } 24 | -------------------------------------------------------------------------------- /apps/parser/src/parser_options.rs: -------------------------------------------------------------------------------- 1 | use primitives::Chain; 2 | 3 | #[derive(Debug, Clone)] 4 | pub struct ParserOptions { 5 | pub chain: Chain, 6 | pub timeout: u64, 7 | } 8 | 9 | impl ParserOptions {} 10 | -------------------------------------------------------------------------------- /apps/parser/src/pusher/mod.rs: -------------------------------------------------------------------------------- 1 | #[allow(clippy::module_inception)] 2 | mod pusher; 3 | pub use pusher::Pusher; 4 | -------------------------------------------------------------------------------- /apps/setup/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "setup" 3 | edition = { workspace = true } 4 | version = { workspace = true } 5 | 6 | [dependencies] 7 | tokio = { workspace = true } 8 | storage = { path = "../../crates/storage" } 9 | settings = { path = "../../crates/settings" } 10 | primitives = { path = "../../crates/primitives" } 11 | search_index = { path = "../../crates/search_index" } 12 | streamer = { path = "../../crates/streamer" } 13 | -------------------------------------------------------------------------------- /bin/generate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "generate" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | primitives = { path = "../../crates/primitives" } 8 | -------------------------------------------------------------------------------- /bin/img-downloader/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "img-downloader" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | tokio = { workspace = true } 8 | serde = { workspace = true } 9 | reqwest = { workspace = true, features = ["stream"] } 10 | reqwest-middleware = { workspace = true } 11 | reqwest-retry = { workspace = true } 12 | 13 | futures-util = { workspace = true } 14 | clap = { version = "4.5.39", features = ["derive"] } 15 | 16 | chain_primitives = { path = "../../crates/chain_primitives" } 17 | coingecko = { path = "../../crates/coingecko" } 18 | settings = { path = "../../crates/settings" } 19 | gem_evm = { path = "../../crates/gem_evm" } 20 | -------------------------------------------------------------------------------- /bin/swapper-dump/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swapper-dump" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | gemstone = { path = "../../gemstone" } 8 | primitives = { path = "../../crates/primitives" } 9 | alien_provider = { path = "../../crates/alien_provider" } 10 | tokio = { workspace = true } 11 | 12 | [[bin]] 13 | name = "swapper-dump" 14 | path = "src/main.rs" 15 | -------------------------------------------------------------------------------- /bin/uniffi-bindgen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "uniffi-bindgen" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | uniffi = { workspace = true, features = ["cli"] } 8 | -------------------------------------------------------------------------------- /bin/uniffi-bindgen/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | uniffi::uniffi_bindgen_main() 3 | } 4 | -------------------------------------------------------------------------------- /crates/alien_provider/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "alien_provider" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | gemstone = { path = "../../gemstone" } 8 | primitives = { path = "../primitives" } 9 | reqwest.workspace = true 10 | serde.workspace = true 11 | serde_json.workspace = true 12 | async-trait.workspace = true 13 | futures.workspace = true 14 | -------------------------------------------------------------------------------- /crates/api_connector/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "api_connector" 3 | edition = { workspace = true } 4 | version = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | reqwest = { workspace = true } 9 | serde_json = { workspace = true } 10 | chrono = { workspace = true } 11 | primitives = { path = "../primitives" } 12 | -------------------------------------------------------------------------------- /crates/api_connector/src/app_store_client/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod models; 3 | -------------------------------------------------------------------------------- /crates/api_connector/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod app_store_client; 2 | pub mod pusher; 3 | pub use self::app_store_client::client::AppStoreClient; 4 | pub use self::pusher::client::PusherClient; 5 | -------------------------------------------------------------------------------- /crates/api_connector/src/pusher/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod model; 3 | -------------------------------------------------------------------------------- /crates/api_connector/src/pusher/model.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Serialize, Deserialize)] 4 | pub struct Response { 5 | pub counts: i32, 6 | pub logs: Vec, 7 | pub success: String, 8 | } 9 | 10 | #[derive(Debug, Serialize, Deserialize)] 11 | pub struct Log { 12 | #[serde(rename = "type")] 13 | pub log_type: String, 14 | pub platform: String, 15 | pub token: String, 16 | pub error: String, 17 | } 18 | 19 | #[derive(Debug, Clone, Serialize, Deserialize)] 20 | pub struct Message { 21 | pub title: String, 22 | pub message: Option, 23 | } 24 | -------------------------------------------------------------------------------- /crates/blockchain/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blockchain" 3 | edition = { workspace = true } 4 | version = { workspace = true } 5 | 6 | [dependencies] 7 | typeshare = { workspace = true } 8 | serde = { workspace = true } 9 | -------------------------------------------------------------------------------- /crates/blockchain/README.md: -------------------------------------------------------------------------------- 1 | # Blockchain 2 | 3 | Basic blockchain models annotated with TypeShare. 4 | -------------------------------------------------------------------------------- /crates/blockchain/src/bitcoin/models/bitcoin_account.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct BitcoinAccount { 3 | balance: String, 4 | } 5 | -------------------------------------------------------------------------------- /crates/blockchain/src/bitcoin/models/bitcoin_block.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct BitcoinBlock { 3 | #[serde(rename = "previousBlockHash")] 4 | previous_block_hash: Option, 5 | } 6 | -------------------------------------------------------------------------------- /crates/blockchain/src/bitcoin/models/bitcoin_fee.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct BitcoinFeeResult { 3 | result: String, 4 | } 5 | -------------------------------------------------------------------------------- /crates/blockchain/src/bitcoin/models/bitcoin_node_info.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct BitcoinNodeInfo { 3 | blockbook: BitcoinBlockbook, 4 | } 5 | 6 | #[typeshare(swift = "Sendable")] 7 | struct BitcoinBlockbook { 8 | #[serde(rename = "inSync")] 9 | in_sync: bool, 10 | #[serde(rename = "lastBlockTime")] 11 | last_block_time: String, 12 | #[serde(rename = "bestHeight")] 13 | best_height: Int, 14 | } 15 | -------------------------------------------------------------------------------- /crates/blockchain/src/bitcoin/models/bitcoin_transaction.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct BitcoinTransaction { 3 | #[serde(rename = "blockHeight")] 4 | block_height: i32, 5 | } 6 | 7 | #[typeshare(swift = "Sendable")] 8 | struct BitcoinTransactionBroacastResult { 9 | error: Option, 10 | result: Option, 11 | } 12 | 13 | #[typeshare(swift = "Sendable")] 14 | struct BitcoinTransactionBroacastError { 15 | message: String, 16 | } 17 | -------------------------------------------------------------------------------- /crates/blockchain/src/bitcoin/models/bitcoin_utxo.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct BitcoinUTXO { 3 | txid: String, 4 | vout: i32, 5 | value: String, 6 | } 7 | -------------------------------------------------------------------------------- /crates/blockchain/src/cosmos/models/cosmos_account.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct CosmosAccount { 3 | account_number: String, 4 | sequence: String, 5 | } 6 | 7 | #[typeshare(swift = "Sendable")] 8 | #[typeshare(swiftGenericConstraints = "T: Sendable")] 9 | struct CosmosAccountResponse { 10 | account: T, 11 | } 12 | 13 | #[typeshare(swift = "Sendable")] 14 | struct CosmosInjectiveAccount { 15 | base_account: CosmosAccount, 16 | } 17 | -------------------------------------------------------------------------------- /crates/blockchain/src/cosmos/models/cosmos_balance.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct CosmosBalances { 3 | balances: Vec, 4 | } 5 | 6 | #[typeshare(swift = "Sendable")] 7 | struct CosmosBalance { 8 | denom: String, 9 | amount: String, 10 | } 11 | -------------------------------------------------------------------------------- /crates/blockchain/src/cosmos/models/cosmos_node_info.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct CosmosBlockResponse { 3 | block: CosmosBlock, 4 | } 5 | 6 | #[typeshare(swift = "Sendable")] 7 | struct CosmosBlock { 8 | header: CosmosHeader, 9 | } 10 | 11 | #[typeshare(swift = "Sendable")] 12 | struct CosmosHeader { 13 | chain_id: String, 14 | height: String, 15 | } 16 | 17 | #[typeshare(swift = "Sendable")] 18 | struct CosmosNodeInfoResponse { 19 | default_node_info: CosmosNodeInfo, 20 | } 21 | 22 | #[typeshare(swift = "Sendable")] 23 | struct CosmosNodeInfo { 24 | network: String, 25 | } 26 | -------------------------------------------------------------------------------- /crates/blockchain/src/cosmos/models/cosmos_syncing.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct CosmosSyncing { 3 | syncing: bool, 4 | } 5 | -------------------------------------------------------------------------------- /crates/blockchain/src/cosmos/models/cosmos_transaction.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct CosmosBroadcastResponse { 3 | tx_response: CosmosBroadcastResult, 4 | } 5 | 6 | #[typeshare(swift = "Sendable")] 7 | struct CosmosBroadcastResult { 8 | txhash: String, 9 | code: i32, 10 | raw_log: String, 11 | } 12 | 13 | #[typeshare(swift = "Sendable")] 14 | struct CosmosTransactionResponse { 15 | tx_response: CosmosTransactionDataResponse, 16 | } 17 | 18 | #[typeshare(swift = "Sendable")] 19 | struct CosmosTransactionDataResponse { 20 | txhash: String, 21 | code: i32, 22 | } 23 | -------------------------------------------------------------------------------- /crates/blockchain/src/ethereum/models/ethereum_transaction.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | #[serde(rename_all = "camelCase")] 3 | struct EthereumTransactionReciept { 4 | status: String, 5 | gas_used: String, 6 | effective_gas_price: String, 7 | #[serde(rename = "l1Fee")] 8 | l1_fee: Option, 9 | } 10 | 11 | #[typeshare(swift = "Sendable")] 12 | struct EthereumFeeHistory { 13 | reward: Vec>, 14 | #[serde(rename = "baseFeePerGas")] 15 | base_fee_per_gas: Vec, 16 | } 17 | -------------------------------------------------------------------------------- /crates/blockchain/src/graphql/graphql_model.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | #[serde(rename_all = "camelCase")] 3 | struct GraphqlRequest { 4 | operation_name: String, 5 | variables: HashMap, 6 | query: String, 7 | } 8 | 9 | #[typeshare(swift = "Sendable")] 10 | #[serde(rename_all = "camelCase")] 11 | #[typeshare(swiftGenericConstraints = "T: Sendable")] 12 | struct GraphqlData { 13 | data: Option, 14 | errors: Option>, 15 | } 16 | 17 | #[typeshare(swift = "Sendable")] 18 | #[serde(rename_all = "camelCase")] 19 | struct GraphqlError { 20 | message: String, 21 | } 22 | -------------------------------------------------------------------------------- /crates/blockchain/src/lib.rs: -------------------------------------------------------------------------------- 1 | // lib.rs 2 | -------------------------------------------------------------------------------- /crates/blockchain/src/solana/models/solana_balance.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct SolanaBalance { 3 | value: Int, 4 | } 5 | 6 | #[typeshare(swift = "Sendable")] 7 | struct SolanaBalanceValue { 8 | amount: String, 9 | } 10 | -------------------------------------------------------------------------------- /crates/blockchain/src/solana/models/solana_blockhash.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | #[serde(rename_all = "camelCase")] 3 | struct SolanaBlockhashResult { 4 | value: SolanaBlockhash, 5 | } 6 | 7 | #[typeshare(swift = "Sendable")] 8 | #[serde(rename_all = "camelCase")] 9 | struct SolanaBlockhash { 10 | blockhash: String, 11 | } 12 | -------------------------------------------------------------------------------- /crates/blockchain/src/solana/models/solana_prioritization_fee.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct SolanaPrioritizationFee { 3 | #[serde(rename = "prioritizationFee")] 4 | prioritization_fee: i32, 5 | } 6 | -------------------------------------------------------------------------------- /crates/blockchain/src/solana/models/solana_stake.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct SolanaValidators { 3 | current: Vec, 4 | } 5 | 6 | #[typeshare(swift = "Sendable")] 7 | #[serde(rename_all = "camelCase")] 8 | struct SolanaValidator { 9 | vote_pubkey: String, 10 | commission: i32, 11 | epoch_vote_account: bool, 12 | } 13 | 14 | #[typeshare(swift = "Sendable")] 15 | #[serde(rename_all = "camelCase")] 16 | struct SolanaEpoch { 17 | epoch: i32, 18 | slot_index: i32, 19 | slots_in_epoch: i32, 20 | } 21 | -------------------------------------------------------------------------------- /crates/blockchain/src/solana/models/solana_transaction.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct SolanaTransaction { 3 | meta: SolanaTransactionMeta, 4 | slot: i32, 5 | } 6 | 7 | #[typeshare(swift = "Sendable")] 8 | struct SolanaTransactionMeta { 9 | err: Option, 10 | } 11 | 12 | #[typeshare(swift = "Sendable")] 13 | struct SolanaTransactionError {} 14 | 15 | #[typeshare(swift = "Sendable")] 16 | #[serde(rename_all = "camelCase")] 17 | struct SolanaInstruction { 18 | program_id: String, 19 | accounts: [SolanaAccountMeta], 20 | data: String, 21 | } 22 | 23 | #[typeshare(swift = "Sendable")] 24 | #[serde(rename_all = "camelCase")] 25 | struct SolanaAccountMeta { 26 | pubkey: String, 27 | } 28 | -------------------------------------------------------------------------------- /crates/blockchain/src/solana/models/solana_value.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | #[typeshare(swiftGenericConstraints = "T: Sendable")] 3 | pub struct SolanaValue { 4 | pub value: T, 5 | } 6 | -------------------------------------------------------------------------------- /crates/blockchain/src/ton/models/ton_broadcast_transaction.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct TonBroadcastTransaction { 3 | hash: String, 4 | } 5 | -------------------------------------------------------------------------------- /crates/blockchain/src/ton/models/ton_chaininfo.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct TonMasterchainInfo { 3 | last: TonBlock, 4 | //init: TonBlock, 5 | } 6 | 7 | #[typeshare(swift = "Sendable")] 8 | struct TonBlock { 9 | seqno: i32, 10 | root_hash: String, 11 | } 12 | -------------------------------------------------------------------------------- /crates/blockchain/src/ton/models/ton_fee.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct TonEstimateFee { 3 | address: String, 4 | body: String, 5 | ignore_chksig: bool, 6 | } 7 | 8 | #[typeshare(swift = "Sendable")] 9 | struct TonFees { 10 | source_fees: TonFee, 11 | } 12 | 13 | #[typeshare(swift = "Sendable")] 14 | struct TonFee { 15 | in_fwd_fee: i32, 16 | storage_fee: i32, 17 | } 18 | -------------------------------------------------------------------------------- /crates/blockchain/src/ton/models/ton_wallet_info.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct TonWalletInfo { 3 | seqno: Option, 4 | last_transaction_id: TonTransactionId, 5 | } 6 | #[typeshare(swift = "Sendable")] 7 | #[typeshare(swiftGenericConstraints = "T: Sendable")] 8 | struct TonResult { 9 | result: T, 10 | } 11 | -------------------------------------------------------------------------------- /crates/blockchain/src/tron/models/tron_block.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct TronBlock { 3 | #[serde(rename = "block_header")] 4 | block_header: TronHeaderRawData, 5 | } 6 | 7 | #[typeshare(swift = "Sendable")] 8 | struct TronHeaderRawData { 9 | raw_data: TronHeader, 10 | } 11 | //TODO: Need to support u64 by typeshare 12 | type UInt64 = u64; 13 | #[typeshare(swift = "Sendable")] 14 | struct TronHeader { 15 | number: UInt64, 16 | version: UInt64, 17 | #[serde(rename = "txTrieRoot")] 18 | tx_trie_root: String, 19 | witness_address: String, 20 | #[serde(rename = "parentHash")] 21 | parent_hash: String, 22 | timestamp: UInt64, 23 | } 24 | -------------------------------------------------------------------------------- /crates/blockchain/src/tron/models/tron_chain_parameters.rs: -------------------------------------------------------------------------------- 1 | //TODO: Need to support u64 by typeshare 2 | type Int64 = i64; 3 | #[typeshare(swift = "Sendable")] 4 | struct TronChainParameters { 5 | chainParameter: Vec, 6 | } 7 | 8 | #[typeshare(swift = "Sendable")] 9 | struct TronChainParameter { 10 | key: String, 11 | value: Option, 12 | } 13 | 14 | #[typeshare(swift = "Equatable, Sendable")] 15 | pub enum TronChainParameterKey { 16 | getCreateNewAccountFeeInSystemContract, 17 | getCreateAccountFee, 18 | getEnergyFee, 19 | } 20 | -------------------------------------------------------------------------------- /crates/blockchain/src/tron/models/tron_smart_contract.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct TronSmartContractCall { 3 | contract_address: String, 4 | function_selector: String, 5 | parameter: Option, 6 | fee_limit: Option, 7 | call_value: Option, 8 | owner_address: String, 9 | visible: Option, 10 | } 11 | 12 | #[typeshare(swift = "Sendable")] 13 | struct TronSmartContractResult { 14 | result: TronSmartContractResultMessage, 15 | constant_result: Vec, 16 | energy_used: i32, 17 | } 18 | 19 | #[typeshare(swift = "Sendable")] 20 | struct TronSmartContractResultMessage { 21 | result: bool, 22 | message: Option, 23 | } 24 | -------------------------------------------------------------------------------- /crates/blockchain/src/tron/models/tron_transaction.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct TronTransactionBroadcast { 3 | result: bool, 4 | txid: String, 5 | } 6 | 7 | #[typeshare(swift = "Sendable")] 8 | struct TronTransactionBroadcastError { 9 | message: String, 10 | } 11 | 12 | #[typeshare(swift = "Sendable")] 13 | struct TronTransaction { 14 | ret: Vec, 15 | } 16 | 17 | #[typeshare(swift = "Sendable")] 18 | struct TronTransactionContractRef { 19 | contractRet: String, 20 | } 21 | 22 | #[typeshare(swift = "Sendable")] 23 | struct TronTransactionReceipt { 24 | #[serde(rename = "blockNumber")] 25 | pub block_number: i32, 26 | fee: Option, 27 | result: Option, 28 | receipt: Option, 29 | } 30 | 31 | #[typeshare(swift = "Sendable")] 32 | struct TronReceipt { 33 | result: Option, 34 | } 35 | -------------------------------------------------------------------------------- /crates/cacher/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cacher" 3 | edition = { workspace = true } 4 | version = { workspace = true } 5 | 6 | [dependencies] 7 | redis = { workspace = true } 8 | serde = { workspace = true } 9 | serde_json = { workspace = true } -------------------------------------------------------------------------------- /crates/chain_primitives/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "chain_primitives" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | primitives = { path = "../primitives" } 8 | gem_evm = { path = "../gem_evm" } 9 | -------------------------------------------------------------------------------- /crates/coingecko/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "coingecko" 3 | edition = { workspace = true } 4 | version = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | reqwest = { workspace = true } 9 | primitives = { path = "../primitives" } 10 | chrono = { workspace = true } 11 | lazy_static = { workspace = true } 12 | reqwest-middleware = { workspace = true } 13 | -------------------------------------------------------------------------------- /crates/coingecko/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | 5 | pub use self::client::CoinGeckoClient; 6 | pub use self::mapper::{get_chain_for_coingecko_platform_id, get_coingecko_market_id_for_chain}; 7 | pub use self::model::{Coin, CoinInfo, CoinMarket}; 8 | -------------------------------------------------------------------------------- /crates/fiat/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fiat" 3 | edition = { workspace = true } 4 | version = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | serde_json = { workspace = true } 9 | reqwest = { workspace = true } 10 | url = { workspace = true } 11 | hmac = { workspace = true } 12 | sha2 = { workspace = true } 13 | base64 = { workspace = true } 14 | futures = { workspace = true } 15 | async-trait = { workspace = true } 16 | hex = { workspace = true } 17 | bigdecimal = { workspace = true } 18 | uuid = { workspace = true } 19 | tokio = { workspace = true } 20 | thiserror = { workspace = true } 21 | 22 | settings = { path = "../settings" } 23 | storage = { path = "../storage" } 24 | primitives = { path = "../primitives" } 25 | chain_primitives = { path = "../chain_primitives" } 26 | serde_serializers = { path = "../serde_serializers" } 27 | number_formatter = { path = "../number_formatter" } 28 | cacher = { path = "../cacher" } -------------------------------------------------------------------------------- /crates/fiat/src/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum FiatError { 5 | #[error("Purchase not allowed")] 6 | FiatPurchaseNotAllowed, 7 | 8 | #[error("Sell not allowed")] 9 | FiatSellNotAllowed, 10 | 11 | #[error("Minimum Amount is {0}")] 12 | MinimumAmount(f64), 13 | 14 | #[error("Unsupported country: {0}")] 15 | UnsupportedCountry(String), 16 | 17 | #[error("Unsupported country {0} for an asset: {0}")] 18 | UnsupportedCountryAsset(String, String), 19 | 20 | #[error("Unsupported state: {0}")] 21 | UnsupportedState(String), 22 | } 23 | -------------------------------------------------------------------------------- /crates/fiat/src/ip_check_client.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | use serde::{Deserialize, Serialize}; 4 | 5 | use crate::providers::MoonPayClient; 6 | 7 | pub struct IPCheckClient { 8 | client: MoonPayClient, 9 | } 10 | 11 | #[derive(Debug, Clone, Serialize, Deserialize)] 12 | pub struct IPAddressInfo { 13 | pub alpha2: String, 14 | pub state: String, 15 | pub ip_address: String, 16 | } 17 | 18 | impl IPCheckClient { 19 | pub fn new(client: MoonPayClient) -> Self { 20 | Self { client } 21 | } 22 | 23 | pub async fn get_ip_address(&self, ip_address: &str) -> Result> { 24 | let data = self.client.get_ip_address(ip_address).await?; 25 | Ok(IPAddressInfo { 26 | alpha2: data.alpha2, 27 | state: data.state, 28 | ip_address: ip_address.to_owned(), 29 | }) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /crates/fiat/src/providers/banxa/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | pub mod provider; 5 | -------------------------------------------------------------------------------- /crates/fiat/src/providers/mercuryo/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | pub mod provider; 5 | -------------------------------------------------------------------------------- /crates/fiat/src/providers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod moonpay; 2 | pub use self::moonpay::client::MoonPayClient; 3 | 4 | pub mod ramp; 5 | pub use self::ramp::client::RampClient; 6 | 7 | pub mod mercuryo; 8 | pub use self::mercuryo::client::MercuryoClient; 9 | 10 | pub mod transak; 11 | pub use self::transak::client::TransakClient; 12 | 13 | pub mod banxa; 14 | pub use self::banxa::client::BanxaClient; 15 | -------------------------------------------------------------------------------- /crates/fiat/src/providers/moonpay/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | pub mod provider; 5 | -------------------------------------------------------------------------------- /crates/fiat/src/providers/ramp/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | pub mod provider; 5 | -------------------------------------------------------------------------------- /crates/fiat/src/providers/transak/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | pub mod provider; 5 | -------------------------------------------------------------------------------- /crates/gem_algorand/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_algorand" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [features] 7 | default = [] 8 | rpc = ["dep:chrono", "dep:reqwest-middleware"] 9 | 10 | [dependencies] 11 | anyhow = { workspace = true } 12 | async-trait = { workspace = true } 13 | serde = { workspace = true } 14 | serde_json = { workspace = true } 15 | thiserror = { workspace = true } 16 | url = { workspace = true } 17 | base64 = { workspace = true } 18 | 19 | chrono = { workspace = true, optional = true } 20 | reqwest-middleware = { workspace = true, features = ["json"], optional = true } 21 | 22 | primitives = { path = "../primitives" } 23 | -------------------------------------------------------------------------------- /crates/gem_algorand/src/lib.rs: -------------------------------------------------------------------------------- 1 | // gem_algorand crate 2 | 3 | pub mod rpc; 4 | -------------------------------------------------------------------------------- /crates/gem_algorand/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | // RPC related modules for Algorand 2 | 3 | pub mod client; 4 | pub mod mapper; 5 | pub mod model; 6 | 7 | pub use client::AlgorandClient; 8 | pub use mapper::AlgorandMapper; 9 | -------------------------------------------------------------------------------- /crates/gem_aptos/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_aptos" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [features] 7 | default = [] 8 | rpc = [ 9 | "dep:async-trait", 10 | "dep:chrono", 11 | "dep:reqwest-middleware", 12 | "dep:url", 13 | "dep:num-bigint", 14 | ] 15 | 16 | [dependencies] 17 | primitives = { path = "../primitives" } 18 | serde = { workspace = true } 19 | serde_json = { workspace = true } 20 | anyhow = { workspace = true } 21 | 22 | # Dependencies for RPC client & mapper 23 | async-trait = { workspace = true, optional = true } 24 | chrono = { workspace = true, optional = true } 25 | reqwest-middleware = { workspace = true, features = ["json"], optional = true } 26 | url = { workspace = true, optional = true } 27 | num-bigint = { workspace = true, optional = true } 28 | -------------------------------------------------------------------------------- /crates/gem_aptos/src/constants.rs: -------------------------------------------------------------------------------- 1 | pub const APTOS_NATIVE_COIN: &str = "0x1::aptos_coin::AptosCoin"; 2 | 3 | /// The module address for the coin info resource 4 | pub const COIN_INFO: &str = "0x1::coin::CoinInfo"; 5 | pub const COIN_STORE: &str = "0x1::coin::CoinStore"; 6 | 7 | pub const STAKE_WITHDRAW_EVENT: &str = "0x1::coin::WithdrawEvent"; 8 | pub const STAKE_DEPOSIT_EVENT: &str = "0x1::coin::DepositEvent"; 9 | -------------------------------------------------------------------------------- /crates/gem_aptos/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod constants; 2 | pub use constants::*; 3 | pub mod model; 4 | pub use model::*; 5 | 6 | #[cfg(feature = "rpc")] 7 | pub mod rpc; 8 | -------------------------------------------------------------------------------- /crates/gem_aptos/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | 4 | pub use client::AptosClient; 5 | pub use mapper::AptosMapper; 6 | -------------------------------------------------------------------------------- /crates/gem_bitcoin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_bitcoin" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | publish = false 6 | 7 | [features] 8 | default = [] 9 | rpc = ["dep:reqwest-middleware", "dep:chrono"] 10 | 11 | [dependencies] 12 | serde = { workspace = true, features = ["derive"] } 13 | primitives = { path = "../primitives" } 14 | 15 | reqwest-middleware = { workspace = true, optional = true } 16 | chrono = { workspace = true, features = ["serde"], optional = true } 17 | -------------------------------------------------------------------------------- /crates/gem_bitcoin/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rpc")] 2 | pub mod rpc; 3 | -------------------------------------------------------------------------------- /crates/gem_bitcoin/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | 5 | pub use client::BitcoinClient; 6 | pub use mapper::BitcoinMapper; 7 | -------------------------------------------------------------------------------- /crates/gem_bsc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_bsc" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | 8 | hex = { workspace = true } 9 | itoa = { workspace = true } 10 | anyhow = { workspace = true } 11 | alloy-primitives = { workspace = true } 12 | alloy-sol-types = { workspace = true } 13 | -------------------------------------------------------------------------------- /crates/gem_bsc/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod stake_hub; 2 | -------------------------------------------------------------------------------- /crates/gem_cardano/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_cardano" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | publish = false 6 | 7 | [features] 8 | default = [] 9 | rpc = ["dep:serde_json", "dep:reqwest-middleware", "dep:chrono"] 10 | 11 | [dependencies] 12 | primitives = { path = "../primitives" } 13 | serde = { workspace = true, features = ["derive"] } 14 | 15 | serde_json = { workspace = true, optional = true } 16 | reqwest-middleware = { workspace = true, optional = true } 17 | chrono = { workspace = true, features = ["serde"], optional = true } 18 | -------------------------------------------------------------------------------- /crates/gem_cardano/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rpc")] 2 | pub mod rpc; 3 | -------------------------------------------------------------------------------- /crates/gem_cardano/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | 5 | pub use client::CardanoClient; 6 | pub use mapper::CardanoMapper; 7 | -------------------------------------------------------------------------------- /crates/gem_chain_rpc/tests/integration_test.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use gem_chain_rpc::solana::provider::SolanaProvider; 4 | use gem_solana::client::SolanaRpc; 5 | use primitives::Chain; 6 | 7 | #[tokio::test] 8 | async fn test_get_solana_token_data() -> Result<(), Box> { 9 | let provider = SolanaProvider::new("https://solana-rpc.publicnode.com"); 10 | let token_data = provider 11 | .get_token_data("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v".to_string()) 12 | .await?; 13 | 14 | assert_eq!(token_data.symbol, "USDC"); 15 | assert_eq!(token_data.decimals, 6); 16 | 17 | Ok(()) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /crates/gem_cosmos/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod converter; 2 | 3 | #[cfg(feature = "rpc")] 4 | pub mod rpc; 5 | -------------------------------------------------------------------------------- /crates/gem_cosmos/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | 5 | pub use client::CosmosClient; 6 | pub use mapper::CosmosMapper; 7 | -------------------------------------------------------------------------------- /crates/gem_evm/src/across/contracts/config_store.rs: -------------------------------------------------------------------------------- 1 | use alloy_sol_types::sol; 2 | 3 | sol! { 4 | interface AcrossConfigStore { 5 | function l1TokenConfig(address l1Token) returns (string); 6 | } 7 | } 8 | 9 | // cast call 0x3B03509645713718B78951126E0A6de6f10043f5 "l1TokenConfig(address)(string)" 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 --rpc-url 10 | -------------------------------------------------------------------------------- /crates/gem_evm/src/across/contracts/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod config_store; 2 | pub mod hub_pool; 3 | pub mod multicall_handler; 4 | pub mod spoke_pool; 5 | 6 | pub use config_store::AcrossConfigStore; 7 | pub use hub_pool::HubPoolInterface; 8 | pub use spoke_pool::V3SpokePoolInterface; 9 | -------------------------------------------------------------------------------- /crates/gem_evm/src/across/contracts/multicall_handler.rs: -------------------------------------------------------------------------------- 1 | use alloy_sol_types::sol; 2 | 3 | // https://github.com/across-protocol/contracts/blob/master/contracts/handlers/MulticallHandler.sol 4 | sol! { 5 | struct Call { 6 | address target; 7 | bytes callData; 8 | uint256 value; 9 | } 10 | 11 | struct Instructions { 12 | // Calls that will be attempted. 13 | Call[] calls; 14 | // Where the tokens go if any part of the call fails. 15 | // Leftover tokens are sent here as well if the action succeeds. 16 | address fallbackRecipient; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /crates/gem_evm/src/across/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod contracts; 2 | pub mod deployment; 3 | pub mod fees; 4 | -------------------------------------------------------------------------------- /crates/gem_evm/src/address.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::{Address, AddressError}; 2 | use std::str::FromStr; 3 | 4 | pub fn ethereum_address_checksum(address: &str) -> Result { 5 | let address = Address::from_str(address)?; 6 | Ok(address.to_checksum(None)) 7 | } 8 | -------------------------------------------------------------------------------- /crates/gem_evm/src/chainlink/contract.rs: -------------------------------------------------------------------------------- 1 | use alloy_sol_types::sol; 2 | 3 | // https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol 4 | sol! { 5 | interface AggregatorInterface { 6 | function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); 7 | } 8 | } 9 | 10 | pub const CHAINLINK_ETH_USD_FEED: &str = "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"; 11 | -------------------------------------------------------------------------------- /crates/gem_evm/src/chainlink/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod contract; 2 | -------------------------------------------------------------------------------- /crates/gem_evm/src/lib.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::U256; 2 | use std::str::FromStr; 3 | 4 | pub mod across; 5 | pub mod address; 6 | pub mod chainlink; 7 | pub mod eip712; 8 | pub mod erc20; 9 | pub mod erc2612; 10 | pub mod ether_conv; 11 | pub mod jsonrpc; 12 | pub mod lido; 13 | pub mod multicall3; 14 | pub mod permit2; 15 | pub mod thorchain; 16 | pub mod uniswap; 17 | pub mod weth; 18 | 19 | #[cfg(feature = "typeshare")] 20 | pub mod typeshare; 21 | 22 | #[cfg(feature = "rpc")] 23 | pub mod rpc; 24 | 25 | pub use address::ethereum_address_checksum; 26 | pub use eip712::{eip712_domain_types, EIP712Domain, EIP712Field, EIP712Type, EIP712TypedValue}; 27 | 28 | pub fn parse_u256(value: &str) -> Option { 29 | if let Some(stripped) = value.strip_prefix("0x") { 30 | U256::from_str_radix(stripped, 16).ok() 31 | } else { 32 | U256::from_str(value).ok() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /crates/gem_evm/src/rpc/alchemy/client.rs: -------------------------------------------------------------------------------- 1 | use alloy_rpc_client::{ClientBuilder, RpcClient}; 2 | use anyhow::Result; 3 | use primitives::EVMChain; 4 | use url::Url; 5 | 6 | use crate::rpc::alchemy::{model::alchemy_url, TokenBalances}; 7 | 8 | pub struct AlchemyClient { 9 | client: RpcClient, 10 | pub chain: EVMChain, 11 | } 12 | 13 | impl AlchemyClient { 14 | pub fn new(chain: EVMChain, api_key: &str) -> Self { 15 | let url = alchemy_url(chain, api_key); 16 | let parsed_url = Url::parse(&url).expect("Invalid Alchemy API URL"); 17 | let client = ClientBuilder::default().http(parsed_url); 18 | Self { client, chain } 19 | } 20 | 21 | pub async fn get_token_balances(&self, address: &str) -> Result { 22 | Ok(self.client.request("alchemy_getTokenBalances", (address,)).await?) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /crates/gem_evm/src/rpc/alchemy/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod model; 3 | pub use client::AlchemyClient; 4 | pub use model::{TokenBalance, TokenBalances}; 5 | -------------------------------------------------------------------------------- /crates/gem_evm/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod alchemy; 2 | pub mod client; 3 | pub mod mapper; 4 | pub mod model; 5 | pub mod swap_mapper; 6 | 7 | pub use alchemy::AlchemyClient; 8 | pub use client::EthereumClient; 9 | pub use mapper::EthereumMapper; 10 | -------------------------------------------------------------------------------- /crates/gem_evm/src/thorchain/contracts.rs: -------------------------------------------------------------------------------- 1 | use alloy_sol_types::sol; 2 | 3 | sol! { 4 | interface RouterInterface { 5 | function depositWithExpiry(address inbound_address, address token_address, uint amount, string memo, uint expiry) external; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /crates/gem_evm/src/thorchain/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod contracts; 2 | -------------------------------------------------------------------------------- /crates/gem_evm/src/typeshare.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | #[derive(Debug, Clone, Serialize, Deserialize)] 5 | #[typeshare(swift = "Sendable")] 6 | #[serde(rename_all = "camelCase")] 7 | struct EthereumTransactionReciept { 8 | status: String, 9 | gas_used: String, 10 | effective_gas_price: String, 11 | #[serde(rename = "l1Fee")] 12 | l1_fee: Option, 13 | } 14 | 15 | #[derive(Debug, Clone, Serialize, Deserialize)] 16 | #[typeshare(swift = "Sendable")] 17 | #[serde(rename_all = "camelCase")] 18 | struct EthereumFeeHistory { 19 | reward: Vec>, 20 | #[serde(rename = "baseFeePerGas")] 21 | base_fee_per_gas: Vec, 22 | } 23 | -------------------------------------------------------------------------------- /crates/gem_evm/src/uniswap/contracts/mod.rs: -------------------------------------------------------------------------------- 1 | use alloy_sol_types::sol; 2 | 3 | pub mod v3; 4 | pub mod v4; 5 | 6 | // https://github.com/Uniswap/universal-router/blob/main/contracts/interfaces/IUniversalRouter.sol 7 | sol! { 8 | /// @notice Executes encoded commands along with provided inputs. Reverts if deadline has expired. 9 | /// @param commands A set of concatenated commands, each 1 byte in length 10 | /// @param inputs An array of byte strings containing abi encoded inputs for each command 11 | /// @param deadline The deadline by which the transaction must be executed 12 | #[derive(Debug, PartialEq)] 13 | interface IUniversalRouter { 14 | function execute(bytes calldata commands, bytes[] calldata inputs, uint256 deadline) external payable; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /crates/gem_evm/src/weth.rs: -------------------------------------------------------------------------------- 1 | use alloy_sol_types::sol; 2 | 3 | sol! { 4 | #[derive(Debug, PartialEq)] 5 | interface WETH9 { 6 | function withdraw(uint wad) public; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /crates/gem_hash/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_hash" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | tiny-keccak = { workspace = true } 8 | -------------------------------------------------------------------------------- /crates/gem_hash/src/keccak.rs: -------------------------------------------------------------------------------- 1 | pub fn keccak256(bytes: &[u8]) -> [u8; 32] { 2 | use tiny_keccak::{Hasher, Keccak}; 3 | let mut hasher = Keccak::v256(); 4 | hasher.update(bytes); 5 | 6 | let mut hash = [0u8; 32]; 7 | hasher.finalize(&mut hash); 8 | hash 9 | } 10 | -------------------------------------------------------------------------------- /crates/gem_hash/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod keccak; 2 | -------------------------------------------------------------------------------- /crates/gem_near/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_near" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | 8 | primitives = { path = "../primitives" } 9 | serde = { workspace = true, features = ["derive"] } 10 | serde_json = { workspace = true, optional = true } 11 | 12 | # RPC specific dependencies 13 | jsonrpsee = { workspace = true, features = ["http-client"], optional = true } 14 | chrono = { workspace = true, features = ["serde"], optional = true } 15 | 16 | [features] 17 | default = [] 18 | rpc = ["dep:serde_json", "dep:jsonrpsee", "dep:chrono"] 19 | -------------------------------------------------------------------------------- /crates/gem_near/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rpc")] 2 | pub mod rpc; 3 | -------------------------------------------------------------------------------- /crates/gem_near/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | 5 | pub use client::NearClient; 6 | pub use mapper::NearMapper; 7 | -------------------------------------------------------------------------------- /crates/gem_polkadot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_polkadot" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | primitives = { path = "../primitives" } 8 | serde = { workspace = true, features = ["derive"] } 9 | 10 | # RPC specific dependencies 11 | serde_json = { workspace = true, optional = true } 12 | reqwest-middleware = { workspace = true, features = ["json"], optional = true } 13 | chrono = { workspace = true, features = ["serde"], optional = true } 14 | 15 | [features] 16 | default = [] 17 | rpc = ["dep:serde_json", "dep:reqwest-middleware", "dep:chrono"] 18 | -------------------------------------------------------------------------------- /crates/gem_polkadot/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rpc")] 2 | pub mod rpc; 3 | -------------------------------------------------------------------------------- /crates/gem_polkadot/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | 5 | pub use client::PolkadotClient; 6 | pub use mapper::PolkadotMapper; 7 | -------------------------------------------------------------------------------- /crates/gem_solana/src/jsonrpc.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | 3 | use crate::model::Filter; 4 | 5 | pub const ENCODING_BASE64: &str = "base64"; 6 | pub const ENCODING_BASE58: &str = "base58"; 7 | 8 | pub enum SolanaRpc { 9 | GetProgramAccounts(String, Vec), 10 | GetAccountInfo(String), 11 | GetMultipleAccounts(Vec), 12 | GetEpochInfo, 13 | GetLatestBlockhash, 14 | } 15 | 16 | impl Display for SolanaRpc { 17 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 18 | match self { 19 | SolanaRpc::GetProgramAccounts(_, _) => write!(f, "getProgramAccounts"), 20 | SolanaRpc::GetAccountInfo(_) => write!(f, "getAccountInfo"), 21 | SolanaRpc::GetMultipleAccounts(_) => write!(f, "getMultipleAccounts"), 22 | SolanaRpc::GetEpochInfo => write!(f, "getEpochInfo"), 23 | SolanaRpc::GetLatestBlockhash => write!(f, "getLatestBlockhash"), 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /crates/gem_solana/src/metaplex/collection.rs: -------------------------------------------------------------------------------- 1 | use crate::pubkey::Pubkey; 2 | use borsh::{BorshDeserialize, BorshSerialize}; 3 | 4 | #[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)] 5 | pub struct Collection { 6 | pub verified: bool, 7 | pub key: Pubkey, 8 | } 9 | 10 | #[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)] 11 | pub enum CollectionDetails { 12 | V1 { size: u64 }, 13 | V2 { padding: [u8; 8] }, 14 | } 15 | -------------------------------------------------------------------------------- /crates/gem_solana/src/metaplex/data.rs: -------------------------------------------------------------------------------- 1 | use crate::pubkey::Pubkey; 2 | use borsh::{BorshDeserialize, BorshSerialize}; 3 | 4 | #[derive(BorshSerialize, BorshDeserialize, Default, PartialEq, Eq, Debug, Clone)] 5 | pub struct Data { 6 | /// The name of the asset 7 | pub name: String, 8 | /// The symbol for the asset 9 | pub symbol: String, 10 | /// URI pointing to JSON representing the asset 11 | pub uri: String, 12 | /// Royalty basis points that goes to creators in secondary sales (0-10000) 13 | pub seller_fee_basis_points: u16, 14 | /// Array of creators, optional 15 | pub creators: Option>, 16 | } 17 | 18 | #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] 19 | pub struct Creator { 20 | pub address: Pubkey, 21 | pub verified: bool, 22 | pub share: u8, 23 | } 24 | -------------------------------------------------------------------------------- /crates/gem_solana/src/metaplex/uses.rs: -------------------------------------------------------------------------------- 1 | use borsh::{BorshDeserialize, BorshSerialize}; 2 | 3 | #[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)] 4 | pub enum UseMethod { 5 | Burn, 6 | Multiple, 7 | Single, 8 | } 9 | 10 | #[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)] 11 | pub struct Uses { 12 | // 17 bytes + Option byte 13 | pub use_method: UseMethod, //1 14 | pub remaining: u64, //8 15 | pub total: u64, //8 16 | } 17 | -------------------------------------------------------------------------------- /crates/gem_solana/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | 4 | pub use client::SolanaClient; 5 | -------------------------------------------------------------------------------- /crates/gem_solana/src/typeshare/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod solana_balance; 2 | pub mod solana_blockhash; 3 | pub mod solana_prioritization_fee; 4 | pub mod solana_stake; 5 | pub mod solana_token_account; 6 | pub mod solana_transaction; 7 | pub mod solana_value; 8 | 9 | type Int = u64; 10 | -------------------------------------------------------------------------------- /crates/gem_solana/src/typeshare/solana_balance.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | use super::Int; 5 | 6 | #[typeshare(swift = "Sendable")] 7 | #[derive(Serialize, Deserialize)] 8 | pub struct SolanaBalance { 9 | pub value: Int, 10 | } 11 | 12 | #[typeshare(swift = "Sendable")] 13 | pub struct SolanaBalanceValue { 14 | pub amount: String, 15 | } 16 | -------------------------------------------------------------------------------- /crates/gem_solana/src/typeshare/solana_blockhash.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | #[typeshare(swift = "Sendable")] 5 | #[derive(Serialize, Deserialize)] 6 | #[serde(rename_all = "camelCase")] 7 | pub struct SolanaBlockhashResult { 8 | pub value: SolanaBlockhash, 9 | } 10 | 11 | #[typeshare(swift = "Sendable")] 12 | #[derive(Serialize, Deserialize)] 13 | #[serde(rename_all = "camelCase")] 14 | pub struct SolanaBlockhash { 15 | pub blockhash: String, 16 | } 17 | -------------------------------------------------------------------------------- /crates/gem_solana/src/typeshare/solana_prioritization_fee.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | use super::Int; 5 | 6 | #[typeshare(swift = "Sendable")] 7 | #[derive(Serialize, Deserialize)] 8 | #[serde(rename_all = "camelCase")] 9 | pub struct SolanaPrioritizationFee { 10 | pub prioritization_fee: Int, 11 | } 12 | -------------------------------------------------------------------------------- /crates/gem_solana/src/typeshare/solana_stake.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | use super::Int; 5 | 6 | #[typeshare(swift = "Sendable")] 7 | #[derive(Serialize, Deserialize)] 8 | #[serde(rename_all = "camelCase")] 9 | pub struct SolanaValidators { 10 | pub current: Vec, 11 | } 12 | 13 | #[typeshare(swift = "Sendable")] 14 | #[derive(Serialize, Deserialize)] 15 | #[serde(rename_all = "camelCase")] 16 | pub struct SolanaValidator { 17 | pub vote_pubkey: String, 18 | pub commission: i32, 19 | pub epoch_vote_account: bool, 20 | } 21 | 22 | #[typeshare(swift = "Sendable")] 23 | #[derive(Serialize, Deserialize)] 24 | #[serde(rename_all = "camelCase")] 25 | pub struct SolanaEpoch { 26 | pub epoch: Int, 27 | pub slot_index: Int, 28 | pub slots_in_epoch: Int, 29 | } 30 | -------------------------------------------------------------------------------- /crates/gem_solana/src/typeshare/solana_value.rs: -------------------------------------------------------------------------------- 1 | use typeshare::typeshare; 2 | 3 | #[typeshare(swift = "Sendable")] 4 | #[typeshare(swiftGenericConstraints = "T: Sendable")] 5 | pub struct SolanaValue { 6 | pub value: T, 7 | } 8 | -------------------------------------------------------------------------------- /crates/gem_stellar/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_stellar" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [features] 7 | default = [] 8 | rpc = ["dep:reqwest-middleware", "dep:number_formatter"] 9 | 10 | [dependencies] 11 | serde = { workspace = true, features = ["derive"] } 12 | primitives = { path = "../primitives" } 13 | 14 | # Optional dependencies for the rpc feature 15 | reqwest-middleware = { workspace = true, optional = true, features = ["json"] } 16 | number_formatter = { path = "../number_formatter", optional = true } 17 | -------------------------------------------------------------------------------- /crates/gem_stellar/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rpc")] 2 | pub mod rpc; 3 | -------------------------------------------------------------------------------- /crates/gem_stellar/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | 5 | pub use client::StellarClient; 6 | pub use mapper::StellarMapper; 7 | -------------------------------------------------------------------------------- /crates/gem_sui/src/object_id.rs: -------------------------------------------------------------------------------- 1 | use sui_types::{Address, ObjectId}; 2 | 3 | pub struct ObjectID { 4 | bytes: [u8; 32], 5 | } 6 | 7 | impl ObjectID { 8 | pub fn from(byte: u8) -> Self { 9 | let mut bytes = [0u8; 32]; 10 | bytes[31] = byte; 11 | Self { bytes } 12 | } 13 | 14 | pub fn addr(&self) -> Address { 15 | Address::new(self.bytes) 16 | } 17 | 18 | pub fn id(&self) -> ObjectId { 19 | ObjectId::new(self.bytes) 20 | } 21 | } 22 | 23 | impl From for ObjectID { 24 | fn from(byte: u8) -> Self { 25 | ObjectID::from(byte) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /crates/gem_sui/src/rpc/constants.rs: -------------------------------------------------------------------------------- 1 | pub const SUI_STAKE_EVENT: &str = "0x3::validator::StakingRequestEvent"; 2 | pub const SUI_UNSTAKE_EVENT: &str = "0x3::validator::UnstakingRequestEvent"; 3 | -------------------------------------------------------------------------------- /crates/gem_sui/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod constants; 3 | pub mod mapper; 4 | pub mod model; 5 | 6 | pub use client::SuiClient; 7 | pub use mapper::SuiMapper; 8 | -------------------------------------------------------------------------------- /crates/gem_ton/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_ton" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [features] 7 | default = [] 8 | rpc = ["dep:reqwest-middleware", "dep:chrono", "dep:serde_serializers"] 9 | 10 | 11 | [dependencies] 12 | thiserror = { workspace = true } 13 | base64 = { workspace = true } 14 | bitstream-io = "2.6.0" 15 | num-bigint = { workspace = true } 16 | num-traits = { workspace = true } 17 | sha2 = { workspace = true } 18 | hex = { workspace = true } 19 | lazy_static = { workspace = true } 20 | crc = "3" 21 | serde = { workspace = true } 22 | serde_json = { workspace = true } 23 | anyhow = { workspace = true } 24 | primitives = { path = "../primitives" } 25 | 26 | reqwest-middleware = { workspace = true, features = ["json"], optional = true } 27 | chrono = { workspace = true, features = ["serde"], optional = true } 28 | serde_serializers = { path = "../serde_serializers", optional = true } 29 | -------------------------------------------------------------------------------- /crates/gem_ton/src/address/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | #[error("Invalid address (Address: {address}, message: {message})")] 5 | pub struct TonAddressParseError { 6 | address: String, 7 | message: String, 8 | } 9 | 10 | impl TonAddressParseError { 11 | pub fn new(address: A, message: M) -> TonAddressParseError { 12 | TonAddressParseError { 13 | address: address.to_string(), 14 | message: message.to_string(), 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /crates/gem_ton/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rpc")] 2 | pub mod rpc; 3 | 4 | // Taken from https://github.com/ston-fi/tonlib-rs, it should be modular crate with feature flags 5 | pub mod address; 6 | pub mod cell; 7 | -------------------------------------------------------------------------------- /crates/gem_ton/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod mapper; 3 | pub mod model; 4 | pub mod model_rpc; 5 | 6 | pub use client::TonClient; 7 | pub use mapper::TonMapper; 8 | -------------------------------------------------------------------------------- /crates/gem_ton/src/rpc/model_rpc.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, Serialize, Deserialize)] 4 | pub struct JettonWallet { 5 | pub balance: String, 6 | pub jetton: String, 7 | } 8 | 9 | #[derive(Debug, Clone, Serialize, Deserialize)] 10 | pub struct AssetsBalances { 11 | pub jetton_wallets: Vec, 12 | } 13 | -------------------------------------------------------------------------------- /crates/gem_tron/src/lib.rs: -------------------------------------------------------------------------------- 1 | // gem_tron/src/lib.rs 2 | 3 | pub mod address; 4 | 5 | // RPC module, feature-gated 6 | #[cfg(feature = "rpc")] 7 | pub mod rpc; 8 | -------------------------------------------------------------------------------- /crates/gem_tron/src/rpc/constants.rs: -------------------------------------------------------------------------------- 1 | pub const NAME_SELECTOR: &str = "name()"; 2 | pub const SYMBOL_SELECTOR: &str = "symbol()"; 3 | pub const DECIMALS_SELECTOR: &str = "decimals()"; 4 | pub const DEFAULT_OWNER_ADDRESS: &str = "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb"; 5 | -------------------------------------------------------------------------------- /crates/gem_tron/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod constants; 3 | pub mod mapper; 4 | pub mod model; 5 | 6 | pub use client::TronClient; 7 | pub use mapper::TronMapper; 8 | -------------------------------------------------------------------------------- /crates/gem_xrp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gem_xrp" 3 | version = { workspace = true } 4 | edition = "2024" 5 | 6 | [features] 7 | default = [] 8 | typeshare = ["dep:typeshare"] 9 | rpc = ["dep:chrono", "dep:reqwest-middleware"] 10 | 11 | [dependencies] 12 | serde = { workspace = true, features = ["derive"] } 13 | serde_json = { workspace = true } 14 | thiserror = { workspace = true } 15 | anyhow = { workspace = true } 16 | async-trait = { workspace = true } 17 | hex = { workspace = true } 18 | primitives = { path = "../primitives" } 19 | number_formatter = { path = "../number_formatter" } 20 | 21 | typeshare = { workspace = true, optional = true } 22 | 23 | reqwest-middleware = { workspace = true, features = ["json"], optional = true } 24 | chrono = { workspace = true, features = ["serde"], optional = true } 25 | -------------------------------------------------------------------------------- /crates/gem_xrp/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # gem_xrp 2 | //! 3 | //! This crate provides XRP Ledger specific functionalities for Gem Wallet. 4 | //! It includes modules for XRP models and rpc operations, activated by feature flags. 5 | 6 | #[cfg(feature = "typeshare")] 7 | pub mod typeshare; 8 | 9 | #[cfg(feature = "rpc")] 10 | pub mod rpc; 11 | #[cfg(feature = "rpc")] 12 | pub use rpc::constants::*; 13 | -------------------------------------------------------------------------------- /crates/gem_xrp/src/rpc/constants.rs: -------------------------------------------------------------------------------- 1 | pub const XRP_EPOCH_OFFSET_SECONDS: i64 = 946684800; // XRP epoch starts 2000-01-01 2 | pub const XRP_DEFAULT_ASSET_DECIMALS: i32 = 15; 3 | -------------------------------------------------------------------------------- /crates/gem_xrp/src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | mod client; 2 | pub mod constants; 3 | pub mod mapper; 4 | pub mod model; 5 | 6 | pub use self::client::XRPClient; 7 | pub use self::mapper::XRPMapper; 8 | -------------------------------------------------------------------------------- /crates/job_runner/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "job_runner" 3 | version = "1.0.0" 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | tokio = { workspace = true } 8 | chrono = { workspace = true } 9 | -------------------------------------------------------------------------------- /crates/localizer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "localizer" 3 | version = "1.0.0" 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | i18n-embed = { workspace = true } 8 | i18n-embed-fl = { workspace = true } 9 | once_cell = { workspace = true } 10 | rust-embed = { workspace = true } 11 | -------------------------------------------------------------------------------- /crates/localizer/i18n.toml: -------------------------------------------------------------------------------- 1 | # (Required) The language identifier of the language used in the 2 | # source code for gettext system, and the primary fallback language 3 | # (for which all strings must be present) when using the fluent 4 | # system. 5 | fallback_language = "en" 6 | 7 | # (Optional) Use the fluent localization system. 8 | [fluent] 9 | # (Required) The path to the assets directory. 10 | # The paths inside the assets directory should be structured like so: 11 | # `assets_dir/{language}/{domain}.ftl` 12 | assets_dir = "i18n" -------------------------------------------------------------------------------- /crates/localizer/tests/localizer.rs: -------------------------------------------------------------------------------- 1 | use localizer::LanguageLocalizer; 2 | 3 | /// Test that the expected languages and fallback language are 4 | /// available. 5 | #[test] 6 | fn test_specific_language() { 7 | let localizer = LanguageLocalizer::new_with_language("es"); 8 | assert_eq!(&localizer.test(), "Prueba"); 9 | 10 | localizer.select_language("pt-BR").unwrap(); 11 | 12 | assert_eq!(&localizer.test(), "Teste"); 13 | } 14 | 15 | #[test] 16 | fn test_invalid_language_fallback() { 17 | let localizer = LanguageLocalizer::new_with_language("unknown"); 18 | assert_eq!(&localizer.test(), "Test"); 19 | } 20 | 21 | #[test] 22 | fn test_pass_argment() { 23 | let localizer = LanguageLocalizer::new_with_language("es"); 24 | assert_eq!(&localizer.notification_transfer_title(true, "1 BTC"), "💸 Enviado: \u{2068}1 BTC\u{2069}"); 25 | } 26 | -------------------------------------------------------------------------------- /crates/name_resolver/README.md: -------------------------------------------------------------------------------- 1 | # Name Resolver 2 | 3 | ## Supported Name Providers 4 | 5 | - [x] [Ethereum Name Service](https://ens.domains/) 6 | - - .eth 7 | - [x] [Base Name Service](https://www.basename.app/) 8 | - - .base 9 | - [x] [Unstoppable Domains](https://unstoppabledomains.com/) 10 | - - .crypto 11 | - [x] [Solana Name Service](https://www.sns.id/) 12 | - - .sol 13 | - [x] [TON Domains](https://dns.ton.org/) 14 | - - .ton 15 | - [x] [Aptos Names](https://www.aptosnames.com/) 16 | - - .apt 17 | - [x] [d.id](https://d.id/) 18 | - - .bit 19 | - [x] [Interchain Nameservice](https://www.icns.xyz/) 20 | - - .atom 21 | - - .osmo 22 | - [x] [Lens](https://www.lens.xyz/) 23 | - - .lens 24 | - [x] [eths.center](https://eths.center/) 25 | - - .tree 26 | - [x] [Space ID](https://space.id) 27 | - - .bnb 28 | - [x] [Sui Name Service](https://suins.io/) 29 | - - .sui 30 | -------------------------------------------------------------------------------- /crates/name_resolver/src/base/contract.rs: -------------------------------------------------------------------------------- 1 | use alloy_sol_types::sol; 2 | 3 | sol! { 4 | /// Interface for the L2Resolver 5 | interface L2Resolver { 6 | /// Returns the address associated with a node. 7 | /// @param node The ENS node to query. 8 | /// @return The associated address. 9 | function addr(bytes32 node) external view returns (address); 10 | 11 | /// Returns the text record associated with an ENS node and key. 12 | /// @param node The ENS node to query. 13 | /// @param key The text record key. 14 | /// @return The text record. 15 | function text(bytes32 node, string key) external view returns (string); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /crates/name_resolver/src/base/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod contract; 2 | pub mod provider; 3 | 4 | pub use provider::Basenames; 5 | -------------------------------------------------------------------------------- /crates/name_resolver/src/codec/mod.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | pub trait Codec { 3 | fn encode(bytes: Vec) -> Result>; 4 | fn decode(string: &str) -> Result, Box>; 5 | } 6 | -------------------------------------------------------------------------------- /crates/name_resolver/src/ens/mod.rs: -------------------------------------------------------------------------------- 1 | mod client; 2 | mod contract; 3 | mod normalizer; 4 | mod provider; 5 | 6 | pub use client::ENSClient; 7 | pub use normalizer::normalize_domain; 8 | -------------------------------------------------------------------------------- /crates/name_resolver/src/ens/normalizer.rs: -------------------------------------------------------------------------------- 1 | use idna::uts46::{AsciiDenyList, DnsLength, Hyphens, Uts46}; 2 | 3 | pub fn normalize_domain(name: &str) -> Result { 4 | let uts46 = Uts46::new(); 5 | let flags = AsciiDenyList::STD3; 6 | let normalized = uts46.to_ascii(name.as_bytes(), flags, Hyphens::Allow, DnsLength::Ignore)?; 7 | Ok(normalized.into_owned()) 8 | } 9 | -------------------------------------------------------------------------------- /crates/name_resolver/src/hyperliquid/contracts.rs: -------------------------------------------------------------------------------- 1 | use alloy_sol_types::sol; 2 | 3 | sol! { 4 | interface Router { 5 | function getCurrentRegistrator() external view returns (address); 6 | } 7 | 8 | interface Registrator { 9 | function getFullRecordJSON(bytes32 _namehash) external view returns (string); 10 | } 11 | 12 | interface HyperliquidNames { 13 | function tokenIdToAddress(uint256 _tokenId) external view returns (address); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/name_resolver/src/hyperliquid/mod.rs: -------------------------------------------------------------------------------- 1 | mod contracts; 2 | mod provider; 3 | mod record; 4 | 5 | pub use provider::Hyperliquid; 6 | -------------------------------------------------------------------------------- /crates/name_resolver/src/hyperliquid/record.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::collections::HashMap; 3 | 4 | #[derive(Debug, Deserialize, Serialize)] 5 | pub struct Record { 6 | pub name: NameRecord, 7 | pub data: DataRecord, 8 | } 9 | 10 | #[derive(Debug, Deserialize, Serialize)] 11 | pub struct NameRecord { 12 | pub owner: String, 13 | pub name: String, 14 | pub expiry: String, 15 | } 16 | 17 | #[derive(Debug, Deserialize, Serialize)] 18 | #[serde(rename_all = "camelCase")] 19 | pub struct DataRecord { 20 | pub chain_addresses: HashMap, 21 | } 22 | -------------------------------------------------------------------------------- /crates/nft/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nft" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | serde_json = { workspace = true } 9 | reqwest = { workspace = true } 10 | futures.workspace = true 11 | async-trait = { workspace = true } 12 | 13 | primitives = { path = "../primitives" } 14 | gem_evm = { path = "../gem_evm" } 15 | gem_solana = { path = "../gem_solana" } 16 | gem_chain_rpc = { path = "../gem_chain_rpc" } -------------------------------------------------------------------------------- /crates/nft/src/magiceden/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod model; 3 | pub use client::MagicEdenClient; 4 | pub mod mapper; 5 | pub mod provider; 6 | -------------------------------------------------------------------------------- /crates/nft/src/magiceden/model.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | #[derive(Deserialize, Clone, Debug)] 4 | #[serde(rename_all = "camelCase")] 5 | pub struct Nft { 6 | pub mint_address: String, 7 | pub name: String, 8 | pub image: String, 9 | pub collection: String, 10 | pub attributes: Vec, 11 | } 12 | 13 | #[derive(Deserialize, Clone, Debug)] 14 | pub struct Trait { 15 | pub trait_type: String, 16 | pub value: serde_json::Value, 17 | } 18 | 19 | #[derive(Deserialize)] 20 | #[serde(rename_all = "camelCase")] 21 | pub struct Collection { 22 | pub symbol: Option, 23 | pub name: String, 24 | pub description: String, 25 | pub image: String, 26 | pub on_chain_collection_address: String, 27 | pub twitter: Option, 28 | pub discord: Option, 29 | pub website: Option, 30 | } 31 | -------------------------------------------------------------------------------- /crates/nft/src/nftscan/evm/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mapper; 2 | pub mod model; 3 | -------------------------------------------------------------------------------- /crates/nft/src/nftscan/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod evm; 3 | pub mod model; 4 | pub mod provider; 5 | pub mod solana; 6 | pub mod ton; 7 | -------------------------------------------------------------------------------- /crates/nft/src/nftscan/model.rs: -------------------------------------------------------------------------------- 1 | use primitives::Chain; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | pub fn get_chain(chain: Chain) -> Option { 5 | match chain { 6 | Chain::Ethereum => Some("eth".to_owned()), 7 | Chain::Solana => Some("sol".to_owned()), 8 | _ => None, 9 | } 10 | } 11 | 12 | #[derive(Debug, Clone, Serialize, Deserialize)] 13 | pub struct NFTAttribute { 14 | pub attribute_name: String, 15 | pub attribute_value: String, 16 | } 17 | 18 | impl NFTAttribute { 19 | pub fn as_primitive(&self) -> Option { 20 | if self.attribute_value.is_empty() || self.attribute_value.len() > 18 { 21 | return None; 22 | } 23 | Some(primitives::NFTAttribute { 24 | name: self.attribute_name.clone(), 25 | value: self.attribute_value.clone(), 26 | percentage: None, 27 | }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /crates/nft/src/opensea/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod model; 3 | pub use client::OpenSeaClient; 4 | pub mod mapper; 5 | pub mod provider; 6 | -------------------------------------------------------------------------------- /crates/number_formatter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "number_formatter" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | num-bigint = { workspace = true } 8 | num-traits = { workspace = true } 9 | bigdecimal = { workspace = true } 10 | rusty-money = { workspace = true } 11 | -------------------------------------------------------------------------------- /crates/number_formatter/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod big_number_formatter; 2 | pub use big_number_formatter::BigNumberFormatter; 3 | pub mod number_formatter; 4 | pub use number_formatter::NumberFormatter; 5 | -------------------------------------------------------------------------------- /crates/pricer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pricer" 3 | edition = { workspace = true } 4 | version = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | serde_json = { workspace = true } 9 | chrono = { workspace = true } 10 | redis = { workspace = true } 11 | 12 | primitives = { path = "../primitives" } 13 | number_formatter = { path = "../number_formatter" } 14 | storage = { path = "../storage" } 15 | api_connector = { path = "../api_connector" } 16 | localizer = { path = "../../crates/localizer" } 17 | cacher = { path = "../../crates/cacher" } -------------------------------------------------------------------------------- /crates/pricer/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod chart_client; 2 | pub mod markets_client; 3 | pub mod price_alert_client; 4 | pub mod price_client; 5 | 6 | pub use chart_client::ChartClient; 7 | pub use markets_client::MarketsClient; 8 | pub use price_alert_client::{PriceAlertClient, PriceAlertNotification, PriceAlertRules}; 9 | pub use price_client::PriceClient; 10 | -------------------------------------------------------------------------------- /crates/pricer_dex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pricer_dex" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | serde_json = { workspace = true } 9 | async-trait = { workspace = true } 10 | base64 = { workspace = true } 11 | chrono = { workspace = true } 12 | 13 | primitives = { path = "../primitives" } 14 | gem_chain_rpc = { path = "../gem_chain_rpc" } 15 | gem_solana = { path = "../gem_solana" } 16 | 17 | [dev-dependencies] 18 | tokio.workspace = true 19 | 20 | [[test]] 21 | name = "integration_test" 22 | test = false 23 | -------------------------------------------------------------------------------- /crates/pricer_dex/src/pyth/decoder.rs: -------------------------------------------------------------------------------- 1 | use base64::{engine::general_purpose, Engine as _}; 2 | 3 | use super::model::Price; 4 | 5 | // https://github.com/pyth-network/pyth-sdk-rs/blob/main/pyth-sdk-solana/src/state.rs#L288 6 | pub fn decode_price_account(base64_str: &str) -> Result> { 7 | let data = general_purpose::STANDARD.decode(base64_str)?; 8 | let price_exponent = i32::from_le_bytes(data[20..24].try_into()?); 9 | let price = i64::from_le_bytes(data[208..216].try_into()?); 10 | 11 | // let last_slot = i64::from_le_bytes(account_data[32..40].try_into()?); 12 | // println!("🔹 Last slot: {}", last_slot); 13 | 14 | let scaled_price = price as f64 * 10f64.powi(price_exponent); 15 | 16 | Ok(Price { price: scaled_price }) 17 | } 18 | -------------------------------------------------------------------------------- /crates/pricer_dex/src/pyth/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod decoder; 3 | pub mod mapper; 4 | pub mod model; 5 | pub mod provider; 6 | -------------------------------------------------------------------------------- /crates/pricer_dex/src/pyth/model.rs: -------------------------------------------------------------------------------- 1 | // https://github.com/pyth-network/pyth-sdk-rs/blob/8c56e4f6a3efee94da9cafa614aba94c29c19376/pyth-sdk-solana/src/state.rs#L288 2 | /// Represents a price update (latest price, confidence, status) 3 | #[repr(C)] 4 | #[derive(Clone, Copy, Debug)] 5 | pub struct Price { 6 | pub price: f64, 7 | } 8 | -------------------------------------------------------------------------------- /crates/pricer_dex/tests/integration_test.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use pricer_dex::{pyth::client::PythClient, PriceChainProvider, PythProvider}; 4 | use primitives::Chain; 5 | 6 | #[tokio::test] 7 | async fn test_get_chain_prices() { 8 | let provider = PythProvider { 9 | pyth_client: PythClient::new("http://pythnet.rpcpool.com"), 10 | }; 11 | let chains = vec![Chain::Bitcoin, Chain::Ethereum]; 12 | let result = provider.get_chain_prices(chains.clone()).await; 13 | 14 | assert!(result.ok().unwrap().len() == chains.len()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /crates/primitives/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "primitives" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | typeshare = { workspace = true } 8 | serde = { workspace = true } 9 | serde_json = { workspace = true } 10 | chrono = { workspace = true } 11 | strum = { workspace = true } 12 | strum_macros = { workspace = true } 13 | anyhow = { workspace = true } 14 | urlencoding = { workspace = true } 15 | url = { workspace = true } 16 | -------------------------------------------------------------------------------- /crates/primitives/src/account.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Equatable, Hashable, Sendable")] 2 | #[serde(rename_all = "camelCase")] 3 | struct Account { 4 | chain: Chain, 5 | address: String, 6 | derivation_path: String, 7 | extended_public_key: Option, 8 | } 9 | -------------------------------------------------------------------------------- /crates/primitives/src/address_formatter.rs: -------------------------------------------------------------------------------- 1 | use crate::chain::Chain; 2 | 3 | pub struct AddressFormatter {} 4 | 5 | impl AddressFormatter { 6 | pub fn short(_chain: Chain, address: &str) -> String { 7 | let len = address.len(); 8 | if len < 10 { 9 | return address.to_string(); 10 | } 11 | let first_four = if address.starts_with("0x") { &address[..6] } else { &address[..4] }; 12 | let last_four = &address[len - 4..]; 13 | format!("{}...{}", first_four, last_four) 14 | } 15 | } 16 | 17 | #[cfg(test)] 18 | mod tests { 19 | use super::*; 20 | 21 | #[test] 22 | fn test_short_address() { 23 | assert_eq!(AddressFormatter::short(Chain::Bitcoin, "1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2"), "1BvB...NVN2"); 24 | assert_eq!( 25 | AddressFormatter::short(Chain::Ethereum, "0x1CeDC0f3Af8f9841B0a1F5c1a4DDc6e1a1629074"), 26 | "0x1CeD...9074" 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /crates/primitives/src/asset_address.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use crate::AssetId; 4 | 5 | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] 6 | pub struct AssetAddress { 7 | pub asset_id: AssetId, 8 | pub address: String, 9 | } 10 | 11 | impl AssetAddress { 12 | pub fn new(asset_id: AssetId, address: String) -> Self { 13 | Self { asset_id, address } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/primitives/src/asset_balance.rs: -------------------------------------------------------------------------------- 1 | use crate::AssetId; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] 5 | #[serde(rename_all = "camelCase")] 6 | pub struct AssetBalance { 7 | pub asset_id: AssetId, 8 | pub balance: String, 9 | } 10 | 11 | impl AssetBalance { 12 | pub fn new(asset_id: AssetId, balance: String) -> Self { 13 | Self { asset_id, balance } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/primitives/src/asset_data.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Equatable, Hashable, Sendable")] 2 | struct AssetData { 3 | asset: Asset, 4 | balance: Balance, 5 | account: Account, 6 | price: Option, 7 | price_alerts: Vec, 8 | metadata: AssetMetaData, 9 | } 10 | 11 | #[typeshare(swift = "Equatable, Hashable, Sendable")] 12 | struct AssetAddress { 13 | asset: Asset, 14 | address: String, 15 | } -------------------------------------------------------------------------------- /crates/primitives/src/asset_metadata.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Equatable, Hashable, Sendable")] 2 | struct AssetMetaData { 3 | #[serde(rename = "isEnabled")] 4 | is_enabled: bool, 5 | #[serde(rename = "isBuyEnabled")] 6 | is_buy_enabled: bool, 7 | #[serde(rename = "isSellEnabled")] 8 | is_sell_enabled: bool, 9 | #[serde(rename = "isSwapEnabled")] 10 | is_swap_enabled: bool, 11 | #[serde(rename = "isStakeEnabled")] 12 | is_stake_enabled: bool, 13 | #[serde(rename = "isPinned")] 14 | is_pinned: bool, 15 | #[serde(rename = "isActive")] 16 | is_active: bool, 17 | #[serde(rename = "stakingApr")] 18 | staking_apr: Option, 19 | #[serde(rename = "rankScore")] 20 | rank_score: i32, 21 | } 22 | -------------------------------------------------------------------------------- /crates/primitives/src/asset_order.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | #[derive(Debug, Clone, Serialize, Deserialize)] 5 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 6 | #[serde(rename_all = "camelCase")] 7 | pub enum AssetOrder { 8 | PriceChange24hAsc, 9 | PriceChange24hDesc, 10 | } 11 | -------------------------------------------------------------------------------- /crates/primitives/src/balance.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct Balance { 3 | available: BigInt, 4 | frozen: BigInt, 5 | locked: BigInt, 6 | staked: BigInt, 7 | pending: BigInt, 8 | rewards: BigInt, 9 | } 10 | -------------------------------------------------------------------------------- /crates/primitives/src/balance_type.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 2 | pub enum BalanceType { 3 | available, 4 | locked, 5 | frozen, 6 | staked, 7 | pending, 8 | rewards, 9 | reserved, 10 | } 11 | -------------------------------------------------------------------------------- /crates/primitives/src/banner.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Equatable, Sendable")] 2 | #[serde(rename_all = "camelCase")] 3 | pub struct Banner { 4 | wallet: Option, 5 | asset: Option, 6 | chain: Option, 7 | event: BannerEvent, 8 | state: BannerState, 9 | } 10 | 11 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 12 | #[serde(rename_all = "camelCase")] 13 | pub enum BannerEvent { 14 | Stake, 15 | AccountActivation, 16 | EnableNotifications, 17 | AccountBlockedMultiSignature, 18 | ActivateAsset, 19 | } 20 | 21 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 22 | #[serde(rename_all = "camelCase")] 23 | pub enum BannerState { 24 | Active, 25 | Cancelled, 26 | AlwaysActive, 27 | } 28 | -------------------------------------------------------------------------------- /crates/primitives/src/chain_address.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use crate::Chain; 4 | 5 | #[derive(Serialize, Deserialize, Clone, Debug)] 6 | pub struct ChainAddress { 7 | pub chain: Chain, 8 | pub address: String, 9 | } 10 | 11 | impl ChainAddress { 12 | pub fn new(chain: Chain, address: String) -> Self { 13 | Self { chain, address } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/primitives/src/chain_bitcoin.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use strum::EnumIter; 3 | use strum_macros::{AsRefStr, EnumString}; 4 | use typeshare::typeshare; 5 | 6 | #[derive(Copy, Clone, Debug, Serialize, Deserialize, EnumIter, AsRefStr, EnumString)] 7 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 8 | #[serde(rename_all = "lowercase")] 9 | #[strum(serialize_all = "lowercase")] 10 | pub enum BitcoinChain { 11 | Bitcoin, 12 | BitcoinCash, 13 | Litecoin, 14 | Doge, 15 | } 16 | -------------------------------------------------------------------------------- /crates/primitives/src/chain_cosmos.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use strum::EnumIter; 3 | use strum_macros::{AsRefStr, EnumString}; 4 | use typeshare::typeshare; 5 | 6 | #[derive(Copy, Clone, Debug, Serialize, Deserialize, EnumString)] 7 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 8 | #[serde(rename_all = "lowercase")] 9 | #[strum(serialize_all = "lowercase")] 10 | pub enum CosmosChain { 11 | Cosmos, 12 | Osmosis, 13 | Celestia, 14 | Thorchain, 15 | Injective, 16 | Sei, 17 | Noble, 18 | } 19 | 20 | #[derive(Copy, Clone, Debug, Serialize, Deserialize, EnumIter, AsRefStr, EnumString)] 21 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 22 | #[serde(rename_all = "lowercase")] 23 | #[strum(serialize_all = "lowercase")] 24 | pub enum CosmosDenom { 25 | Rune, 26 | Uatom, 27 | Uosmo, 28 | Utia, 29 | Inj, 30 | Usei, 31 | Uusdc, 32 | } 33 | -------------------------------------------------------------------------------- /crates/primitives/src/chain_type.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use strum::{AsRefStr, EnumString}; 3 | use typeshare::typeshare; 4 | 5 | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, AsRefStr, EnumString)] 6 | #[typeshare(swift = "Equatable, CaseIterable, Hashable, Sendable")] 7 | #[serde(rename_all = "lowercase")] 8 | #[strum(serialize_all = "lowercase")] 9 | pub enum ChainType { 10 | Ethereum, 11 | Bitcoin, 12 | Solana, 13 | Cosmos, 14 | Ton, 15 | Tron, 16 | Aptos, 17 | Sui, 18 | Xrp, 19 | Near, 20 | Stellar, 21 | Algorand, 22 | Polkadot, 23 | Cardano, 24 | } 25 | -------------------------------------------------------------------------------- /crates/primitives/src/currency.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | #[derive(Debug, Clone, Serialize, Deserialize)] 5 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 6 | pub enum Currency { 7 | MXN, 8 | CHF, 9 | CNY, 10 | THB, 11 | HUF, 12 | AUD, 13 | IDR, 14 | RUB, 15 | ZAR, 16 | EUR, 17 | NZD, 18 | SAR, 19 | SGD, 20 | BMD, 21 | KWD, 22 | HKD, 23 | JPY, 24 | GBP, 25 | DKK, 26 | KRW, 27 | PHP, 28 | CLP, 29 | TWD, 30 | PKR, 31 | BRL, 32 | CAD, 33 | BHD, 34 | MMK, 35 | VEF, 36 | VND, 37 | CZK, 38 | TRY, 39 | INR, 40 | ARS, 41 | BDT, 42 | NOK, 43 | USD, 44 | LKR, 45 | ILS, 46 | PLN, 47 | NGN, 48 | UAH, 49 | XDR, 50 | MYR, 51 | AED, 52 | SEK, 53 | } 54 | -------------------------------------------------------------------------------- /crates/primitives/src/device.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | use crate::{platform::Platform, PlatformStore}; 5 | 6 | #[derive(Debug, Clone, Serialize, Deserialize)] 7 | #[typeshare(swift = "Equatable, Sendable")] 8 | #[serde(rename_all = "camelCase")] 9 | pub struct Device { 10 | pub id: String, 11 | pub platform: Platform, 12 | pub platform_store: Option, 13 | pub token: String, 14 | pub locale: String, 15 | pub version: String, 16 | pub currency: String, 17 | pub is_push_enabled: bool, 18 | pub is_price_alerts_enabled: Option, 19 | pub subscriptions_version: i32, 20 | } 21 | -------------------------------------------------------------------------------- /crates/primitives/src/encoding_type.rs: -------------------------------------------------------------------------------- 1 | use typeshare::typeshare; 2 | 3 | #[derive(Clone, Debug, PartialEq)] 4 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 5 | pub enum EncodingType { 6 | Hex, 7 | Base58, 8 | } 9 | -------------------------------------------------------------------------------- /crates/primitives/src/explorers/algorand.rs: -------------------------------------------------------------------------------- 1 | use crate::block_explorer::{BlockExplorer, Metadata}; 2 | 3 | pub struct AlgorandAllo { 4 | pub meta: Metadata, 5 | } 6 | 7 | impl AlgorandAllo { 8 | pub fn new() -> Box { 9 | Box::new(Self { 10 | meta: Metadata { 11 | name: "Allo", 12 | base_url: "https://allo.info", 13 | }, 14 | }) 15 | } 16 | } 17 | 18 | impl BlockExplorer for AlgorandAllo { 19 | fn name(&self) -> String { 20 | self.meta.name.into() 21 | } 22 | fn get_tx_url(&self, hash: &str) -> String { 23 | format!("{}/tx/{}", self.meta.base_url, hash) 24 | } 25 | fn get_address_url(&self, address: &str) -> String { 26 | format!("{}/account/{}", self.meta.base_url, address) 27 | } 28 | fn get_validator_url(&self, validator: &str) -> Option { 29 | self.get_address_url(validator).into() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /crates/primitives/src/explorers/cardano.rs: -------------------------------------------------------------------------------- 1 | use crate::block_explorer::{BlockExplorer, Metadata}; 2 | 3 | pub struct Cardanocan { 4 | pub meta: Metadata, 5 | } 6 | 7 | impl Cardanocan { 8 | pub fn new() -> Box { 9 | Box::new(Self { 10 | meta: Metadata { 11 | name: "CardanoScan", 12 | base_url: "https://cardanoscan.io", 13 | }, 14 | }) 15 | } 16 | } 17 | 18 | impl BlockExplorer for Cardanocan { 19 | fn name(&self) -> String { 20 | self.meta.name.into() 21 | } 22 | fn get_tx_url(&self, hash: &str) -> String { 23 | format!("{}/transaction/{}", self.meta.base_url, hash) 24 | } 25 | fn get_address_url(&self, address: &str) -> String { 26 | format!("{}/address/{}", self.meta.base_url, address) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/primitives/src/explorers/mayanscan.rs: -------------------------------------------------------------------------------- 1 | use crate::block_explorer::{BlockExplorer, Metadata}; 2 | 3 | pub struct MayanScan { 4 | pub meta: Metadata, 5 | } 6 | 7 | impl MayanScan { 8 | pub fn new() -> Box { 9 | Box::new(Self { 10 | meta: Metadata { 11 | name: "Mayan Explorer", 12 | base_url: "https://explorer.mayan.finance", 13 | }, 14 | }) 15 | } 16 | } 17 | impl BlockExplorer for MayanScan { 18 | fn name(&self) -> String { 19 | self.meta.name.into() 20 | } 21 | fn get_tx_url(&self, hash: &str) -> String { 22 | format!("{}/tx/{}", self.meta.base_url, hash) 23 | } 24 | // this method is not supported on mayan 25 | fn get_address_url(&self, address: &str) -> String { 26 | format!("{}/address/{}", self.meta.base_url, address) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/primitives/src/explorers/mempool.rs: -------------------------------------------------------------------------------- 1 | use crate::block_explorer::{BlockExplorer, Metadata}; 2 | 3 | pub struct Mempool { 4 | pub meta: Metadata, 5 | } 6 | 7 | impl Mempool { 8 | pub fn new() -> Box { 9 | Box::new(Self { 10 | meta: Metadata { 11 | name: "Mempool", 12 | base_url: "https://mempool.space", 13 | }, 14 | }) 15 | } 16 | } 17 | 18 | impl BlockExplorer for Mempool { 19 | fn name(&self) -> String { 20 | self.meta.name.into() 21 | } 22 | fn get_tx_url(&self, hash: &str) -> String { 23 | format!("{}/tx/{}", self.meta.base_url, hash) 24 | } 25 | fn get_address_url(&self, address: &str) -> String { 26 | format!("{}/address/{}", self.meta.base_url, address) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/primitives/src/explorers/near.rs: -------------------------------------------------------------------------------- 1 | use crate::block_explorer::{BlockExplorer, Metadata}; 2 | 3 | pub struct NearBlocks { 4 | pub meta: Metadata, 5 | } 6 | 7 | impl NearBlocks { 8 | pub fn new() -> Box { 9 | Box::new(Self { 10 | meta: Metadata { 11 | name: "Near", 12 | base_url: "https://nearblocks.io", 13 | }, 14 | }) 15 | } 16 | } 17 | 18 | impl BlockExplorer for NearBlocks { 19 | fn name(&self) -> String { 20 | self.meta.name.into() 21 | } 22 | fn get_tx_url(&self, hash: &str) -> String { 23 | format!("{}/txns/{}", self.meta.base_url, hash) 24 | } 25 | fn get_address_url(&self, address: &str) -> String { 26 | format!("{}/address/{}", self.meta.base_url, address) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/primitives/src/explorers/socketscan.rs: -------------------------------------------------------------------------------- 1 | use crate::block_explorer::{BlockExplorer, Metadata}; 2 | 3 | pub struct SocketScan { 4 | pub meta: Metadata, 5 | } 6 | 7 | impl SocketScan { 8 | pub fn new() -> Box { 9 | Box::new(Self { 10 | meta: Metadata { 11 | name: "SocketScan", 12 | base_url: "https://socketscan.io", 13 | }, 14 | }) 15 | } 16 | } 17 | impl BlockExplorer for SocketScan { 18 | fn name(&self) -> String { 19 | self.meta.name.into() 20 | } 21 | fn get_tx_url(&self, hash: &str) -> String { 22 | format!("{}/tx/{}", self.meta.base_url, hash) 23 | } 24 | 25 | fn get_address_url(&self, address: &str) -> String { 26 | format!("{}/address/{}", self.meta.base_url, address) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/primitives/src/explorers/subscan.rs: -------------------------------------------------------------------------------- 1 | use crate::block_explorer::{BlockExplorer, Metadata}; 2 | 3 | pub struct SubScan { 4 | pub meta: Metadata, 5 | } 6 | 7 | macro_rules! subscan_url { 8 | ($chain:expr) => { 9 | concat!("https://", $chain, ".subscan.io") 10 | }; 11 | } 12 | 13 | impl SubScan { 14 | pub fn new_polkadot() -> Box { 15 | Box::new(Self { 16 | meta: Metadata { 17 | name: "SubScan", 18 | base_url: subscan_url!("polkadot"), 19 | }, 20 | }) 21 | } 22 | } 23 | 24 | impl BlockExplorer for SubScan { 25 | fn name(&self) -> String { 26 | self.meta.name.into() 27 | } 28 | fn get_tx_url(&self, hash: &str) -> String { 29 | format!("{}/extrinsic/{}", self.meta.base_url, hash) 30 | } 31 | fn get_address_url(&self, address: &str) -> String { 32 | format!("{}/account/{}", self.meta.base_url, address) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /crates/primitives/src/explorers/xrpscan.rs: -------------------------------------------------------------------------------- 1 | use crate::block_explorer::{BlockExplorer, Metadata}; 2 | 3 | pub struct XrpScan { 4 | pub meta: Metadata, 5 | } 6 | 7 | impl XrpScan { 8 | pub fn new() -> Box { 9 | Box::new(Self { 10 | meta: Metadata { 11 | name: "XrpScan", 12 | base_url: "https://xrpscan.com", 13 | }, 14 | }) 15 | } 16 | } 17 | 18 | impl BlockExplorer for XrpScan { 19 | fn name(&self) -> String { 20 | self.meta.name.into() 21 | } 22 | fn get_tx_url(&self, hash: &str) -> String { 23 | format!("{}/tx/{}", self.meta.base_url, hash) 24 | } 25 | fn get_address_url(&self, address: &str) -> String { 26 | format!("{}/account/{}", self.meta.base_url, address) 27 | } 28 | fn get_token_url(&self, token: &str) -> Option { 29 | Some(self.get_address_url(token)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /crates/primitives/src/explorers/zksync.rs: -------------------------------------------------------------------------------- 1 | use crate::block_explorer::{BlockExplorer, Metadata}; 2 | 3 | pub struct ZkSync { 4 | pub meta: Metadata, 5 | } 6 | 7 | impl ZkSync { 8 | pub fn new() -> Box { 9 | Box::new(Self { 10 | meta: Metadata { 11 | name: "zkSync.io", 12 | base_url: "https://explorer.zksync.io", 13 | }, 14 | }) 15 | } 16 | } 17 | 18 | impl BlockExplorer for ZkSync { 19 | fn name(&self) -> String { 20 | self.meta.name.into() 21 | } 22 | fn get_tx_url(&self, hash: &str) -> String { 23 | format!("{}/tx/{}", self.meta.base_url, hash) 24 | } 25 | fn get_address_url(&self, address: &str) -> String { 26 | format!("{}/address/{}", self.meta.base_url, address) 27 | } 28 | fn get_token_url(&self, _token: &str) -> Option { 29 | Some(self.get_address_url(_token)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /crates/primitives/src/fee.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use strum::{AsRefStr, EnumIter, EnumString}; 3 | use typeshare::typeshare; 4 | 5 | #[derive(Debug, Clone, Serialize, Deserialize, AsRefStr, EnumString, EnumIter)] 6 | #[typeshare(swift = "Equatable, Sendable, CaseIterable")] 7 | #[serde(rename_all = "camelCase")] 8 | #[strum(serialize_all = "camelCase")] 9 | pub enum FeePriority { 10 | Slow, 11 | Normal, 12 | Fast, 13 | } 14 | 15 | #[derive(Debug, Clone, Serialize, Deserialize, AsRefStr, EnumString, EnumIter)] 16 | #[serde(rename_all = "camelCase")] 17 | #[strum(serialize_all = "camelCase")] 18 | #[typeshare(swift = "Equatable, Sendable")] 19 | pub enum FeeUnitType { 20 | SatVb, 21 | Gwei, 22 | Native, 23 | } 24 | -------------------------------------------------------------------------------- /crates/primitives/src/fiat_assets.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use serde::{Deserialize, Serialize}; 4 | use typeshare::typeshare; 5 | 6 | use crate::AssetId; 7 | 8 | #[derive(Debug, Clone, Serialize, Deserialize)] 9 | #[typeshare(swift = "Sendable")] 10 | #[serde(rename_all = "camelCase")] 11 | pub struct FiatAssets { 12 | pub version: u32, 13 | pub asset_ids: Vec, 14 | } 15 | 16 | #[derive(Debug, Clone, Deserialize)] 17 | #[serde(rename_all = "camelCase")] 18 | pub struct FiatAsset { 19 | pub id: String, 20 | pub asset_id: Option, 21 | pub provider: String, 22 | pub symbol: String, 23 | pub network: Option, 24 | pub token_id: Option, 25 | pub enabled: bool, 26 | pub unsupported_countries: HashMap>, 27 | } 28 | -------------------------------------------------------------------------------- /crates/primitives/src/fiat_rate.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | #[typeshare(swift = "Sendable")] 5 | #[derive(Debug, Serialize, Deserialize, Clone)] 6 | pub struct FiatRate { 7 | pub symbol: String, 8 | pub rate: f64, 9 | } 10 | 11 | impl FiatRate { 12 | pub fn multiplier(&self, base: f64) -> f64 { 13 | self.rate * base 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/primitives/src/json_rpc.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, Serialize, Deserialize)] 4 | pub struct JsonRpcResult { 5 | pub result: T, 6 | } 7 | -------------------------------------------------------------------------------- /crates/primitives/src/link_type.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use strum::{AsRefStr, EnumIter, EnumString, IntoEnumIterator}; 3 | use typeshare::typeshare; 4 | 5 | #[derive(Debug, Serialize, Deserialize, Clone, EnumIter, AsRefStr, EnumString)] 6 | #[typeshare(swift = "Sendable, Hashable, Equatable")] 7 | #[serde(rename_all = "lowercase")] 8 | #[strum(serialize_all = "lowercase")] 9 | pub enum LinkType { 10 | X, 11 | Discord, 12 | Reddit, 13 | Telegram, 14 | GitHub, 15 | YouTube, 16 | Facebook, 17 | Website, 18 | Coingecko, 19 | OpenSea, 20 | Instagram, 21 | MagicEden, 22 | CoinMarketCap, 23 | TikTok, 24 | } 25 | 26 | impl LinkType { 27 | pub fn name(&self) -> String { 28 | self.as_ref().to_string() 29 | } 30 | } 31 | 32 | impl LinkType { 33 | pub fn all() -> Vec { 34 | Self::iter().collect::>() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /crates/primitives/src/name.rs: -------------------------------------------------------------------------------- 1 | use crate::chain::Chain; 2 | use serde::Serialize; 3 | use strum::EnumString; 4 | use strum_macros::AsRefStr; 5 | use typeshare::typeshare; 6 | 7 | #[derive(Debug, Serialize)] 8 | #[typeshare(swift = "Sendable, Hashable")] 9 | #[allow(dead_code)] 10 | pub struct NameRecord { 11 | pub name: String, 12 | pub chain: Chain, 13 | pub address: String, 14 | pub provider: String, 15 | } 16 | 17 | #[derive(Debug, Serialize, AsRefStr, EnumString)] 18 | #[typeshare(swift = "Sendable")] 19 | #[serde(rename_all = "lowercase")] 20 | #[strum(serialize_all = "lowercase")] 21 | pub enum NameProvider { 22 | Ud, 23 | Ens, 24 | Sns, 25 | Ton, 26 | Tree, 27 | Spaceid, 28 | Eths, 29 | Did, 30 | Suins, 31 | Aptos, 32 | Injective, 33 | Icns, 34 | Lens, 35 | Basenames, 36 | Hyperliquid, 37 | } 38 | -------------------------------------------------------------------------------- /crates/primitives/src/payment_decoder/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod decoder; 2 | pub mod erc681; 3 | pub mod solana_pay; 4 | pub mod ton_pay; 5 | 6 | pub use self::decoder::{DecodedLinkType, Payment, PaymentURLDecoder}; 7 | -------------------------------------------------------------------------------- /crates/primitives/src/response.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | #[typeshare(swift = "Sendable")] 5 | #[typeshare(swiftGenericConstraints = "T: Sendable")] 6 | #[derive(Debug, Clone, Serialize, Deserialize)] 7 | pub struct ResponseResult { 8 | pub data: T, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | pub error: Option, 11 | } 12 | 13 | impl ResponseResult { 14 | pub fn new(data: T) -> Self { 15 | Self { data, error: None } 16 | } 17 | } 18 | 19 | #[typeshare(swift = "Sendable")] 20 | #[derive(Debug, Clone, Serialize, Deserialize)] 21 | pub struct ResponseError { 22 | pub error: String, 23 | } 24 | 25 | impl From> for ResponseError { 26 | fn from(error: Box) -> Self { 27 | Self { error: error.to_string() } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /crates/primitives/src/solana_token_program.rs: -------------------------------------------------------------------------------- 1 | use serde::Serialize; 2 | use strum::{AsRefStr, EnumString}; 3 | use typeshare::typeshare; 4 | 5 | #[derive(Debug, Serialize, AsRefStr, EnumString)] 6 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 7 | #[serde(rename_all = "lowercase")] 8 | #[strum(serialize_all = "lowercase")] 9 | pub enum SolanaTokenProgramId { 10 | Token, 11 | Token2022, 12 | } 13 | -------------------------------------------------------------------------------- /crates/primitives/src/subscription.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | use crate::chain::Chain; 5 | 6 | #[derive(Clone, Debug, Serialize, Deserialize)] 7 | #[typeshare(swift = "Equatable, Hashable, Sendable")] 8 | pub struct Subscription { 9 | pub wallet_index: i32, 10 | pub chain: Chain, 11 | pub address: String, 12 | } 13 | -------------------------------------------------------------------------------- /crates/primitives/src/swap/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mode; 2 | pub mod quote; 3 | pub mod slippage; 4 | 5 | pub use mode::*; 6 | pub use quote::*; 7 | pub use slippage::*; 8 | -------------------------------------------------------------------------------- /crates/primitives/src/swap/mode.rs: -------------------------------------------------------------------------------- 1 | use typeshare::typeshare; 2 | 3 | use crate::Chain; 4 | 5 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] 6 | #[typeshare] 7 | pub enum SwapProviderMode { 8 | OnChain, 9 | CrossChain, 10 | Bridge, 11 | OmniChain(Vec), // supports both on-chain and cross-chain. Specify the chain for on-chain swaps 12 | } 13 | 14 | #[derive(Debug, Copy, Clone, PartialEq)] 15 | #[typeshare] 16 | pub enum SwapMode { 17 | ExactIn, 18 | ExactOut, 19 | } 20 | -------------------------------------------------------------------------------- /crates/primitives/src/swap/slippage.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Copy, Clone, PartialEq)] 2 | pub struct Slippage { 3 | pub bps: u32, 4 | pub mode: SlippageMode, 5 | } 6 | 7 | #[derive(Debug, Copy, Clone, PartialEq)] 8 | pub enum SlippageMode { 9 | Auto, 10 | Exact, 11 | } 12 | 13 | impl From for Slippage { 14 | fn from(value: u32) -> Self { 15 | Slippage { 16 | bps: value, 17 | mode: SlippageMode::Exact, 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /crates/primitives/src/tag.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use strum::{AsRefStr, EnumIter, EnumString, IntoEnumIterator}; 3 | use typeshare::typeshare; 4 | 5 | #[derive(Clone, Debug, Serialize, Deserialize, EnumIter, AsRefStr, EnumString)] 6 | #[typeshare(swift = "Equatable, Hashable, Sendable")] 7 | #[serde(rename_all = "snake_case")] 8 | #[strum(serialize_all = "snake_case")] 9 | pub enum AssetTag { 10 | Trending, 11 | TrendingFiatPurchase, 12 | Gainers, 13 | Losers, 14 | New, 15 | Stablecoins, 16 | } 17 | 18 | impl AssetTag { 19 | pub fn all() -> Vec { 20 | Self::iter().collect::>() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/primitives/src/transaction_direction.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] 5 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 6 | #[serde(rename_all = "lowercase")] 7 | pub enum TransactionDirection { 8 | #[serde(rename = "self")] 9 | SelfTransfer, 10 | Outgoing, 11 | Incoming, 12 | } 13 | -------------------------------------------------------------------------------- /crates/primitives/src/transaction_extended.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Sendable")] 2 | struct TransactionExtended { 3 | transaction: Transaction, 4 | asset: Asset, 5 | #[serde(rename = "feeAsset")] 6 | feeAsset: Asset, 7 | price: Option, 8 | #[serde(rename = "feePrice")] 9 | fee_price: Option, 10 | assets: Vec, 11 | prices: Vec, 12 | } 13 | -------------------------------------------------------------------------------- /crates/primitives/src/transaction_metadata_types.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | use crate::AssetId; 5 | 6 | #[derive(Debug, Clone, Serialize, Deserialize)] 7 | #[typeshare(swift = "Sendable")] 8 | #[serde(rename_all = "camelCase")] 9 | pub struct TransactionSwapMetadata { 10 | pub from_asset: AssetId, 11 | pub from_value: String, 12 | pub to_asset: AssetId, 13 | pub to_value: String, 14 | pub provider: Option, 15 | } 16 | 17 | #[derive(Debug, Clone, Serialize, Deserialize)] 18 | #[typeshare(swift = "Sendable")] 19 | #[serde(rename_all = "camelCase")] 20 | pub struct TransactionNFTTransferMetadata { 21 | pub asset_id: String, 22 | } 23 | -------------------------------------------------------------------------------- /crates/primitives/src/transaction_type.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use strum::{AsRefStr, EnumIter, EnumString, IntoEnumIterator}; 3 | use typeshare::typeshare; 4 | 5 | #[derive(Debug, Clone, Serialize, Deserialize, EnumString, AsRefStr, PartialEq, EnumIter)] 6 | #[typeshare(swift = "Equatable, CaseIterable, Sendable")] 7 | #[serde(rename_all = "camelCase")] 8 | #[strum(serialize_all = "camelCase")] 9 | pub enum TransactionType { 10 | Transfer, 11 | TransferNFT, 12 | Swap, 13 | TokenApproval, 14 | StakeDelegate, 15 | StakeUndelegate, 16 | StakeRewards, 17 | StakeRedelegate, 18 | StakeWithdraw, 19 | AssetActivation, 20 | SmartContractCall, 21 | } 22 | 23 | impl Default for TransactionType { 24 | fn default() -> Self { 25 | Self::Transfer 26 | } 27 | } 28 | 29 | impl TransactionType { 30 | pub fn all() -> Vec { 31 | Self::iter().collect::>() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /crates/primitives/src/transaction_utxo.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | #[derive(Debug, Clone, Serialize, Deserialize)] 5 | #[typeshare(swift = "Sendable, Equatable")] 6 | pub struct TransactionInput { 7 | pub address: String, // Coinbase / OP_Return will be filtered 8 | pub value: String, 9 | } 10 | -------------------------------------------------------------------------------- /crates/primitives/src/utxo.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | #[derive(Debug, Clone, Serialize, Deserialize)] 5 | #[typeshare(swift = "Sendable")] 6 | pub struct UTXO { 7 | pub transaction_id: String, 8 | pub vout: i32, 9 | pub value: String, 10 | pub address: String, 11 | } 12 | -------------------------------------------------------------------------------- /crates/primitives/src/validator.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone, Serialize, Deserialize)] 2 | #[typeshare(swift = "Equatable, Hashable, Sendable")] 3 | #[serde(rename_all = "camelCase")] 4 | pub struct StakeValidator { 5 | pub id: String, 6 | pub name: String, 7 | } 8 | -------------------------------------------------------------------------------- /crates/primitives/src/wallet.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Equatable, Sendable, Hashable")] 2 | struct Wallet { 3 | id: String, 4 | name: String, 5 | index: i32, 6 | #[serde(rename = "type")] 7 | wallet_type: WalletType, 8 | accounts: Vec, 9 | order: i32, 10 | #[serde(rename = "isPinned")] 11 | is_pinned: bool, 12 | #[serde(rename = "imageUrl")] 13 | image_url: Option, 14 | } 15 | 16 | #[typeshare(swift = "Equatable, Hashable, Sendable")] 17 | #[serde(rename_all = "camelCase")] 18 | pub enum WalletType { 19 | multicoin, 20 | single, 21 | private_key, 22 | view, 23 | } 24 | 25 | #[typeshare(swift = "Equatable, Sendable")] 26 | struct WalletId { 27 | id: String, 28 | } 29 | -------------------------------------------------------------------------------- /crates/primitives/src/websocket.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use typeshare::typeshare; 3 | 4 | use crate::{AssetId, AssetPrice, FiatRate}; 5 | 6 | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] 7 | #[serde(rename_all = "lowercase")] 8 | #[typeshare(swift = "Sendable")] 9 | pub enum WebSocketPriceActionType { 10 | Subscribe, 11 | Add, 12 | } 13 | 14 | #[derive(Debug, Clone, Serialize, Deserialize)] 15 | #[typeshare(swift = "Sendable")] 16 | pub struct WebSocketPriceAction { 17 | pub action: WebSocketPriceActionType, 18 | #[serde(default)] 19 | pub assets: Vec, 20 | } 21 | 22 | #[derive(Debug, Clone, Serialize, Deserialize)] 23 | #[typeshare(swift = "Sendable")] 24 | pub struct WebSocketPricePayload { 25 | pub prices: Vec, 26 | pub rates: Vec, 27 | } 28 | -------------------------------------------------------------------------------- /crates/search_index/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "search_index" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | serde_json = { workspace = true } 9 | meilisearch-sdk = { workspace = true } 10 | 11 | primitives = { path = "../primitives" } 12 | settings = { path = "../settings" } 13 | -------------------------------------------------------------------------------- /crates/security_goplus/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "security_goplus" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | async-trait = { workspace = true } 8 | serde = { workspace = true } 9 | serde_json = { workspace = true } 10 | security_provider = { path = "../security_provider" } 11 | reqwest = { workspace = true } 12 | -------------------------------------------------------------------------------- /crates/security_goplus/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod provider; 2 | pub use self::provider::GoPlusProvider; 3 | pub mod models; 4 | -------------------------------------------------------------------------------- /crates/security_goplus/src/models.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, Serialize, Deserialize)] 4 | pub struct Response { 5 | pub code: i32, 6 | pub message: String, 7 | pub result: T, 8 | } 9 | 10 | #[derive(Debug, Clone, Serialize, Deserialize)] 11 | pub struct SecurityAddress { 12 | pub cybercrime: String, 13 | pub money_laundering: String, 14 | pub financial_crime: String, 15 | pub blacklist_doubt: String, 16 | pub stealing_attack: String, 17 | } 18 | 19 | impl SecurityAddress { 20 | pub fn is_malicious(&self) -> bool { 21 | self.cybercrime == "1" || self.money_laundering == "1" || self.financial_crime == "1" || self.blacklist_doubt == "1" || self.stealing_attack == "1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /crates/security_hashdit/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "security_hashdit" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | async-trait = { workspace = true } 8 | uuid = { workspace = true } 9 | serde = { workspace = true } 10 | serde_json = { workspace = true } 11 | hex = { workspace = true } 12 | hmac = { workspace = true } 13 | sha2 = { workspace = true } 14 | reqwest-enum = { workspace = true } 15 | reqwest = { workspace = true } 16 | 17 | security_provider = { path = "../security_provider" } 18 | -------------------------------------------------------------------------------- /crates/security_hashdit/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod api; 2 | mod models; 3 | pub mod provider; 4 | pub use self::provider::HashDitProvider; 5 | -------------------------------------------------------------------------------- /crates/security_provider/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "security_provider" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | async-trait = { workspace = true } 8 | serde = { workspace = true } 9 | primitives = { path = "../primitives" } 10 | 11 | [dev-dependencies] 12 | serde_json = { workspace = true } 13 | -------------------------------------------------------------------------------- /crates/serde_serializers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde_serializers" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | serde_json = { workspace = true } 9 | num-bigint = { workspace = true } 10 | num-traits = { workspace = true } -------------------------------------------------------------------------------- /crates/serde_serializers/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod bigint; 2 | pub use bigint::{deserialize_bigint_from_str, serialize_bigint}; 3 | pub mod biguint; 4 | pub use biguint::{ 5 | deserialize_biguint_from_hex_str, deserialize_biguint_from_option_hex_str, deserialize_biguint_from_str, serialize_biguint, serialize_biguint_to_hex_str, 6 | }; 7 | pub mod f64; 8 | pub use f64::{deserialize_f64_from_str, deserialize_option_f64_from_str, serialize_f64}; 9 | pub mod u64; 10 | pub use u64::{deserialize_u64_from_str, deserialize_u64_from_str_or_int, serialize_u64}; 11 | -------------------------------------------------------------------------------- /crates/settings/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "settings" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | typeshare = { workspace = true } 8 | serde = { workspace = true } 9 | config = { workspace = true } 10 | -------------------------------------------------------------------------------- /crates/settings_chain/src/provider_config.rs: -------------------------------------------------------------------------------- 1 | use primitives::Chain; 2 | 3 | #[derive(Debug, Clone)] 4 | pub struct ProviderConfig { 5 | pub chain: Chain, 6 | pub url: String, 7 | pub alchemy_key: String, 8 | } 9 | 10 | impl ProviderConfig { 11 | pub fn new(chain: Chain, url: &str, alchemy_key: &str) -> Self { 12 | Self { 13 | chain, 14 | url: url.to_string(), 15 | alchemy_key: alchemy_key.to_string(), 16 | } 17 | } 18 | 19 | pub fn with_url(&self, url: &str) -> Self { 20 | Self { 21 | url: url.to_string(), 22 | ..self.clone() 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /crates/storage/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "storage" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | serde = { workspace = true } 8 | serde_json = { workspace = true } 9 | redis = { workspace = true } 10 | diesel = { workspace = true } 11 | diesel_migrations = { workspace = true } 12 | chrono = { workspace = true } 13 | clickhouse = { workspace = true } 14 | async-trait = { workspace = true } 15 | 16 | primitives = { path = "../primitives" } 17 | -------------------------------------------------------------------------------- /crates/storage/src/clickhouse/clickhouse_migration.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS charts 2 | ( 3 | coin_id LowCardinality(String), 4 | price Float32 CODEC(ZSTD(1)), 5 | ts DateTime CODEC(DoubleDelta, ZSTD(1)) 6 | ) 7 | ENGINE = MergeTree 8 | PARTITION BY toYYYYMM(ts) 9 | ORDER BY (coin_id, toStartOfDay(ts), toStartOfHour(ts), toStartOfFifteenMinutes(ts), toStartOfFiveMinute(ts)) 10 | TTL 11 | ts + INTERVAL 1 HOUR GROUP BY coin_id, toStartOfDay(ts), toStartOfHour(ts), toStartOfFifteenMinutes(ts), toStartOfFiveMinute(ts) SET price = avg(price), 12 | ts + INTERVAL 1 DAY GROUP BY coin_id, toStartOfDay(ts), toStartOfHour(ts), toStartOfFifteenMinutes(ts) SET price = avg(price), 13 | ts + INTERVAL 1 WEEK GROUP BY coin_id, toStartOfDay(ts), toStartOfHour(ts) SET price = avg(price), 14 | ts + INTERVAL 1 MONTH GROUP BY coin_id, toStartOfDay(ts) SET price = avg(price); 15 | -------------------------------------------------------------------------------- /crates/storage/src/clickhouse/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod clickhouse_database; 2 | -------------------------------------------------------------------------------- /crates/storage/src/database/assets_links.rs: -------------------------------------------------------------------------------- 1 | use crate::models::asset::AssetLink; 2 | use crate::schema::assets_links::dsl::*; 3 | 4 | use crate::DatabaseClient; 5 | use diesel::{prelude::*, upsert::excluded}; 6 | 7 | impl DatabaseClient { 8 | pub fn add_assets_links(&mut self, values: Vec) -> Result { 9 | diesel::insert_into(assets_links) 10 | .values(values) 11 | .on_conflict((asset_id, link_type)) 12 | .do_update() 13 | .set((url.eq(excluded(url)),)) 14 | .execute(&mut self.connection) 15 | } 16 | 17 | pub fn get_asset_links(&mut self, _asset_id: &str) -> Result, diesel::result::Error> { 18 | use crate::schema::assets_links::dsl::*; 19 | assets_links 20 | .filter(asset_id.eq(_asset_id)) 21 | .select(AssetLink::as_select()) 22 | .load(&mut self.connection) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /crates/storage/src/database/assets_types.rs: -------------------------------------------------------------------------------- 1 | use crate::schema::assets_types::dsl::*; 2 | 3 | use crate::{models::AssetType, DatabaseClient}; 4 | use diesel::prelude::*; 5 | 6 | impl DatabaseClient { 7 | pub fn add_assets_types(&mut self, values: Vec) -> Result { 8 | let values = values.iter().map(|x| AssetType { id: x.as_ref().to_owned() }).collect::>(); 9 | 10 | diesel::insert_into(assets_types) 11 | .values(values) 12 | .on_conflict_do_nothing() 13 | .execute(&mut self.connection) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/storage/src/database/nodes.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | use crate::{models::*, DatabaseClient}; 4 | use diesel::prelude::*; 5 | use primitives::node::ChainNode; 6 | 7 | pub trait NodeStore { 8 | fn get_nodes(&mut self) -> Result, diesel::result::Error>; 9 | } 10 | 11 | pub trait NodeRepository { 12 | fn get_nodes(&mut self) -> Result, Box>; 13 | } 14 | 15 | impl NodeStore for DatabaseClient { 16 | fn get_nodes(&mut self) -> Result, diesel::result::Error> { 17 | use crate::schema::nodes::dsl::*; 18 | nodes.select(Node::as_select()).load(&mut self.connection) 19 | } 20 | } 21 | 22 | impl NodeRepository for DatabaseClient { 23 | fn get_nodes(&mut self) -> Result, Box> { 24 | Ok(NodeStore::get_nodes(self)?.into_iter().map(|x| x.as_primitive()).collect()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/00000000000000_diesel_initial_setup/down.sql: -------------------------------------------------------------------------------- 1 | -- This file was automatically created by Diesel to setup helper functions 2 | -- and other internal bookkeeping. This file is safe to edit, any future 3 | -- changes will be added to existing projects as new migrations. 4 | 5 | DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); 6 | DROP FUNCTION IF EXISTS diesel_set_updated_at(); 7 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-18-212125_chains/down.sql: -------------------------------------------------------------------------------- 1 | drop table chains; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-18-212125_chains/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE chains ( 2 | id VARCHAR(32) PRIMARY KEY NOT NULL, 3 | 4 | updated_at timestamp NOT NULL default current_timestamp, 5 | created_at timestamp NOT NULL default current_timestamp 6 | ); 7 | 8 | SELECT diesel_manage_updated_at('chains'); 9 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-21-201556_assets_types/down.sql: -------------------------------------------------------------------------------- 1 | drop table assets_types; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-21-201556_assets_types/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE assets_types ( 2 | id VARCHAR(32) PRIMARY KEY NOT NULL, 3 | 4 | updated_at timestamp NOT NULL default current_timestamp, 5 | created_at timestamp NOT NULL default current_timestamp 6 | ); 7 | 8 | INSERT INTO assets_types(id) VALUES ('NATIVE'); 9 | INSERT INTO assets_types(id) VALUES ('ERC20'); 10 | INSERT INTO assets_types(id) VALUES ('BEP20'); 11 | INSERT INTO assets_types(id) VALUES ('BEP2'); 12 | INSERT INTO assets_types(id) VALUES ('SPL'); 13 | INSERT INTO assets_types(id) VALUES ('TRC20'); 14 | 15 | SELECT diesel_manage_updated_at('assets_types'); -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-22-205905_assets/down.sql: -------------------------------------------------------------------------------- 1 | drop table assets; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-22-205905_assets/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE assets ( 2 | id VARCHAR(128) PRIMARY KEY, 3 | chain VARCHAR(32) NOT NULL REFERENCES chains (id) ON DELETE CASCADE, 4 | token_id VARCHAR(128), 5 | asset_type VARCHAR(16) NOT NULL REFERENCES assets_types (id) ON DELETE CASCADE, 6 | name VARCHAR(64) NOT NULL, 7 | symbol VARCHAR(16) NOT NULL, 8 | decimals INTEGER NOT NULL, 9 | updated_at timestamp NOT NULL default current_timestamp, 10 | created_at timestamp NOT NULL default current_timestamp, 11 | rank INTEGER NOT NULL DEFAULT 0, 12 | 13 | is_enabled BOOLEAN NOT NULL DEFAULT TRUE, 14 | is_buyable boolean NOT NULL default false, 15 | is_sellable boolean NOT NULL default false, 16 | is_swappable boolean NOT NULL default false, 17 | is_stakeable boolean NOT NULL default false, 18 | staking_apr float, 19 | 20 | UNIQUE(id) 21 | ); 22 | 23 | SELECT diesel_manage_updated_at('assets'); 24 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-23-195320_nodes/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE nodes; 2 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-23-195320_nodes/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE nodes ( 2 | id SERIAL PRIMARY KEY, 3 | chain VARCHAR NOT NULL REFERENCES chains (id) ON DELETE CASCADE, 4 | url VARCHAR NOT NULL, 5 | status VARCHAR NOT NULL, 6 | priority INTEGER NOT NULL, 7 | updated_at timestamp default current_timestamp, 8 | created_at timestamp default current_timestamp 9 | ) -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-23-215138_fiat_providers/down.sql: -------------------------------------------------------------------------------- 1 | drop table fiat_providers; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-23-215138_fiat_providers/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE fiat_providers ( 2 | id VARCHAR(32) PRIMARY KEY NOT NULL, 3 | name VARCHAR(32) NOT NULL, 4 | enabled BOOLEAN NOT NULL DEFAULT FALSE, 5 | 6 | updated_at timestamp NOT NULL default current_timestamp, 7 | created_at timestamp NOT NULL default current_timestamp 8 | ); 9 | 10 | SELECT diesel_manage_updated_at('fiat_providers'); 11 | 12 | 13 | CREATE TABLE fiat_providers_countries ( 14 | id VARCHAR(32) PRIMARY KEY NOT NULL, 15 | provider VARCHAR(128) NOT NULL REFERENCES fiat_providers (id) ON DELETE CASCADE, 16 | alpha2 VARCHAR(32) NOT NULL, 17 | is_allowed BOOLEAN NOT NULL, 18 | 19 | updated_at timestamp NOT NULL default current_timestamp, 20 | created_at timestamp NOT NULL default current_timestamp 21 | ); 22 | 23 | SELECT diesel_manage_updated_at('fiat_providers_countries'); -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-24-215139_fiat_assets/down.sql: -------------------------------------------------------------------------------- 1 | drop table fiat_assets; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-24-215139_fiat_assets/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE fiat_assets ( 2 | id VARCHAR(128) PRIMARY KEY, 3 | asset_id VARCHAR(128) REFERENCES assets (id) ON DELETE CASCADE, 4 | provider VARCHAR(128) NOT NULL REFERENCES fiat_providers (id) ON DELETE CASCADE, 5 | code VARCHAR(128) NOT NULL, 6 | symbol VARCHAR(128) NOT NULL, 7 | network VARCHAR(128) NULL, 8 | token_id VARCHAR(128) NULL, 9 | is_enabled BOOLEAN NOT NULL DEFAULT TRUE, 10 | is_enabled_by_provider BOOLEAN NOT NULL DEFAULT TRUE, 11 | unsupported_countries jsonb, 12 | updated_at timestamp NOT NULL default current_timestamp, 13 | created_at timestamp NOT NULL default current_timestamp 14 | ); 15 | 16 | SELECT diesel_manage_updated_at('fiat_assets'); 17 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-28-193518_prices/down.sql: -------------------------------------------------------------------------------- 1 | drop table prices; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-28-193519_prices_assets/down.sql: -------------------------------------------------------------------------------- 1 | drop table prices_assets; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-28-193519_prices_assets/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE prices_assets ( 2 | asset_id VARCHAR(256) PRIMARY KEY NOT NULL REFERENCES assets (id) ON DELETE CASCADE, 3 | price_id VARCHAR(256) NOT NULL REFERENCES prices (id) ON DELETE CASCADE, 4 | 5 | updated_at timestamp NOT NULL default current_timestamp, 6 | created_at timestamp NOT NULL default current_timestamp, 7 | 8 | UNIQUE(asset_id) 9 | ); 10 | 11 | SELECT diesel_manage_updated_at('prices_assets'); 12 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-29-040300_fiat_rates/down.sql: -------------------------------------------------------------------------------- 1 | DROP table fiat_rates; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-07-29-040300_fiat_rates/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE fiat_rates ( 2 | id VARCHAR(8) NOT NULL PRIMARY KEY, 3 | name VARCHAR NOT NULL, 4 | rate float NOT NULL DEFAULT 0, 5 | created_at timestamp NOT NULL default current_timestamp, 6 | updated_at timestamp NOT NULL default current_timestamp 7 | ); 8 | 9 | SELECT diesel_manage_updated_at('fiat_rates'); -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-09-03-192926_devices/down.sql: -------------------------------------------------------------------------------- 1 | drop table devices; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-09-03-192926_devices/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE devices ( 2 | id SERIAL PRIMARY KEY, 3 | device_id VARCHAR(32) NOT NULL, 4 | is_push_enabled boolean NOT NULL, 5 | platform VARCHAR(8) NOT NULL, 6 | platform_store VARCHAR(32), 7 | token VARCHAR(256) NOT NULL, 8 | locale VARCHAR(8) NOT NULL, 9 | version VARCHAR(8) NOT NULL, 10 | updated_at timestamp NOT NULL default current_timestamp, 11 | created_at timestamp NOT NULL default current_timestamp, 12 | currency VARCHAR(8) NOT NULL REFERENCES fiat_rates (id) ON DELETE CASCADE, 13 | subscriptions_version INTEGER NOT NULL DEFAULT 0, 14 | is_price_alerts_enabled boolean NOT NULL DEFAULT false, 15 | UNIQUE(device_id) 16 | ); 17 | 18 | CREATE INDEX devices_token_idx ON devices (token); 19 | 20 | SELECT diesel_manage_updated_at('devices'); 21 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-09-03-220931_parser/down.sql: -------------------------------------------------------------------------------- 1 | drop table parser_state; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-09-03-220931_parser/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE parser_state ( 2 | chain VARCHAR NOT NULL PRIMARY KEY REFERENCES chains (id) ON DELETE CASCADE, 3 | current_block INTEGER NOT NULL default 0, 4 | latest_block INTEGER NOT NULL default 0, 5 | await_blocks INTEGER NOT NULL default 0, 6 | timeout_between_blocks INTEGER NOT NULL default 0, 7 | timeout_latest_block INTEGER NOT NULL default 0, 8 | parallel_blocks INTEGER NOT NULL default 1, 9 | is_enabled boolean NOT NULL default true, 10 | updated_at timestamp NOT NULL default current_timestamp, 11 | created_at timestamp NOT NULL default current_timestamp, 12 | queue_behind_blocks INTEGER, 13 | UNIQUE(chain) 14 | ); 15 | 16 | SELECT diesel_manage_updated_at('parser_state'); -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-09-04-220616_subscriptions/down.sql: -------------------------------------------------------------------------------- 1 | drop table subscriptions; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-09-04-220616_subscriptions/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE subscriptions ( 2 | id SERIAL PRIMARY KEY, 3 | device_id INTEGER NOT NULL REFERENCES devices (id) ON DELETE CASCADE, 4 | chain VARCHAR NOT NULL REFERENCES chains (id) ON DELETE CASCADE, 5 | address VARCHAR(256) NOT NULL, 6 | updated_at timestamp NOT NULL DEFAULT current_timestamp, 7 | created_at timestamp NOT NULL DEFAULT current_timestamp, 8 | wallet_index INTEGER NOT NULL, 9 | UNIQUE(device_id, wallet_index, chain, address) 10 | ); 11 | 12 | SELECT diesel_manage_updated_at('subscriptions'); 13 | 14 | CREATE INDEX subscriptions_address_idx ON subscriptions (address DESC); 15 | CREATE INDEX subscriptions_chain_idx ON subscriptions (chain DESC); 16 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-09-05-011115_transactions/down.sql: -------------------------------------------------------------------------------- 1 | drop table tranasctions; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-10-18-184745_scan_address/down.sql: -------------------------------------------------------------------------------- 1 | drop table scan_addresses; 2 | drop table scan_addresses_types; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-11-03-004112_transactions_addresses/down.sql: -------------------------------------------------------------------------------- 1 | drop table transactions_addresses; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2023-11-03-004112_transactions_addresses/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE transactions_addresses 2 | ( 3 | id SERIAL PRIMARY KEY, 4 | chain_id VARCHAR(32) NOT NULL REFERENCES chains (id) ON DELETE CASCADE, 5 | transaction_id VARCHAR(256) NOT NULL REFERENCES transactions (id) ON DELETE CASCADE, 6 | asset_id VARCHAR(256) NOT NULL REFERENCES assets (id) ON DELETE CASCADE, 7 | address VARCHAR(256) NOT NULL, 8 | created_at timestamp NOT NULL default current_timestamp, 9 | UNIQUE (transaction_id, address, asset_id) 10 | ); 11 | 12 | CREATE INDEX transactions_addresses_chain_id_idx ON transactions_addresses (chain_id); 13 | CREATE INDEX transactions_addresses_asset_id_idx ON transactions_addresses (asset_id); 14 | CREATE INDEX transactions_addresses_address_idx ON transactions_addresses (address); 15 | CREATE INDEX transactions_addresses_transaction_id_idx ON transactions_addresses (transaction_id); -------------------------------------------------------------------------------- /crates/storage/src/migrations/2024-03-29-030159_fiat_transactions/down.sql: -------------------------------------------------------------------------------- 1 | drop table fiat_transactions; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2024-05-08-002620_subscriptions_addresses_exclude/down.sql: -------------------------------------------------------------------------------- 1 | drop table subscriptions_addresses_exclude; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2024-05-08-002620_subscriptions_addresses_exclude/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE subscriptions_addresses_exclude ( 2 | address VARCHAR(128) PRIMARY KEY NOT NULL, 3 | chain VARCHAR(32) NOT NULL REFERENCES chains (id) ON DELETE CASCADE, 4 | name VARCHAR(64), 5 | updated_at timestamp NOT NULL default current_timestamp, 6 | created_at timestamp NOT NULL default current_timestamp 7 | ); 8 | 9 | SELECT diesel_manage_updated_at('subscriptions_addresses_exclude'); 10 | 11 | CREATE INDEX subscriptions_addresses_exclude_address_idx ON subscriptions_addresses_exclude (address); -------------------------------------------------------------------------------- /crates/storage/src/migrations/2024-09-12-202145_price_alerts/down.sql: -------------------------------------------------------------------------------- 1 | drop table price_alerts; 2 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2024-09-12-202145_price_alerts/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS price_alerts ( 2 | id SERIAL PRIMARY KEY, 3 | identifier varchar(512) NOT NULL, 4 | 5 | device_id INTEGER NOT NULL REFERENCES devices (id) ON DELETE CASCADE, 6 | asset_id VARCHAR(128) NOT NULL REFERENCES assets (id) ON DELETE CASCADE, 7 | currency VARCHAR(128) NOT NULL REFERENCES fiat_rates (id) ON DELETE CASCADE, 8 | price_direction VARCHAR(16), 9 | price float, 10 | price_percent_change float, 11 | last_notified_at timestamp, 12 | 13 | updated_at timestamp NOT NULL default current_timestamp, 14 | created_at timestamp NOT NULL default current_timestamp, 15 | 16 | UNIQUE (device_id, identifier) 17 | ); 18 | 19 | SELECT diesel_manage_updated_at('price_alerts'); -------------------------------------------------------------------------------- /crates/storage/src/migrations/2024-09-24-204906_releases/down.sql: -------------------------------------------------------------------------------- 1 | drop table releases; 2 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2024-09-24-204906_releases/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE releases ( 2 | platform_store VARCHAR(32) PRIMARY KEY NOT NULL, 3 | 4 | version VARCHAR(32) NOT NULL, 5 | upgrade_required bool NOT NULL default false, 6 | 7 | updated_at timestamp NOT NULL default current_timestamp, 8 | created_at timestamp NOT NULL default current_timestamp 9 | ); 10 | 11 | 12 | SELECT diesel_manage_updated_at('releases'); -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-01-13-170539_link_types/down.sql: -------------------------------------------------------------------------------- 1 | drop table link_types; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-01-13-170539_link_types/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE link_types ( 2 | id VARCHAR(32) PRIMARY KEY NOT NULL, 3 | name VARCHAR(255) NOT NULL default '' 4 | ); -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-01-14-162733_nft_collections/down.sql: -------------------------------------------------------------------------------- 1 | drop table nft_collections; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-01-14-191614_nft_assets/down.sql: -------------------------------------------------------------------------------- 1 | drop table nft_assets; 2 | drop table nft_types; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-01-22-173935_assets_links/down.sql: -------------------------------------------------------------------------------- 1 | drop table assets_links; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-01-22-173935_assets_links/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE assets_links ( 2 | id SERIAL PRIMARY KEY, 3 | 4 | asset_id VARCHAR(128) NOT NULL REFERENCES assets (id) ON DELETE CASCADE, 5 | 6 | link_type VARCHAR(128) NOT NULL REFERENCES link_types (id) ON DELETE CASCADE, 7 | 8 | url VARCHAR(256) NOT NULL, 9 | 10 | updated_at timestamp NOT NULL default current_timestamp, 11 | created_at timestamp NOT NULL default current_timestamp, 12 | 13 | UNIQUE(asset_id, link_type) 14 | ); 15 | 16 | SELECT diesel_manage_updated_at('assets_links'); 17 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-03-12-161335_assets_tags/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS assets_tags; 2 | DROP TABLE IF EXISTS tags; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-03-12-161335_assets_tags/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tags ( 2 | id VARCHAR(64) PRIMARY KEY, 3 | created_at timestamp NOT NULL default current_timestamp 4 | ); 5 | 6 | CREATE TABLE assets_tags ( 7 | asset_id VARCHAR(128) NOT NULL REFERENCES assets (id) ON DELETE CASCADE, 8 | tag_id VARCHAR(64) NOT NULL REFERENCES tags (id) ON DELETE CASCADE, 9 | "order" INTEGER, 10 | created_at timestamp NOT NULL default current_timestamp, 11 | PRIMARY KEY (asset_id, tag_id) 12 | ); 13 | -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-06-05-015957_assets_addresses/down.sql: -------------------------------------------------------------------------------- 1 | drop table assets_addresses; -------------------------------------------------------------------------------- /crates/storage/src/migrations/2025-06-05-015957_assets_addresses/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE assets_addresses 2 | ( 3 | id SERIAL PRIMARY KEY, 4 | chain VARCHAR(32) NOT NULL REFERENCES chains (id) ON DELETE CASCADE, 5 | asset_id VARCHAR(256) NOT NULL REFERENCES assets (id) ON DELETE CASCADE, 6 | address VARCHAR(256) NOT NULL, 7 | updated_at timestamp NOT NULL default current_timestamp, 8 | created_at timestamp NOT NULL default current_timestamp, 9 | UNIQUE (asset_id, address) 10 | ); 11 | 12 | CREATE INDEX assets_addresses_chain_idx ON assets_addresses (chain); 13 | CREATE INDEX assets_addresses_asset_id_idx ON assets_addresses (asset_id); 14 | CREATE INDEX assets_addresses_address_idx ON assets_addresses (address); 15 | 16 | SELECT diesel_manage_updated_at('assets_addresses'); -------------------------------------------------------------------------------- /crates/storage/src/mod.rs: -------------------------------------------------------------------------------- 1 | //mod storage; 2 | 3 | mod schema; 4 | -------------------------------------------------------------------------------- /crates/storage/src/models/asset_address.rs: -------------------------------------------------------------------------------- 1 | use diesel::prelude::*; 2 | use serde::{Deserialize, Serialize}; 3 | #[derive(Debug, Queryable, Selectable, Serialize, Deserialize, Insertable, Clone)] 4 | #[diesel(table_name = crate::schema::assets_addresses)] 5 | #[diesel(check_for_backend(diesel::pg::Pg))] 6 | pub struct AssetAddress { 7 | pub chain: String, 8 | pub asset_id: String, 9 | pub address: String, 10 | } 11 | 12 | impl AssetAddress { 13 | pub fn new(chain: String, asset_id: String, address: String) -> Self { 14 | Self { chain, asset_id, address } 15 | } 16 | } 17 | 18 | impl AssetAddress { 19 | pub fn from_primitive(asset_address: primitives::AssetAddress) -> Self { 20 | Self { 21 | chain: asset_address.asset_id.chain.as_ref().to_string(), 22 | asset_id: asset_address.asset_id.to_string(), 23 | address: asset_address.address.clone(), 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /crates/storage/src/models/asset_type.rs: -------------------------------------------------------------------------------- 1 | use diesel::prelude::*; 2 | use serde::{Deserialize, Serialize}; 3 | #[derive(Debug, Queryable, Selectable, Serialize, Deserialize, Insertable, Clone)] 4 | #[diesel(table_name = crate::schema::assets_types)] 5 | #[diesel(check_for_backend(diesel::pg::Pg))] 6 | pub struct AssetType { 7 | pub id: String, 8 | } 9 | -------------------------------------------------------------------------------- /crates/storage/src/models/chain.rs: -------------------------------------------------------------------------------- 1 | use diesel::prelude::*; 2 | use serde::{Deserialize, Serialize}; 3 | #[derive(Debug, Queryable, Selectable, Serialize, Deserialize, Insertable, Clone)] 4 | #[diesel(table_name = crate::schema::chains)] 5 | #[diesel(check_for_backend(diesel::pg::Pg))] 6 | pub struct Chain { 7 | pub id: String, 8 | } 9 | -------------------------------------------------------------------------------- /crates/storage/src/models/chart.rs: -------------------------------------------------------------------------------- 1 | use clickhouse::Row; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Debug, Serialize, Deserialize, Row, Clone)] 5 | pub struct GetChart { 6 | pub price: f64, 7 | pub date: i32, 8 | } 9 | 10 | #[derive(Debug, Serialize, Deserialize, Row, Clone)] 11 | pub struct CreateChart { 12 | pub coin_id: String, 13 | pub price: f32, 14 | pub ts: u32, 15 | } 16 | -------------------------------------------------------------------------------- /crates/storage/src/models/link.rs: -------------------------------------------------------------------------------- 1 | use diesel::prelude::*; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Debug, Queryable, Selectable, Insertable, AsChangeset, Serialize, Deserialize, Clone)] 5 | #[diesel(table_name = crate::schema::link_types)] 6 | #[diesel(check_for_backend(diesel::pg::Pg))] 7 | pub struct LinkType { 8 | pub id: String, 9 | pub name: String, 10 | } 11 | 12 | impl LinkType { 13 | pub fn from_primitive(primitive: primitives::LinkType) -> Self { 14 | Self { 15 | id: primitive.as_ref().to_string(), 16 | name: primitive.name(), 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /crates/storage/src/models/nft_link.rs: -------------------------------------------------------------------------------- 1 | use diesel::prelude::*; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Debug, Queryable, Selectable, Serialize, Deserialize, Insertable, AsChangeset, Clone)] 5 | #[diesel(table_name = crate::schema::nft_collections_links)] 6 | #[diesel(check_for_backend(diesel::pg::Pg))] 7 | pub struct NftLink { 8 | pub collection_id: String, 9 | pub link_type: String, 10 | pub url: String, 11 | } 12 | 13 | impl NftLink { 14 | pub fn as_primitive(&self) -> primitives::AssetLink { 15 | primitives::AssetLink { 16 | name: self.link_type.clone(), 17 | url: self.url.clone(), 18 | } 19 | } 20 | 21 | pub fn from_primitive(collection_id: &str, link: primitives::AssetLink) -> Self { 22 | Self { 23 | collection_id: collection_id.to_string(), 24 | link_type: link.name.clone(), 25 | url: link.url.clone(), 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/storage/src/models/node.rs: -------------------------------------------------------------------------------- 1 | use diesel::prelude::*; 2 | use primitives::node::{ChainNode, NodeState}; 3 | use std::str::FromStr; 4 | 5 | #[derive(Debug, Clone, Queryable, Selectable)] 6 | #[diesel(table_name = crate::schema::nodes)] 7 | #[diesel(check_for_backend(diesel::pg::Pg))] 8 | pub struct Node { 9 | pub id: i32, 10 | pub chain: String, 11 | pub url: String, 12 | pub status: String, 13 | pub priority: i32, 14 | } 15 | 16 | impl Node { 17 | pub fn as_primitive(&self) -> ChainNode { 18 | ChainNode { 19 | chain: self.chain.clone(), 20 | node: self.as_primitive_node(), 21 | } 22 | } 23 | 24 | pub fn as_primitive_node(&self) -> primitives::node::Node { 25 | primitives::node::Node { 26 | url: self.url.clone(), 27 | status: NodeState::from_str(&self.status).unwrap(), 28 | priority: self.priority, 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /crates/storage/src/models/parser_state.rs: -------------------------------------------------------------------------------- 1 | use chrono::NaiveDateTime; 2 | use diesel::prelude::*; 3 | use serde::{Deserialize, Serialize}; 4 | 5 | #[derive(Debug, Queryable, Selectable, Serialize, Deserialize, Insertable, AsChangeset, Clone)] 6 | #[diesel(table_name = crate::schema::parser_state)] 7 | #[diesel(check_for_backend(diesel::pg::Pg))] 8 | pub struct ParserState { 9 | pub chain: String, 10 | pub current_block: i32, 11 | pub latest_block: i32, 12 | pub await_blocks: i32, 13 | pub timeout_between_blocks: i32, 14 | pub timeout_latest_block: i32, 15 | pub parallel_blocks: i32, 16 | pub is_enabled: bool, 17 | pub updated_at: NaiveDateTime, 18 | pub queue_behind_blocks: Option, 19 | } 20 | -------------------------------------------------------------------------------- /crates/storage/src/models/tag.rs: -------------------------------------------------------------------------------- 1 | use diesel::prelude::*; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Debug, Queryable, Selectable, Serialize, Deserialize, Insertable, Clone)] 5 | #[diesel(table_name = crate::schema::tags)] 6 | #[diesel(check_for_backend(diesel::pg::Pg))] 7 | pub struct Tag { 8 | pub id: String, 9 | } 10 | 11 | #[derive(Debug, Queryable, Selectable, Serialize, Deserialize, Insertable, Clone)] 12 | #[diesel(table_name = crate::schema::assets_tags)] 13 | #[diesel(check_for_backend(diesel::pg::Pg))] 14 | pub struct AssetTag { 15 | pub asset_id: String, 16 | pub tag_id: String, 17 | pub order: Option, 18 | } 19 | 20 | impl Tag { 21 | pub fn from_primitive(primitive: primitives::AssetTag) -> Self { 22 | Self { 23 | id: primitive.as_ref().to_lowercase(), 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /crates/streamer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "streamer" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | 6 | [dependencies] 7 | tokio = { workspace = true, features = ["sync", "rt"] } 8 | serde = { workspace = true } 9 | serde_json = { workspace = true } 10 | futures = { workspace = true } 11 | lapin = { workspace = true } 12 | async-trait = { workspace = true } 13 | strum = { workspace = true } 14 | strum_macros = { workspace = true } 15 | 16 | primitives = { path = "../primitives" } -------------------------------------------------------------------------------- /crates/streamer/src/exchange.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use strum::{EnumIter, IntoEnumIterator}; 3 | 4 | #[derive(Debug, Clone, EnumIter)] 5 | pub enum ExchangeName { 6 | Transactions, 7 | NewAddresses, 8 | } 9 | 10 | impl ExchangeName { 11 | pub fn all() -> Vec { 12 | ExchangeName::iter().collect() 13 | } 14 | } 15 | 16 | impl fmt::Display for ExchangeName { 17 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 18 | match self { 19 | ExchangeName::Transactions => write!(f, "transactions"), 20 | ExchangeName::NewAddresses => write!(f, "new_addresses"), 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /crates/streamer/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod consumer; 2 | pub mod exchange; 3 | pub mod payload; 4 | pub mod queue; 5 | pub mod steam_producer_queue; 6 | pub mod stream_producer; 7 | pub mod stream_reader; 8 | 9 | pub use consumer::run_consumer; 10 | pub use consumer::ConsumerConfig; 11 | pub use exchange::ExchangeName; 12 | pub use payload::*; 13 | pub use primitives::AssetId; 14 | pub use queue::QueueName; 15 | pub use steam_producer_queue::StreamProducerQueue; 16 | pub use stream_producer::StreamProducer; 17 | pub use stream_reader::StreamReader; 18 | -------------------------------------------------------------------------------- /diesel.toml: -------------------------------------------------------------------------------- 1 | # For documentation on how to configure this file, 2 | # see https://diesel.rs/guides/configuring-diesel-cli 3 | 4 | [print_schema] 5 | file = "crates/storage/src/schema.rs" 6 | custom_type_derives = ["diesel::query_builder::QueryId"] 7 | 8 | [migrations_directory] 9 | dir = "crates/storage/src/migrations" 10 | -------------------------------------------------------------------------------- /gemstone/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [profile.dev] 2 | # Disabling debug info speeds up builds a bunch, inspired by rust-analyzer. 3 | debug = 0 4 | 5 | [profile.release] 6 | # https://github.com/johnthagen/min-sized-rust 7 | strip = true 8 | codegen-units = 1 9 | lto = true 10 | opt-level = "z" 11 | -------------------------------------------------------------------------------- /gemstone/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | target/ 3 | generated/ 4 | xcuserdata/ 5 | jniLibs/ 6 | -------------------------------------------------------------------------------- /gemstone/README.md: -------------------------------------------------------------------------------- 1 | # Gemstone 2 | 3 | Gemstone is the essential cross platform library used by Gem Wallet clients (mainly iOS and Android). 4 | 5 | ## Build 6 | 7 | iOS 8 | 9 | ```bash 10 | just build-ios 11 | ``` 12 | 13 | Android 14 | 15 | ```bash 16 | just bindgen-kotlin && just build-android 17 | ``` 18 | 19 | you can check out `tests` folder to see how to use it. 20 | -------------------------------------------------------------------------------- /gemstone/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /gemstone/android/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("org.jetbrains.kotlin.android") version "2.0.21" apply false 3 | id("com.android.application") version "8.6.1" apply false 4 | id("com.github.willir.rust.cargo-ndk-android") version "0.3.4" apply false 5 | } 6 | -------------------------------------------------------------------------------- /gemstone/android/gemstone/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | src/main/java/uniffi 3 | -------------------------------------------------------------------------------- /gemstone/android/gemstone/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/android/gemstone/consumer-rules.pro -------------------------------------------------------------------------------- /gemstone/android/gemstone/src/androidTest/java/com/gemwallet/gemstone/GemstoneTest.kt: -------------------------------------------------------------------------------- 1 | package com.gemwallet.gemstone 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | 7 | import org.junit.Assert.* 8 | import uniffi.gemstone.* 9 | 10 | @RunWith(AndroidJUnit4::class) 11 | class GemstoneTest { 12 | 13 | init { 14 | System.loadLibrary("gemstone") 15 | } 16 | 17 | @Test 18 | fun testLibVersion() { 19 | assertTrue(libVersion().isNotEmpty()) 20 | } 21 | } -------------------------------------------------------------------------------- /gemstone/android/gemstone/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /gemstone/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gemstone/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Oct 09 16:14:27 JST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gemstone/android/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google { 4 | content { 5 | includeGroupByRegex("com\\.android.*") 6 | includeGroupByRegex("com\\.google.*") 7 | includeGroupByRegex("androidx.*") 8 | } 9 | } 10 | mavenCentral() 11 | gradlePluginPortal() 12 | } 13 | } 14 | dependencyResolutionManagement { 15 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 16 | repositories { 17 | google() 18 | mavenCentral() 19 | } 20 | } 21 | 22 | rootProject.name = "gemstone-android" 23 | include(":gemstone") 24 | -------------------------------------------------------------------------------- /gemstone/build.rs: -------------------------------------------------------------------------------- 1 | fn main() {} 2 | -------------------------------------------------------------------------------- /gemstone/src/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 6.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Gemstone", 7 | platforms: [ 8 | .iOS(.v17) 9 | ], 10 | products: [ 11 | .library( 12 | name: "Gemstone", 13 | targets: ["Gemstone", "GemstoneFFI"] 14 | ) 15 | ], 16 | dependencies: [ 17 | ], 18 | targets: [ 19 | .target( 20 | name: "Gemstone", 21 | dependencies: ["GemstoneFFI"], 22 | swiftSettings: [ 23 | .swiftLanguageMode(.v5) // TODO: - remove when GemstoneFFI will support swift6 fully 24 | ] 25 | ), 26 | .binaryTarget(name: "GemstoneFFI", path: "Sources/GemstoneFFI.xcframework") 27 | ] 28 | ) 29 | -------------------------------------------------------------------------------- /gemstone/src/config/evm_chain.rs: -------------------------------------------------------------------------------- 1 | use primitives::EVMChain; 2 | 3 | #[derive(uniffi::Record, Debug, Clone, PartialEq)] 4 | pub struct EVMChainConfig { 5 | pub min_priority_fee: u64, 6 | pub is_opstack: bool, 7 | pub rewards_percentiles: EVMHistoryRewardPercentiles, 8 | } 9 | 10 | #[derive(uniffi::Record, Debug, Clone, PartialEq)] 11 | pub struct EVMHistoryRewardPercentiles { 12 | pub slow: i64, 13 | pub normal: i64, 14 | pub fast: i64, 15 | } 16 | 17 | pub fn get_evm_chain_config(chain: EVMChain) -> EVMChainConfig { 18 | EVMChainConfig { 19 | min_priority_fee: chain.min_priority_fee(), 20 | is_opstack: chain.is_opstack(), 21 | rewards_percentiles: EVMHistoryRewardPercentiles { 22 | slow: 25, 23 | normal: 50, 24 | fast: 75, 25 | }, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /gemstone/src/config/node.rs: -------------------------------------------------------------------------------- 1 | use primitives::node_config::{Node, NodePriority}; 2 | 3 | // Sources: 4 | // https://chainlist.org 5 | 6 | #[uniffi::remote(Record)] 7 | pub struct Node { 8 | pub url: String, 9 | pub priority: NodePriority, 10 | } 11 | 12 | #[uniffi::remote(Enum)] 13 | pub enum NodePriority { 14 | High, 15 | Medium, 16 | Low, 17 | Inactive, 18 | } 19 | -------------------------------------------------------------------------------- /gemstone/src/config/wallet_connect.rs: -------------------------------------------------------------------------------- 1 | use primitives::{Chain, EVMChain}; 2 | 3 | #[derive(uniffi::Record, Debug, Clone, PartialEq)] 4 | pub struct WalletConnectConfig { 5 | pub chains: Vec, 6 | } 7 | 8 | pub fn get_wallet_connect_config() -> WalletConnectConfig { 9 | let chains: Vec = [vec![Chain::Solana], EVMChain::all().iter().map(|x| x.to_chain()).collect()].concat(); 10 | 11 | WalletConnectConfig { 12 | chains: chains.into_iter().map(|x| x.to_string()).collect(), 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gemstone/src/cosmos/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::GemstoneError; 2 | use gem_cosmos::converter::convert_cosmos_address; 3 | 4 | /// Exports functions 5 | #[uniffi::export] 6 | pub fn cosmos_convert_hrp(address: String, hrp: String) -> Result { 7 | convert_cosmos_address(&address, &hrp).map_err(GemstoneError::from) 8 | } 9 | -------------------------------------------------------------------------------- /gemstone/src/message/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod decoder; 2 | pub mod eip712; 3 | pub mod sign_type; 4 | -------------------------------------------------------------------------------- /gemstone/src/message/sign_type.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, uniffi::Enum)] 2 | pub enum SignDigestType { 3 | Sign, 4 | Eip191, 5 | Eip712, 6 | Base58, 7 | } 8 | 9 | #[derive(Debug, uniffi::Record)] 10 | pub struct SignMessage { 11 | pub sign_type: SignDigestType, 12 | pub data: Vec, 13 | } 14 | -------------------------------------------------------------------------------- /gemstone/src/network/mod.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | pub mod jsonrpc; 4 | pub mod mock; 5 | pub mod provider; 6 | pub mod target; 7 | pub use jsonrpc::*; 8 | pub use provider::*; 9 | pub use target::*; 10 | 11 | #[derive(Debug, Clone, uniffi::Error, thiserror::Error)] 12 | pub enum AlienError { 13 | #[error("Request is invalid: {msg}")] 14 | RequestError { msg: String }, 15 | #[error("Request error: {msg}")] 16 | ResponseError { msg: String }, 17 | } 18 | -------------------------------------------------------------------------------- /gemstone/src/network/provider.rs: -------------------------------------------------------------------------------- 1 | pub use super::{AlienError, AlienTarget}; 2 | use async_trait::async_trait; 3 | use primitives::Chain; 4 | use std::fmt::Debug; 5 | 6 | pub type Data = Vec; 7 | 8 | #[uniffi::export(with_foreign)] 9 | #[async_trait] 10 | pub trait AlienProvider: Send + Sync + Debug { 11 | async fn request(&self, target: AlienTarget) -> Result; 12 | async fn batch_request(&self, targets: Vec) -> Result, AlienError>; 13 | fn get_endpoint(&self, chain: Chain) -> Result; 14 | } 15 | -------------------------------------------------------------------------------- /gemstone/src/sui/gas_budget.rs: -------------------------------------------------------------------------------- 1 | use super::rpc::models::InspectGasUsed; 2 | use std::cmp::max; 3 | 4 | pub struct GasBudgetCalculator {} 5 | 6 | impl GasBudgetCalculator { 7 | pub fn gas_budget(gas_used: &InspectGasUsed) -> u64 { 8 | let computation_budget = gas_used.computation_cost; 9 | let budget = max(computation_budget, computation_budget + gas_used.storage_cost - gas_used.storage_rebate); 10 | budget * 120 / 100 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /gemstone/src/sui/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod jsonrpc; 3 | pub mod models; 4 | 5 | pub use client::SuiClient; 6 | pub use models::CoinAsset; 7 | -------------------------------------------------------------------------------- /gemstone/src/swapper/across/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod provider; 2 | pub use provider::Across; 3 | pub mod api; 4 | pub mod config_store; 5 | pub mod hubpool; 6 | 7 | const DEFAULT_FILL_TIMEOUT: u32 = 60 * 60 * 6; // 6 hours 8 | const DEFAULT_DEPOSIT_GAS_LIMIT: u64 = 180_000; // gwei 9 | const DEFAULT_FILL_GAS_LIMIT: u64 = 120_000; // gwei 10 | -------------------------------------------------------------------------------- /gemstone/src/swapper/approval/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod evm; 2 | pub mod tron; 3 | 4 | pub use evm::{check_approval_erc20, check_approval_permit2}; 5 | -------------------------------------------------------------------------------- /gemstone/src/swapper/approval/tron.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::U256; 2 | use std::sync::Arc; 3 | 4 | use crate::{ 5 | network::AlienProvider, 6 | swapper::{models::ApprovalType, ApprovalData, SwapperError}, 7 | tron::client::TronClient, 8 | }; 9 | 10 | pub async fn check_approval_tron( 11 | owner_address: &str, 12 | token_address: &str, 13 | spender_address: &str, 14 | amount: U256, 15 | provider: Arc, 16 | ) -> Result { 17 | let client = TronClient::new(provider.clone()); 18 | let allowance = client.get_token_allowance(owner_address, token_address, spender_address).await?; 19 | if allowance < amount { 20 | return Ok(ApprovalType::Approve(ApprovalData { 21 | token: token_address.to_string(), 22 | spender: spender_address.to_string(), 23 | value: amount.to_string(), 24 | })); 25 | } 26 | Ok(ApprovalType::None) 27 | } 28 | -------------------------------------------------------------------------------- /gemstone/src/swapper/cetus/api/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod models; 3 | 4 | pub use client::CetusClient; 5 | -------------------------------------------------------------------------------- /gemstone/src/swapper/cetus/mod.rs: -------------------------------------------------------------------------------- 1 | mod api; 2 | mod models; 3 | mod provider; 4 | mod tx_builder; 5 | 6 | pub use provider::Cetus; 7 | 8 | // https://github.com/CetusProtocol/cetus-clmm-sui-sdk/blob/main/src/config/mainnet.ts 9 | const CETUS_GLOBAL_CONFIG_ID: &str = "0xdaa46292632c3c4d8f31f23ea0f9b36a28ff3677e9684980e4438403a67a3d8f"; 10 | const CETUS_GLOBAL_CONFIG_SHARED_VERSION: u64 = 1574190; 11 | const CETUS_CLMM_PACKAGE_ID: &str = "0x1eabed72c53feb3805120a081dc15963c204dc8d091542592abaf7a35689b2fb"; 12 | const CETUS_ROUTER_PACKAGE_ID: &str = "0x3a5aa90ffa33d09100d7b6941ea1c0ffe6ab66e77062ddd26320c1b073aabb10"; 13 | 14 | const CETUS_MAINNET_PARTNER_ID: &str = "0x08b1875b6541c847f05ed71d04cbcfa66e4e8619bf3b8923b07c5b5409433366"; 15 | const CETUS_PARTNER_SHARED_VERSION: u64 = 507739678; 16 | #[allow(unused)] 17 | const CETUS_TESTNET_PARTNER_ID: &str = "0x0364d744bd811122bbfdfe11a153aed9e91a2b3a5d6be1eaa5b7f081ed174487"; 18 | -------------------------------------------------------------------------------- /gemstone/src/swapper/cetus/test/route_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "object_id": "0x51e883ba7c0b566a26cbc8a94cd33eb0abd418a77cc1e60ad22fd9b1f29cd2ab", 3 | "version": 509395278, 4 | "digest": "CBF9PWWjzzw1snQ4uzUZzFRahvkseJCGqbCU7b6CNcrG", 5 | "coin_a": "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC", 6 | "coin_b": "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI", 7 | "initial_shared_version": 376543995, 8 | "fee_rate": "0.0005" 9 | } -------------------------------------------------------------------------------- /gemstone/src/swapper/chainflip/broker/mod.rs: -------------------------------------------------------------------------------- 1 | mod client; 2 | pub mod model; 3 | 4 | pub use client::BrokerClient; 5 | pub use model::*; 6 | -------------------------------------------------------------------------------- /gemstone/src/swapper/chainflip/capitalize.rs: -------------------------------------------------------------------------------- 1 | pub fn capitalize_first_letter(s: &str) -> String { 2 | let mut chars = s.chars(); 3 | match chars.next() { 4 | None => String::new(), 5 | Some(first_char) => first_char.to_uppercase().collect::() + chars.as_str(), 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /gemstone/src/swapper/chainflip/client/mod.rs: -------------------------------------------------------------------------------- 1 | mod model; 2 | mod swap; 3 | 4 | pub use model::*; 5 | pub use swap::ChainflipClient; 6 | -------------------------------------------------------------------------------- /gemstone/src/swapper/chainflip/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod broker; 2 | pub mod capitalize; 3 | pub mod client; 4 | pub mod model; 5 | pub mod price; 6 | pub mod provider; 7 | pub mod seed; 8 | pub mod tx_builder; 9 | 10 | pub use model::*; 11 | pub use provider::ChainflipProvider; 12 | -------------------------------------------------------------------------------- /gemstone/src/swapper/chainflip/model.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use super::broker::DcaParameters; 4 | 5 | #[derive(Debug, Serialize, Deserialize, PartialEq)] 6 | pub struct ChainflipRouteData { 7 | pub boost_fee: Option, 8 | pub fee_bps: u32, 9 | pub estimated_price: String, 10 | pub dca_parameters: Option, 11 | } 12 | -------------------------------------------------------------------------------- /gemstone/src/swapper/chainflip/seed.rs: -------------------------------------------------------------------------------- 1 | use rand::Rng; 2 | use rand::RngCore; 3 | 4 | pub fn generate_random_seed(max_bytes: usize) -> Vec { 5 | if max_bytes == 0 || max_bytes > 32 { 6 | return vec![]; 7 | } 8 | 9 | let mut rng = rand::rng(); 10 | let num_bytes = rng.random_range(1..=max_bytes); 11 | 12 | let mut seed_bytes = vec![0u8; num_bytes]; 13 | rng.fill_bytes(&mut seed_bytes); 14 | 15 | seed_bytes 16 | } 17 | -------------------------------------------------------------------------------- /gemstone/src/swapper/custom_types.rs: -------------------------------------------------------------------------------- 1 | use primitives::{AssetId, Chain}; 2 | use std::str::FromStr; 3 | 4 | uniffi::custom_type!(Chain, String, { 5 | remote, 6 | lower: |s| s.to_string(), 7 | try_lift: |s| Chain::from_str(&s).map_err(|_| anyhow::anyhow!("Invalid Chain")), 8 | }); 9 | 10 | uniffi::custom_type!(AssetId, String, { 11 | remote, 12 | lower: |s| s.to_string(), 13 | try_lift: |s| AssetId::new(&s).ok_or(anyhow::anyhow!("Invalid AssetId")), 14 | }); 15 | -------------------------------------------------------------------------------- /gemstone/src/swapper/jupiter/mod.rs: -------------------------------------------------------------------------------- 1 | mod client; 2 | mod model; 3 | mod provider; 4 | mod token_account; 5 | pub use provider::Jupiter; 6 | 7 | pub const PROGRAM_ADDRESS: &str = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"; 8 | -------------------------------------------------------------------------------- /gemstone/src/swapper/orca/fee_tiers.rs: -------------------------------------------------------------------------------- 1 | use super::models::FeeTier; 2 | 3 | #[allow(unused)] 4 | pub fn get_all_fee_tiers() -> Vec { 5 | let fee_tiers = vec![ 6 | FeeTier::new(1, 100), 7 | FeeTier::new(2, 200), 8 | FeeTier::new(4, 400), 9 | FeeTier::new(8, 500), 10 | FeeTier::new(16, 1600), 11 | FeeTier::new(64, 3000), 12 | FeeTier::new(96, 6500), 13 | FeeTier::new(128, 10000), 14 | FeeTier::new(32896, 10000), 15 | FeeTier::new(256, 20000), 16 | ]; 17 | fee_tiers 18 | } 19 | 20 | pub fn get_splash_pool_fee_tiers() -> FeeTier { 21 | FeeTier::new(32896, 10000) 22 | } 23 | -------------------------------------------------------------------------------- /gemstone/src/swapper/orca/mod.rs: -------------------------------------------------------------------------------- 1 | mod fee_tiers; 2 | mod jsonrpc; 3 | mod models; 4 | mod provider; 5 | mod whirlpool; 6 | pub use provider::*; 7 | 8 | const WHIRLPOOL_PROGRAM: &str = "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc"; 9 | const WHIRLPOOL_CONFIG: &str = "2LecshUwdy9xi7meFgHtFJQNSKk4KdTrcpvaB56dP2NQ"; 10 | const FEE_TIER_DISCRIMINATOR: &str = "AR8t9QRDQXa"; 11 | -------------------------------------------------------------------------------- /gemstone/src/swapper/orca/test/tick_array_request.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": 1, 4 | "method": "getMultipleAccounts", 5 | "params": [ 6 | [ 7 | "ErdzvuYUjAkvo82StCX1AinozCW6XHNZvKPw3Kzi6XeZ", 8 | "Hv9aCrHkyJQFdHdPyLiuj4d3E3H833jzK1VBpEh1QjpP", 9 | "5Fainb1wjVLUawSMqbirJNek47eBAPDyivaMZFbMZYFF", 10 | "A8DJW3RDjYZGtgU7B86jiFJbzEGUygGszWVJxS1Dn2zG", 11 | "7cjaXfrUGEB78rzmLJQhr1myjju75rr9raYyeh4XT7Ya" 12 | ], 13 | { 14 | "commitment": "confirmed", 15 | "encoding": "base64" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /gemstone/src/swapper/pancakeswap_aptos/model.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | pub const PANCAKE_SWAP_APTOS_ADDRESS: &str = "0xc7efb4076dbe143cbcd98cfaaa929ecfc8f299203dfff63b95ccb6bfe19850fa"; 4 | 5 | #[derive(Debug, Clone, Serialize, Deserialize)] 6 | pub struct TokenPairReserve { 7 | pub reserve_x: String, 8 | pub reserve_y: String, 9 | } 10 | 11 | #[derive(Debug, Clone, Serialize, Deserialize)] 12 | pub struct RouteData { 13 | pub assets: Vec, 14 | pub min_value: String, 15 | } 16 | -------------------------------------------------------------------------------- /gemstone/src/swapper/proxy/mayan/explorer.rs: -------------------------------------------------------------------------------- 1 | use super::model::MayanTransactionResult; 2 | use crate::{ 3 | network::{AlienProvider, AlienTarget}, 4 | swapper::SwapperError, 5 | }; 6 | use std::sync::Arc; 7 | 8 | pub struct MayanExplorer { 9 | provider: Arc, 10 | } 11 | 12 | impl MayanExplorer { 13 | pub fn new(provider: Arc) -> Self { 14 | Self { provider } 15 | } 16 | 17 | pub async fn get_transaction_status(&self, tx_hash: &str) -> Result { 18 | let url = format!("https://explorer-api.mayan.finance/v3/swap/trx/{}", tx_hash); 19 | let target = AlienTarget::get(&url); 20 | let response = self.provider.request(target).await?; 21 | let result: MayanTransactionResult = serde_json::from_slice(&response).map_err(SwapperError::from)?; 22 | 23 | Ok(result) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /gemstone/src/swapper/proxy/mayan/mod.rs: -------------------------------------------------------------------------------- 1 | mod explorer; 2 | mod model; 3 | 4 | pub use explorer::MayanExplorer; 5 | pub use model::{MayanClientStatus, MayanTransactionResult}; 6 | -------------------------------------------------------------------------------- /gemstone/src/swapper/proxy/mod.rs: -------------------------------------------------------------------------------- 1 | mod client; 2 | 3 | pub mod mayan; 4 | pub mod provider; 5 | pub mod symbiosis; 6 | 7 | pub mod provider_factory; 8 | pub use provider_factory::*; 9 | -------------------------------------------------------------------------------- /gemstone/src/swapper/proxy/symbiosis/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod model; 2 | -------------------------------------------------------------------------------- /gemstone/src/swapper/proxy/symbiosis/model.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, Serialize, Deserialize)] 4 | #[serde(rename_all = "camelCase")] 5 | pub struct SymbiosisTransactionData { 6 | pub chain_id: u64, 7 | pub data: String, 8 | pub to: String, 9 | pub value: Option, 10 | pub function_selector: String, 11 | pub fee_limit: Option, 12 | pub from: Option, 13 | } 14 | -------------------------------------------------------------------------------- /gemstone/src/swapper/uniswap/deadline.rs: -------------------------------------------------------------------------------- 1 | use std::time::{SystemTime, UNIX_EPOCH}; 2 | 3 | const DEFAULT_DEADLINE: u64 = 3600; 4 | 5 | pub fn get_sig_deadline() -> u64 { 6 | let now = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs(); 7 | now + DEFAULT_DEADLINE 8 | } 9 | -------------------------------------------------------------------------------- /gemstone/src/swapper/uniswap/mod.rs: -------------------------------------------------------------------------------- 1 | mod deadline; 2 | mod fee_token; 3 | mod quote_result; 4 | mod swap_route; 5 | 6 | pub mod universal_router; 7 | pub mod v3; 8 | pub mod v4; 9 | -------------------------------------------------------------------------------- /gemstone/src/swapper/uniswap/universal_router/mod.rs: -------------------------------------------------------------------------------- 1 | mod oku; 2 | mod pancakeswap; 3 | mod reservoir; 4 | mod uniswap_v3; 5 | mod wagmi; 6 | 7 | use crate::swapper::uniswap::{v3::UniswapV3, v4::UniswapV4}; 8 | 9 | pub fn new_uniswap_v3() -> UniswapV3 { 10 | UniswapV3::new(Box::new(uniswap_v3::UniswapUniversalRouter::default())) 11 | } 12 | 13 | pub fn new_pancakeswap() -> UniswapV3 { 14 | UniswapV3::new(Box::new(pancakeswap::PancakeSwapUniversalRouter::default())) 15 | } 16 | 17 | pub fn new_oku() -> UniswapV3 { 18 | UniswapV3::new(Box::new(oku::OkuUniversalRouter::default())) 19 | } 20 | 21 | pub fn new_wagmi() -> UniswapV3 { 22 | UniswapV3::new(Box::new(wagmi::WagmiUniversalRouter::default())) 23 | } 24 | 25 | pub fn new_reservoir() -> UniswapV3 { 26 | UniswapV3::new(Box::new(reservoir::ReservoirUniversalRouter::default())) 27 | } 28 | 29 | pub fn new_uniswap_v4() -> UniswapV4 { 30 | UniswapV4::default() 31 | } 32 | -------------------------------------------------------------------------------- /gemstone/src/swapper/uniswap/v3/mod.rs: -------------------------------------------------------------------------------- 1 | mod commands; 2 | mod path; 3 | mod quoter_v2; 4 | 5 | pub mod provider; 6 | pub use provider::UniswapV3; 7 | 8 | use crate::swapper::SwapProviderType; 9 | use gem_evm::uniswap::{deployment::v3::V3Deployment, FeeTier}; 10 | use primitives::Chain; 11 | use std::fmt::Debug; 12 | 13 | pub trait UniversalRouterProvider: Send + Sync + Debug { 14 | fn provider(&self) -> &SwapProviderType; 15 | fn get_tiers(&self) -> Vec; 16 | fn get_deployment_by_chain(&self, chain: &Chain) -> Option; 17 | } 18 | 19 | const DEFAULT_SWAP_GAS_LIMIT: u64 = 500_000; // gwei 20 | -------------------------------------------------------------------------------- /gemstone/src/swapper/uniswap/v4/mod.rs: -------------------------------------------------------------------------------- 1 | mod commands; 2 | mod path; 3 | mod quoter; 4 | 5 | pub mod provider; 6 | pub use provider::UniswapV4; 7 | 8 | const DEFAULT_SWAP_GAS_LIMIT: u64 = 300_000; // gwei 9 | -------------------------------------------------------------------------------- /gemstone/src/ton/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::GemstoneError; 2 | 3 | pub mod address; 4 | pub mod jetton; 5 | 6 | /// Exports functions 7 | #[uniffi::export] 8 | pub fn ton_encode_get_wallet_address(address: String) -> Result { 9 | jetton::encode_get_wallet_address_slice(&address).map_err(GemstoneError::from) 10 | } 11 | 12 | #[uniffi::export] 13 | pub fn ton_decode_jetton_address(base64_data: String, len: u64) -> Result { 14 | jetton::decode_data_to_address(&base64_data, len).map_err(GemstoneError::from) 15 | } 16 | 17 | #[uniffi::export] 18 | pub fn ton_hex_to_base64_address(hex_str: String) -> Result { 19 | address::hex_to_base64_address(hex_str).map_err(GemstoneError::from) 20 | } 21 | 22 | #[uniffi::export] 23 | pub fn ton_base64_to_hex_address(base64_str: String) -> Result { 24 | address::base64_to_hex_address(base64_str).map_err(GemstoneError::from) 25 | } 26 | -------------------------------------------------------------------------------- /gemstone/src/tron/model.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | #[derive(Debug, Deserialize)] 4 | pub struct TronNodeResponse { 5 | pub result: TronNodeResult, 6 | pub energy_used: u64, 7 | pub energy_penalty: u64, 8 | pub constant_result: Vec, 9 | } 10 | 11 | #[derive(Debug, Deserialize)] 12 | #[serde(untagged)] 13 | pub enum TronNodeResult { 14 | Result(TronResult), 15 | Error(TronErrorResult), 16 | } 17 | 18 | #[derive(Deserialize, Debug)] 19 | pub struct TronResult { 20 | pub result: bool, 21 | } 22 | 23 | #[derive(Deserialize, Debug)] 24 | pub struct TronErrorResult { 25 | pub code: String, 26 | pub message: String, 27 | } 28 | -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/java/com/example/gemtest/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.example.gemtest.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple80 = Color(0xFFD0BCFF) 6 | val PurpleGrey80 = Color(0xFFCCC2DC) 7 | val Pink80 = Color(0xFFEFB8C8) 8 | 9 | val Purple40 = Color(0xFF6650a4) 10 | val PurpleGrey40 = Color(0xFF625b71) 11 | val Pink40 = Color(0xFF7D5260) -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gemwalletcom/core/91aa4b6afb4e7edaf8a67f0a26cf14396e869d95/gemstone/tests/android/GemTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | GemTest 3 | -------------------------------------------------------------------------------- /gemstone/tests/android/GemTest/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |